2

PURPOSE:

I am theorising as to how one would go about creating a pointer scanner in a Linux environment.

DISCLAIMER:

My findings have been tested on Debian Bookworm (current stable) and a Gentoo system with a custom kernel. No differences have been observed.

PROBLEM:

Without attaching debuggers to a target process, I want to be able to identify the VMA of the stack of each thread/child task. This should be achievable using the proc pseudo-filesystem

DISCUSSION:

Prior to Linux 4.5, /proc/[parent_tid]/maps would label the parent task's stack region with [STACK] in the pathname field, and label each child task's stack region with [STACK:child_tid].

Following Linux 4.5, only the parent task's stack region maintains its [STACK] label. Child task stack regions now have no label. In the commit message for this change (See link 1), Johannes Weiner states that child task stack VMAs can still be viewed by observing their process maps via /proc/[parent_tid]/task/[child_tid]/maps.

This has proven ineffective to me. The memory region maps are identical across parent and child tasks. /proc/[parent_tid]/maps/proc/[parent_tid]/task/[child_tid*]/maps. This ultimately means that the [STACK] label is attached to the same region.

/proc/[tid]/stat can be used to find the VMA of the bottom of the stack for a given task. It is the 28th value (see man 5 proc). Once again, /proc/[parent_tid]/stat/proc/[parent_tid]/task/[child_tid*]/stat. Clearly the child task does not share the start of the stack with every other task in the process.

clone(2), the system call used to create new child tasks, takes a stack pointer as a parameter. The most obvious way to acquire memory for a stack is via an anonymous mmap(2). Anonymous memory maps do not have a label in /proc/[tid]/maps. From observing a few single threaded and multi-threaded processes, there is a direct correlation between the number of anonymous memory mappings and the threads of a program. While such mappings are used for more than thread stacks, I very much expect thread stacks to be allocated this way. Each memory mapping gets its own entry in /proc/[tid]/maps. Surely there is a way to determine which of these act as child task stacks?

What am I getting wrong here?


RELATED LINKS:

  1. Commit for removing the [STACK:tid] label from /proc/[tid]/maps:
    https://lists.ubuntu.com/archives/kernel-team/2016-March/074681.html

1 Answer 1

1

The 28th field works for me, on Linux 6.1.0. Note that tasks will not have their own stack, unless they need it.

Here is a simple script to run, it should return different bottom stack values for some of the tasks. You might need to download/install Firefox.

#!/bin/bash

# create a temporary profile
test -d /tmp/temporary_profile || mkdir /tmp/temporary_profile

# run Firefox on that profile
firefox --profile /tmp/temporary_profile &

# Give it some time to create the tasks
sleep 10

# Get the PID
FFPID=$!

# Print field 28 of the stat files
awk '{print FILENAME" "$28}' /proc/$FFPID/stat /proc/$FFPID/task/*/stat

If you are running Firefox, you can run the following line and type its current process ID:

read a;awk '{print FILENAME" "$28}' /proc/$a/stat /proc/$a/task/*/stat

It will work with other multi-threaded programs, but I know Firefox will almost inmediately create some tasks that will have stacks of their own, and that might help you check if your code is working.

2
  • In what case would a child task not need its own stack? Surely its .text would have to operate entirely on heap allocations, which is impossible as far as I am aware. Here is my output of your script for a chromium based browser: pastebin.com/5RRdrNbk
    – vykt
    Commented Oct 15, 2023 at 10:59
  • 1
    @vykt I don't know, that's an interesting question, you might want ask it (as a new one) adding the output from Firefox and Chromium. Or even better creating a small test program that opens a couple of threads. People are more inclined to answer if they can reproduce the issue on their computers. Something like the code here. Commented Oct 15, 2023 at 20:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .