Home / Alt manpages / proc_pid_mem(5)

  • proc_pid_mem(5)
  • File format
  • linux

Read a Process's Memory Safely through /proc/pid/mem

You will read bytes from a buffer owned by the current Python process through /proc/self/mem, then check the access boundary that applies to a different PID. Allow about ten minutes. The example needs Linux, Python 3 and an ordinary shell; it does not need root and it leaves no persistent change behind.

1. Confirm the local documentation and package version

The installed manual page describes /proc/pid/mem as a file that can be accessed with open(2), read(2) and lseek(2). Access is controlled by a PTRACE_MODE_ATTACH_FSCREDS check, with the details documented by ptrace(2). On this machine the file comes from Linux man-pages 6.7, package version 6.7-2. This identifies the documentation installed here, not the version of the running kernel.

$ command -v python3
/usr/bin/python3
$ dpkg-query -W manpages
manpages 6.7-2
$ man 5 proc_pid_mem

Checkpoint: the relevant interface is a pseudo-file, not a normal disk file. There is no useful file size to inspect, and copying it as if it were an ordinary file is the wrong model.

2. Inspect the entry without reading memory

Start by checking the directory entry for your own process. Substitute a numeric PID if you want to inspect another process's entry. This command only asks the kernel for metadata:

$ PID=$$
$ stat "/proc/$PID/mem"
  File: /proc/12345/mem
  Size: 0          Blocks: 0          IO Block: 1024   regular empty file
Device: 0,20       Inode: 12345       Links: 1
Access: (0600/-rw-------)  Uid: ( 1000/   user)   Gid: ( 1000/   user)

The PID, inode, device and ownership vary. The apparent size of zero does not mean that the process has no memory. It is a procfs interface whose reads are interpreted by the kernel. A mode bit or a successful stat call also does not prove that a later read will pass the ptrace access check.

Do not use dd with a guessed large offset against another process. An address is meaningful only in the target process, mappings can change while it runs, and a read can expose secrets such as tokens or private data.

3. Read a known buffer from the same process

The safest reproducible test makes the reader, the memory owner and the address lookup one short-lived process. The buffer contains a harmless marker. ctypes.addressof supplies its address, and os.pread reads from that offset without changing the file position.

$ python3 - <<'PY'
import ctypes
import os

value = ctypes.create_string_buffer(b'proc-pid-mem-ok')
address = ctypes.addressof(value)

with open('/proc/self/mem', 'rb', buffering=0) as mem:
    got = os.pread(mem.fileno(), len(value.value), address)

print('address:', hex(address))
print('read:', got.decode())
PY
address: 0x799159280580
read: proc-pid-mem-ok

The hexadecimal address is expected to change between runs. The useful result is the marker on the final line. A short read is still a result, not permission to guess a new offset: compare len(got) with the requested length before treating data as complete.

Checkpoint: if this self-read succeeds, you have verified that the local kernel and Python process can open and read the interface for the process that owns the memory. You have not established access to an unrelated process.

4. Check a target process before attempting a read

For a real debugging or forensics task, first identify the exact target and its owner. The following commands do not read its memory:

$ TARGET_PID=12345
$ ps -o pid,user,comm= -p "$TARGET_PID"
    PID USER     COMMAND
  12345 user     example
$ stat "/proc/$TARGET_PID/mem"

Use an explicit PID, not a name match that can select the wrong process. Recheck the PID immediately before opening the file because process IDs can be reused after a process exits. If the target is a service, its service account, user namespace, dumpability state and security policy can all affect the ptrace check.

Do not add sudo just because a read failed. The manual specifies a ptrace access decision, not a simple owner check. A privileged process may still be constrained by namespaces, security modules or other kernel policy. Record the exact error from the program performing the read and investigate that boundary first.

5. Keep reads bounded and read-only

The documented interface permits reads and seeking, but that does not make arbitrary memory extraction safe. Read only a known range from a process you are authorised to examine. Prefer a debugger or a purpose-built diagnostic tool when you need mappings, thread coordination, symbol handling or repeatable snapshots.

Never turn an investigation into a write experiment. Opening /proc/pid/mem with write access can alter the target process if the access checks and file operations permit it. That can corrupt application state, bypass program logic, or expose credentials to an attacker. The example above explicitly uses 'rb', reads a fixed number of bytes and lets the process exit normally.

If you must collect bytes for an approved investigation, save them to a destination with controlled permissions, minimise the range, and remove the copy using your organisation's approved retention process after analysis. Do not paste raw memory into tickets or shell history. Memory contents are often sensitive even when the process is not a security tool.

6. Diagnose the common failures

FileNotFoundError usually means the PID disappeared or the path was formed incorrectly. Confirm that the target is still present, then repeat the identity check. PermissionError means the ptrace access decision rejected the operation; check credentials, namespaces and the target's ownership rather than assuming that the proc entry's mode text is decisive.

An OSError during pread can also mean that the offset is not a readable mapping, that the requested range crosses an unmapped boundary, or that the process changed its mappings. Do not retry with random offsets. For your own test, keep the buffer alive until after the read and use the address returned by that same process.

There is nothing to undo after the example: it reads a temporary process's own buffer and makes no persistent configuration change. If you created a diagnostic dump elsewhere, preserve or remove it according to its data-handling policy rather than using a blind rm command.

Done means

  • You confirmed the installed proc_pid_mem(5) documentation and man-pages package version.
  • You distinguished procfs metadata from the bytes exposed by a memory read.
  • You reproduced a bounded read from a known buffer in the same process.
  • You understand that access is governed by PTRACE_MODE_ATTACH_FSCREDS, not just visible Unix mode bits.
  • You will use an exact, authorised target and avoid unbounded reads, arbitrary offsets and writes.