A Linux kernel module for reading selected virtual memory ranges from a
process. It exposes /dev/aeon_memdump as a mode 0600 misc device and
requires CAP_SYS_ADMIN for opening the device, selecting a range, and
reading memory.
This is a behavioral reconstruction from an AArch64 module's disassembly, relocations, and DWARF type information. The repository contains readable module source, its userspace ABI, a range reader, and a self-test that reads known contents from a child process it creates.
Use the kernel source, configuration, generated headers, Module.symvers,
and toolchain for your target kernel. Kernel release numbers alone do not
establish module compatibility. In particular, architecture and security
configuration options can change structure layouts used by inline helpers.
For the local kernel:
make
make tools selftestFor an AArch64 target with a prepared kernel build tree:
make KDIR=/path/to/kernel/build ARCH=arm64 LLVM=1 LLVM_IAS=1 \
CROSS_COMPILE=aarch64-linux-gnu-
make tools selftest USER_CC=aarch64-linux-gnu-gcc USER_LDFLAGS=-staticmodules_prepare generates headers but does not produce a complete
Module.symvers. When the target uses CONFIG_MODVERSIONS, obtain that
file from its kernel build. The module inherits the kernel build system's
compiler and configuration settings; adjust them to match the target.
Load the module with sufficient privileges:
sudo insmod aeon_memdump.koRead a range from a process you control. The PID is decimal; the address and length are hexadecimal:
sudo ./bin/aeon_read_range PID HEX_ADDRESS HEX_SIZE > dump.binThe reader writes only memory bytes to stdout and sends status to stderr. It uses the Aeon device directly and does not fall back to another memory access mechanism.
Unload when finished:
sudo rmmod aeon_memdumpOn Android, push the module and the statically linked tools with adb and
run them from a root shell on the target. Match the module to that device's
kernel build rather than the host kernel.
Include aeon_memdump_uapi.h in userspace code. Select a range using
ioctl(fd, AEON_SET_RANGE, &range):
struct aeon_memdump_range {
__u32 pid;
__u32 flags;
__u64 start;
__u64 len;
};The request is 24 bytes and the ioctl command is 0x40184101
(_IOW('A', 1, struct aeon_memdump_range)). flags is currently ignored;
callers should initialize it to zero. A successful ioctl resets the
per-file read position.
Each read returns at most 64 KiB using
access_process_vm(..., FOLL_FORCE). Continue reading until the requested
length has been consumed. Reaching the end of a range returns zero, as
does reading before selecting a range. Seeking does not reposition the
range reader; use the ioctl to select a new range.
| Condition | Result |
|---|---|
Missing CAP_SYS_ADMIN |
EPERM |
| Unknown ioctl | ENOTTY |
| Zero PID, zero length, or address overflow | EINVAL |
| Target PID does not exist | ESRCH |
| Invalid userspace request or destination buffer | EFAULT |
| No bytes readable from the selected address | EIO |
| Buffer allocation fails | ENOMEM |
The module has no separate 32-bit compatibility ioctl handler. Its validated target is AArch64.
With the module loaded:
sudo ./bin/aeon_selftestThe self-test creates its own target process and checks deterministic memory contents, reads spanning the 64 KiB limit, EOF, range reset, invalid arguments, destination faults, exited processes, and capability enforcement. All 21 checks passed on an AArch64 Linux 5.10.160 target. The source also compiled against Linux 7.2.6 host headers; that compile is not a runtime validation of other kernels.
This reconstruction preserves the original locking behavior. It snapshots the selected range under a mutex, releases the mutex during the memory read, then updates the position under the mutex. Serialize operations on each open file description: simultaneous reads or range changes can race.
Each read looks up the PID again. The interface does not pin a process for the duration of a multi-read capture or guard against PID reuse. Captures are sequential observations of a running process, not atomic snapshots.
GPL-2.0-only. See LICENSE.