Skip to content

Commit b764375

Browse files
siddheshtorvalds
authored andcommitted
procfs: mark thread stack correctly in proc/<pid>/maps
Stack for a new thread is mapped by userspace code and passed via sys_clone. This memory is currently seen as anonymous in /proc/<pid>/maps, which makes it difficult to ascertain which mappings are being used for thread stacks. This patch uses the individual task stack pointers to determine which vmas are actually thread stacks. For a multithreaded program like the following: #include <pthread.h> void *thread_main(void *foo) { while(1); } int main() { pthread_t t; pthread_create(&t, NULL, thread_main, NULL); pthread_join(t, NULL); } proc/PID/maps looks like the following: 00400000-00401000 r-xp 00000000 fd:0a 3671804 /home/siddhesh/a.out 00600000-00601000 rw-p 00000000 fd:0a 3671804 /home/siddhesh/a.out 019ef000-01a10000 rw-p 00000000 00:00 0 [heap] 7f8a44491000-7f8a44492000 ---p 00000000 00:00 0 7f8a44492000-7f8a44c92000 rw-p 00000000 00:00 0 7f8a44c92000-7f8a44e3d000 r-xp 00000000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a44e3d000-7f8a4503d000 ---p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a4503d000-7f8a45041000 r--p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45041000-7f8a45043000 rw-p 001af000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45043000-7f8a45048000 rw-p 00000000 00:00 0 7f8a45048000-7f8a4505f000 r-xp 00000000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4505f000-7f8a4525e000 ---p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525e000-7f8a4525f000 r--p 00016000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525f000-7f8a45260000 rw-p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a45260000-7f8a45264000 rw-p 00000000 00:00 0 7f8a45264000-7f8a45286000 r-xp 00000000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45457000-7f8a4545a000 rw-p 00000000 00:00 0 7f8a45484000-7f8a45485000 rw-p 00000000 00:00 0 7f8a45485000-7f8a45486000 r--p 00021000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45486000-7f8a45487000 rw-p 00022000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45487000-7f8a45488000 rw-p 00000000 00:00 0 7fff6273b000-7fff6275c000 rw-p 00000000 00:00 0 [stack] 7fff627ff000-7fff62800000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Here, one could guess that 7f8a44492000-7f8a44c92000 is a stack since the earlier vma that has no permissions (7f8a44e3d000-7f8a4503d000) but that is not always a reliable way to find out which vma is a thread stack. Also, /proc/PID/maps and /proc/PID/task/TID/maps has the same content. With this patch in place, /proc/PID/task/TID/maps are treated as 'maps as the task would see it' and hence, only the vma that that task uses as stack is marked as [stack]. All other 'stack' vmas are marked as anonymous memory. /proc/PID/maps acts as a thread group level view, where all thread stack vmas are marked as [stack:TID] where TID is the process ID of the task that uses that vma as stack, while the process stack is marked as [stack]. So /proc/PID/maps will look like this: 00400000-00401000 r-xp 00000000 fd:0a 3671804 /home/siddhesh/a.out 00600000-00601000 rw-p 00000000 fd:0a 3671804 /home/siddhesh/a.out 019ef000-01a10000 rw-p 00000000 00:00 0 [heap] 7f8a44491000-7f8a44492000 ---p 00000000 00:00 0 7f8a44492000-7f8a44c92000 rw-p 00000000 00:00 0 [stack:1442] 7f8a44c92000-7f8a44e3d000 r-xp 00000000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a44e3d000-7f8a4503d000 ---p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a4503d000-7f8a45041000 r--p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45041000-7f8a45043000 rw-p 001af000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45043000-7f8a45048000 rw-p 00000000 00:00 0 7f8a45048000-7f8a4505f000 r-xp 00000000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4505f000-7f8a4525e000 ---p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525e000-7f8a4525f000 r--p 00016000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525f000-7f8a45260000 rw-p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a45260000-7f8a45264000 rw-p 00000000 00:00 0 7f8a45264000-7f8a45286000 r-xp 00000000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45457000-7f8a4545a000 rw-p 00000000 00:00 0 7f8a45484000-7f8a45485000 rw-p 00000000 00:00 0 7f8a45485000-7f8a45486000 r--p 00021000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45486000-7f8a45487000 rw-p 00022000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45487000-7f8a45488000 rw-p 00000000 00:00 0 7fff6273b000-7fff6275c000 rw-p 00000000 00:00 0 [stack] 7fff627ff000-7fff62800000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Thus marking all vmas that are used as stacks by the threads in the thread group along with the process stack. The task level maps will however like this: 00400000-00401000 r-xp 00000000 fd:0a 3671804 /home/siddhesh/a.out 00600000-00601000 rw-p 00000000 fd:0a 3671804 /home/siddhesh/a.out 019ef000-01a10000 rw-p 00000000 00:00 0 [heap] 7f8a44491000-7f8a44492000 ---p 00000000 00:00 0 7f8a44492000-7f8a44c92000 rw-p 00000000 00:00 0 [stack] 7f8a44c92000-7f8a44e3d000 r-xp 00000000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a44e3d000-7f8a4503d000 ---p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a4503d000-7f8a45041000 r--p 001ab000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45041000-7f8a45043000 rw-p 001af000 fd:00 2097482 /lib64/libc-2.14.90.so 7f8a45043000-7f8a45048000 rw-p 00000000 00:00 0 7f8a45048000-7f8a4505f000 r-xp 00000000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4505f000-7f8a4525e000 ---p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525e000-7f8a4525f000 r--p 00016000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a4525f000-7f8a45260000 rw-p 00017000 fd:00 2099938 /lib64/libpthread-2.14.90.so 7f8a45260000-7f8a45264000 rw-p 00000000 00:00 0 7f8a45264000-7f8a45286000 r-xp 00000000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45457000-7f8a4545a000 rw-p 00000000 00:00 0 7f8a45484000-7f8a45485000 rw-p 00000000 00:00 0 7f8a45485000-7f8a45486000 r--p 00021000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45486000-7f8a45487000 rw-p 00022000 fd:00 2097348 /lib64/ld-2.14.90.so 7f8a45487000-7f8a45488000 rw-p 00000000 00:00 0 7fff6273b000-7fff6275c000 rw-p 00000000 00:00 0 7fff627ff000-7fff62800000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] where only the vma that is being used as a stack by *that* task is marked as [stack]. Analogous changes have been made to /proc/PID/smaps, /proc/PID/numa_maps, /proc/PID/task/TID/smaps and /proc/PID/task/TID/numa_maps. Relevant snippets from smaps and numa_maps: [siddhesh@localhost ~ ]$ pgrep a.out 1441 [siddhesh@localhost ~ ]$ cat /proc/1441/smaps | grep "\[stack" 7f8a44492000-7f8a44c92000 rw-p 00000000 00:00 0 [stack:1442] 7fff6273b000-7fff6275c000 rw-p 00000000 00:00 0 [stack] [siddhesh@localhost ~ ]$ cat /proc/1441/task/1442/smaps | grep "\[stack" 7f8a44492000-7f8a44c92000 rw-p 00000000 00:00 0 [stack] [siddhesh@localhost ~ ]$ cat /proc/1441/task/1441/smaps | grep "\[stack" 7fff6273b000-7fff6275c000 rw-p 00000000 00:00 0 [stack] [siddhesh@localhost ~ ]$ cat /proc/1441/numa_maps | grep "stack" 7f8a44492000 default stack:1442 anon=2 dirty=2 N0=2 7fff6273a000 default stack anon=3 dirty=3 N0=3 [siddhesh@localhost ~ ]$ cat /proc/1441/task/1442/numa_maps | grep "stack" 7f8a44492000 default stack anon=2 dirty=2 N0=2 [siddhesh@localhost ~ ]$ cat /proc/1441/task/1441/numa_maps | grep "stack" 7fff6273a000 default stack anon=3 dirty=3 N0=3 [akpm@linux-foundation.org: checkpatch fixes] [akpm@linux-foundation.org: fix build] Signed-off-by: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com> Cc: KOSAKI Motohiro <kosaki.motohiro@gmail.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Jamie Lokier <jamie@shareable.org> Cc: Mike Frysinger <vapier@gentoo.org> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Matt Mackall <mpm@selenic.com> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 9e81130 commit b764375

