TL;DR I don't think grsec is doing the wrong thing here. I'm just trying to port/placate a piece of third party code which is attempting to do some horrible things to its stack....
We're integrating said piece of software into our environment, which has a grsec kernel with PAX_ASLR and PAX_RANDMMAP turned on. The specific problem is that this software is making what I believe to be the unwarranted assumption that if the stack rlim_cur is RLIMIT_INFINITY then it can assume that the stack runs backwards from the high address in the [stack] line of /proc/self/maps for at least 8MB. It then proceeds to try to validate this assumption by walking backward, reading a byte from each page in order to force it to be allocated, and finally tries to set up its own guard page mapping one page before the real kernel guard page (so that it can catch overflows for its own purposes).
Empirically for our environment the rlimit being returned for the main thread stack is RLIMIT_INFINITY (I assume, but may be mistaken, that none of the other folks on our project has done anything special to cause that) but, with a random mmap_base, the gap available for the main thread stack is very seldom anything like 8MB. I rather suspect that it also isn't anything like that even on a non-grsec kernel, but that the software in question "gets away with it" because there tend to be at least 8MB worth of contiguous readable mappings which are actually from loaded shared objects, and that its manual guard page
actually ends up somewhere entirely inappropriate....
In the process of trying to come up with something that makes this all play together nicely, I looked at how the VM_GROWSDOWN stack segment is set up, (some of) how it's grown, and how it's reported in /proc/*/maps. If I understand it correctly -- and admittedly I probably don't -- it seems to me that the stack mapping (and by extension the [stack] line in /proc/*/maps [stack]) will only describe the current vma as it stands, and not the space for the vma to grow into; and also that the guard page is only going to show up if it actually gets touched (and a mapping is therefore created). However, I may easily be misunderstanding that -- particularly since I still haven't figured out how the guard page gets created/handled for ARMv7.
Anyway, FWIW, I just found it odd that such fundamental bits of information as the main thread stack base and usable size are apparently only available by using file I/O to grot through multiple lines of text -- of which at most only two are germane to the problem at hand -- and even then rely on knowing a) how the kernel will grow the stack and b) how big the guard area will be. That seems like an awful lot of work to fetch two well known integers....
I also found it slightly odd that the rlimit being returned doesn't provide a useful indication of the actual space available -- but since that's notionally under user control, it's arguably not the kernel's problem. (And it's entrely possible that it's self-inflicted somewhere on our part -- I'm pretty new to this project.)
Again, it's been a long time since I've had to fiddle with the Linux kernel, so I may have enitrely the wrong then of the stick. Or stack. Whichever.