Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading living process memory without interrupting it

Tags:

linux

memory

I would like to explore the memory of a living process, and when I do so, the process must not get disturbed - so attaching gdb to the process (which would stop it) is not an option. Therefore I would like to get this info from /proc/kcore (if you know of another way to do this please let me know). So I made a little experiment. I created a file called TEST with only "EXTRATESTEXTRA" inside. Then I opened it with less

$ less TEST 

I got the PID of this process with

$ ps aux | grep TEST user    7785  0.0  0.0  17944   992 pts/8    S+   16:15   0:00 less TEST user    7798  0.0  0.0  13584   904 pts/9    S+   16:16   0:00 grep TEST 

And then I used this script to create a dump of all files :

#!/bin/bash grep rw-p /proc/$1/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done 

(I found it on this site https://serverfault.com/questions/173999/dump-a-linux-processs-memory-to-file)

$ sudo ./dump_all_pid_memory.sh 7785 

After this, I looked for "TRATESTEX" in all dumped files :

$ grep -a -o -e '...TRATESTEX...' ./*.dump ./7785-00624000-00628000.dump:HEXTRATESTEXTRA ./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA ./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA 

So I concluded that there must be an occurance of this string somewhere between 0x00624000 and 0x00628000 . Therefore I converted the offsets into decimal numbers and used dd to get the memory from /proc/kcore :

$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1 

To my surprise, the file y.txt was full of zeros (I didn't find the string I was looking for in it).

As a bonus surprise, I ran a simmilar test at the same time with a different test file and found that the other test string i was using (both processes with less were running at the same time) should be found at the same location (the dumping and greping gave the same offset). So there must be something I don't understand clearly.

  • Isn't the /proc/pid/maps supposed to show the offset of the memory (i.e. : if it would say "XXX" is at offset 0x10, another program could not be using the same offset am I right? - this is the source of my second surprise)

  • How can I read /proc/kmap to get the memory that belongs to a process which's pid I know ?

like image 695
hmhmhmmm Avatar asked Oct 19 '12 15:10

hmhmhmmm


People also ask

How do you inspect process memory?

You can check memory of a process or a set of processes in human readable format (in KB or kilobytes) with pmap command. All you need is the PID of the processes you want to check memory usage of. As you can see, the total memory used by the process 917 is 516104 KB or kilobytes.

Which command is used to check the memory status?

Entering cat /proc/meminfo in your terminal opens the /proc/meminfo file. This is a virtual file that reports the amount of available and used memory. It contains real-time information about the system's memory usage as well as the buffers and shared memory used by the kernel.

How to check the memory in unix?

To get some quick memory information on a Linux system, you can also use the meminfo command. Looking at the meminfo file, we can see how much memory is installed as well as how much is free.


Video Answer


2 Answers

If you have root access and are on a linux system, you can use the following linux script (adapted from Gilles' excellent unix.stackexchange.com answer and the answer originally given in the question above but including SyntaxErrors and not being pythonic):

#!/usr/bin/env python  import re import sys  def print_memory_of_pid(pid, only_writable=True):     """      Run as root, take an integer PID and return the contents of memory to STDOUT     """     memory_permissions = 'rw' if only_writable else 'r-'     sys.stderr.write("PID = %d" % pid)     with open("/proc/%d/maps" % pid, 'r') as maps_file:         with open("/proc/%d/mem" % pid, 'r', 0) as mem_file:             for line in maps_file.readlines():  # for each mapped region                 m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r][-w])', line)                 if m.group(3) == memory_permissions:                      sys.stderr.write("\nOK : \n" + line+"\n")                     start = int(m.group(1), 16)                     if start > 0xFFFFFFFFFFFF:                         continue                     end = int(m.group(2), 16)                     sys.stderr.write( "start = " + str(start) + "\n")                     mem_file.seek(start)  # seek to region start                     chunk = mem_file.read(end - start)  # read region contents                     print chunk,  # dump contents to standard output                 else:                     sys.stderr.write("\nPASS : \n" + line+"\n")  if __name__ == '__main__': # Execute this code when run from the commandline.     try:         assert len(sys.argv) == 2, "Provide exactly 1 PID (process ID)"         pid = int(sys.argv[1])         print_memory_of_pid(pid)     except (AssertionError, ValueError) as e:         print "Please provide 1 PID as a commandline argument."         print "You entered: %s" % ' '.join(sys.argv)         raise e 

If you save this as write_mem.py, you can run this (with python2.6 or 2.7) or early in python2.5 (if you add from __future__ import with_statement) as:

sudo python write_mem.py 1234 > pid1234_memory_dump 

to dump pid1234 memory to the file pid1234_memory_dump.

like image 171
dr jimbob Avatar answered Oct 06 '22 05:10

dr jimbob


For process 1234 you can get its memory map by reading sequentially /proc/1234/maps (a textual pseudo-file) and read the virtual memory by e.g. read(2)-ing or mmap(2)-ing appropriate segments of the /proc/1234/mem sparse pseudo-file.

However, I believe you cannot avoid some kind of synchronization (perhaps with ptrace(2), as gdb does), since the process 1234 can (and does) alter its address space at any time (with mmap & related syscalls).

The situation is different if the monitored process 1234 is not arbitrary, but if you could improve it to communicate somehow with the monitoring process.

I'm not sure to understand why do you ask this. And gdb is able to watch some location without stopping the process.

like image 33
Basile Starynkevitch Avatar answered Oct 06 '22 05:10

Basile Starynkevitch