File tree

7 files changed

+313
-63
lines changed

7 files changed

+313
-63
lines changed

Documentation/filesystems/proc.txt

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ Table 1-4: Contents of the stat files (as of 2.6.30-rc7)
290290
rsslim current limit in bytes on the rss
291291
start_code address above which program text can run
292292
end_code address below which program text can run
293-
start_stack address of the start of the stack
293+
start_stack address of the start of the main process stack
294294
esp current value of ESP
295295
eip current value of EIP
296296
pending bitmap of pending signals
@@ -325,7 +325,7 @@ address perms offset dev inode pathname
325325
a7cb1000-a7cb2000 ---p 00000000 00:00 0
326326
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
327327
a7eb2000-a7eb3000 ---p 00000000 00:00 0
328-
a7eb3000-a7ed5000 rw-p 00000000 00:00 0
328+
a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001]
329329
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
330330
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
331331
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
@@ -357,11 +357,39 @@ is not associated with a file:
357357

358358
[heap] = the heap of the program
359359
[stack] = the stack of the main process
360+
[stack:1001] = the stack of the thread with tid 1001
360361
[vdso] = the "virtual dynamic shared object",
361362
the kernel system call handler
362363

363364
or if empty, the mapping is anonymous.
364365

366+
The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
367+
of the individual tasks of a process. In this file you will see a mapping marked
368+
as [stack] if that task sees it as a stack. This is a key difference from the
369+
content of /proc/PID/maps, where you will see all mappings that are being used
370+
as stack by all of those tasks. Hence, for the example above, the task-level
371+
map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
372+
373+
08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
374+
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
375+
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
376+
a7cb1000-a7cb2000 ---p 00000000 00:00 0
377+
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
378+
a7eb2000-a7eb3000 ---p 00000000 00:00 0
379+
a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack]
380+
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
381+
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
382+
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
383+
a800b000-a800e000 rw-p 00000000 00:00 0
384+
a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0
385+
a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0
386+
a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0
387+
a8024000-a8027000 rw-p 00000000 00:00 0
388+
a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2
389+
a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2
390+
a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2
391+
aff35000-aff4a000 rw-p 00000000 00:00 0
392+
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
365393

