3

I have a little library that writes out a "thin core" which contains only the stack info (and necessary other bits for a valid core) but doesn't include any of the heap. This is not always useful but the core is much smaller than a full core and sometimes people don't want to provide the contents of their heap.

This library worked by reading /proc/<PID>/maps and locating the [stack] and [stack:<tid>] segments (this process has a lot of threads). For example I'd see output like this:

  ...
7fe848000000-7fe848021000 rw-p 00000000 00:00 0 
7fe848021000-7fe84c000000 ---p 00000000 00:00 0 
7fe84c1ff000-7fe84c200000 ---p 00000000 00:00 0 
7fe84c200000-7fe84ca00000 rw-p 00000000 00:00 0    [stack:25672]
7fe84ca00000-7fe84cc00000 rw-p 00000000 00:00 0 
7fe84cdff000-7fe84ce00000 ---p 00000000 00:00 0 
7fe84ce00000-7fe84d600000 rw-p 00000000 00:00 0    [stack:25534]
7fe84d600000-7fe84d800000 rw-p 00000000 00:00 0 
7fe84d9ff000-7fe84da00000 ---p 00000000 00:00 0 
7fe84da00000-7fe84e200000 rw-p 00000000 00:00 0    [stack:25532]
7fe84e200000-7fe84e600000 rw-p 00000000 00:00 0 
7fe84e7fd000-7fe84e7fe000 ---p 00000000 00:00 0 
7fe84e7fe000-7fe84effe000 rw-p 00000000 00:00 0    [stack:25531]
7fe84effe000-7fe84efff000 ---p 00000000 00:00 0 
7fe84efff000-7fe84f7ff000 rw-p 00000000 00:00 0    [stack:25530]
7fe84f7ff000-7fe84f800000 ---p 00000000 00:00 0 
7fe84f800000-7fe850000000 rw-p 00000000 00:00 0    [stack:25529]
7fe850000000-7fe850021000 rw-p 00000000 00:00 0 
7fe850021000-7fe854000000 ---p 00000000 00:00 0 
7fe854000000-7fe854400000 rw-p 00000000 00:00 0 
7fe8545ff000-7fe854600000 ---p 00000000 00:00 0
  ...
7fff5ce1d000-7fff5ce3e000 rw-p 00000000 00:00 0    [stack]
  ...

etc. That was working fine on older Linux kernels like 3.5 (Ubuntu 12.04) and 3.13 (Ubuntu 14.04).

However, with newer kernels (for example 4.4 from Ubuntu 16.04) the /proc/<PID>/maps file no longer seems to contain any entries for the per-thread stack segments. I only see the main stack [stack]; all the memory segments that appear like they might be stack segments have an empty pathname section.

This means that my "thin cores" are too thin and only the main thread's stack is provided.

I've tried examining /proc/<PID>/smaps in newer kernels and I can't find a way to determine which segments are associated with a thread stack and which are not, in the new more limited format.

Also I checked the procfs(5) man page and it still lists the [stack:<tid>] format as something I should be seeing, but I'm not seeing it...

Anyone have any ideas where this information went and whether I can infer it from some other available information?

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Maybe related, you might find some useful information in [The Stack Clash](https://blog.qualys.com/securitylabs/2017/06/19/the-stack-clash) proof of concepts. – jww Jul 31 '17 at 21:53
  • An interesting idea but the ones I looked at seemed to attack the main stack (`[stack]`) not the thread stacks. – MadScientist Aug 01 '17 at 12:02

1 Answers1

0

I haven't found a real solution to this problem. For posterity I'll describe what I did for the short term: I obtained the size of my thread stack using pthread_attr_getstacksize(), then when I looked through the unnamed memory segments to decide what to write to the "thin core" I preserved the segments which had that exact size and ignored the rest.

This is a pretty dodgy heuristic but it was all I could come up with and it seems to work so far from my limited testing.

I'm still hoping someone will provide a more reliable/robust alternative.

MadScientist
  • 92,819
  • 9
  • 109
  • 136