bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

stack bounds


From: Bruno Haible
Subject: stack bounds
Date: Wed, 23 Sep 2020 02:58:08 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-189-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

> While looking into this I discovered pthread_getattr_np + 
> pthread_attr_getstack 
> which might have been nice for the GNU/Linux part of c-stack.c, except 
> they're 
> not async-signal-safe. As I understand it, libsigsegv works around the 
> async-signal-safe problem by parsing /proc/self/maps with async-signal-safe 
> functions, which is quite a feat and is probably beyond what c-stack should 
> do.

Yes, I agree: reading /proc/self/maps without calling malloc() is quite a bunch
of code.

> PS. I also found this circa-2015 Linux kernel bug related to PIE that looks 
> like 
> it might be of interest to the libsigsegv developers
> 
> https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-1000253
> 
> This bug causes /proc/self/maps to report the wrong VMA (actually, 
> overlapping 
> VMAs) for the stack. This could be worth a comment in the libsigsegv sources.

This is hardly a danger in practice: It applies to executables with a data
segment of size 128 MB or more. emacs' data segment size is 13 MB, and the one 
of
dockerd is 21 MB.

> Given the longstanding security problems with stack overflow (as witness 
> the name stackoverflow.com!) it is somewhat disturbing that there is still no 
> reliable way in GNU/Linux to answer the simple question "Where's my stack?" 
> or 
> to detect and recover from stack overflow reliably. What's up with that?

It sounds what you want is a function that returns the stack bounds, in such a
way that every recursion step in a recursive function call the code can ask
"am I close to the stack bound? do I need to stop recursing?"

Such a thing cannot exist.

The reason is that the OS allows or disallows further growth of the stack
according to multiple criteria:
  - ulimit stack
  - ulimit memory
  - ulimit virtual memory
  - avoid collision with existing mmap()ed areas.

The algorithm that makes this decision (whether more stack can be allocated
or not) is undocumented and subject to change. And it changed in Linux, a
couple of years ago. Also, this algorithm may treat the primary thread
differently than other threads.

So, really, the only thing you can do is to do a sigaltstack() for
preparation, and wait for the signal when the OS decides to no longer allow
stack growth.

It's like when you write to a file on disk. On old operating systems like
DOS you could determine the maximum file size by looking at the free space
on the disk. This no longer works, because the decision whether a file
can grow is done by looking at
  - the free space,
  - the space occupied by the metadata for the current file,
  - quota.

Here too, your best bet is to let the OS do its decision and react when
it reports a write failure.

It would be technically possible to export the function that determines
the stack bounds (libsigsegv/src/stackvma-*). But it's pointless to do
so, because the stack bound is not the only factor considered by the OS.

Bruno




reply via email to

[Prev in Thread] Current Thread [Next in Thread]