366394
The /proc/PID/smaps is an extension based on maps, showing the memory
367395
consumption for each of the process's mappings. For each of mappings there

fs/proc/base.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,9 +2989,9 @@ static const struct pid_entry tgid_base_stuff[] = {
29892989
INF("cmdline", S_IRUGO, proc_pid_cmdline),
29902990
ONE("stat", S_IRUGO, proc_tgid_stat),
29912991
ONE("statm", S_IRUGO, proc_pid_statm),
2992-
REG("maps", S_IRUGO, proc_maps_operations),
2992+
REG("maps", S_IRUGO, proc_pid_maps_operations),
29932993
#ifdef CONFIG_NUMA
2994-
REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
2994+
REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations),
29952995
#endif
29962996
REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations),
29972997
LNK("cwd", proc_cwd_link),
@@ -3002,7 +3002,7 @@ static const struct pid_entry tgid_base_stuff[] = {
30023002
REG("mountstats", S_IRUSR, proc_mountstats_operations),
30033003
#ifdef CONFIG_PROC_PAGE_MONITOR
30043004
REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
3005-
REG("smaps", S_IRUGO, proc_smaps_operations),
3005+
REG("smaps", S_IRUGO, proc_pid_smaps_operations),
30063006
REG("pagemap", S_IRUGO, proc_pagemap_operations),
30073007
#endif
30083008
#ifdef CONFIG_SECURITY
@@ -3348,9 +3348,9 @@ static const struct pid_entry tid_base_stuff[] = {
33483348
INF("cmdline", S_IRUGO, proc_pid_cmdline),
33493349
ONE("stat", S_IRUGO, proc_tid_stat),
33503350
ONE("statm", S_IRUGO, proc_pid_statm),
3351-
REG("maps", S_IRUGO, proc_maps_operations),
3351+
REG("maps", S_IRUGO, proc_tid_maps_operations),
33523352
#ifdef CONFIG_NUMA
3353-
REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
3353+
REG("numa_maps", S_IRUGO, proc_tid_numa_maps_operations),
33543354
#endif
33553355
REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations),
33563356
LNK("cwd", proc_cwd_link),
@@ -3360,7 +3360,7 @@ static const struct pid_entry tid_base_stuff[] = {
33603360
REG("mountinfo", S_IRUGO, proc_mountinfo_operations),
33613361
#ifdef CONFIG_PROC_PAGE_MONITOR
33623362
REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
3363-
REG("smaps", S_IRUGO, proc_smaps_operations),
3363+
REG("smaps", S_IRUGO, proc_tid_smaps_operations),
33643364
REG("pagemap", S_IRUGO, proc_pagemap_operations),
33653365
#endif
33663366
#ifdef CONFIG_SECURITY

fs/proc/internal.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
5353
struct pid *pid, struct task_struct *task);
5454
extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
5555

56-
extern const struct file_operations proc_maps_operations;
57-
extern const struct file_operations proc_numa_maps_operations;
58-
extern const struct file_operations proc_smaps_operations;
56+
extern const struct file_operations proc_pid_maps_operations;
57+
extern const struct file_operations proc_tid_maps_operations;
58+
extern const struct file_operations proc_pid_numa_maps_operations;
59+
extern const struct file_operations proc_tid_numa_maps_operations;
60+
extern const struct file_operations proc_pid_smaps_operations;
61+
extern const struct file_operations proc_tid_smaps_operations;
5962
extern const struct file_operations proc_clear_refs_operations;
6063
extern const struct file_operations proc_pagemap_operations;
6164
extern const struct file_operations proc_net_operations;

0 commit comments

Comments
 (0)