tools/include/nolibc/stackprotector.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
We are using the getrandom syscall to get a random seed for the
stack protector canary but we are calling it with no flags which means
it'll block until there is some real randomness to return.
This means that if the crng is not ready yet program startup will
block and if you are unlucky that could be for a long time and
look like the program has crashed.
There is a comment in the code about mixing in the pid to make
sure the canary isn't 0 even if getrandom fails so it seems ok
to pass the non-blocking and insecure flags so it doesn't block
and potentially return something even if the crng is not init
yet.
Fixes: 7188d4637e95 ("tools/nolibc: add support for stack protector")
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
The insecure flag is apparently from 5.6, I think Willy said before
we are trying to keep nolibc working on the oldest LTS kernel.
That seems to be 5.10 so I think its ok?
Anyhow, I switched compilers for my nommu target and everything
stopped working, tracked it down to this. my other compiler must
have not supported the stack protector.
tools/include/nolibc/stackprotector.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/include/nolibc/stackprotector.h b/tools/include/nolibc/stackprotector.h
index e11c20c75465..916a92062ba0 100644
--- a/tools/include/nolibc/stackprotector.h
+++ b/tools/include/nolibc/stackprotector.h
@@ -42,7 +42,8 @@ uintptr_t __stack_chk_guard;
static __nolibc_no_stack_protector void __stack_chk_init(void)
{
- __nolibc_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard), 0);
+ __nolibc_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard),
+ GRND_INSECURE | GRND_NONBLOCK);
/* a bit more randomness in case getrandom() fails, ensure the guard is never 0 */
if (__stack_chk_guard != (uintptr_t) &__stack_chk_guard)
__stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
--
2.53.0
Hi Daniel!
On Fri, May 22, 2026 at 06:07:26PM +0900, Daniel Palmer wrote:
> We are using the getrandom syscall to get a random seed for the
> stack protector canary but we are calling it with no flags which means
> it'll block until there is some real randomness to return.
>
> This means that if the crng is not ready yet program startup will
> block and if you are unlucky that could be for a long time and
> look like the program has crashed.
>
> There is a comment in the code about mixing in the pid to make
> sure the canary isn't 0 even if getrandom fails so it seems ok
> to pass the non-blocking and insecure flags so it doesn't block
> and potentially return something even if the crng is not init
> yet.
>
> Fixes: 7188d4637e95 ("tools/nolibc: add support for stack protector")
> Signed-off-by: Daniel Palmer <daniel@thingy.jp>
Acked-by: Willy Tarreau <w@1wt.eu>
> ---
>
> The insecure flag is apparently from 5.6, I think Willy said before
> we are trying to keep nolibc working on the oldest LTS kernel.
> That seems to be 5.10 so I think its ok?
Sounds reasonable. We could also condition the flag to its existence
if it causes issues.
> Anyhow, I switched compilers for my nommu target and everything
> stopped working, tracked it down to this. my other compiler must
> have not supported the stack protector.
Possible, indeed.
Thanks!
Willy
>
> tools/include/nolibc/stackprotector.h | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/tools/include/nolibc/stackprotector.h b/tools/include/nolibc/stackprotector.h
> index e11c20c75465..916a92062ba0 100644
> --- a/tools/include/nolibc/stackprotector.h
> +++ b/tools/include/nolibc/stackprotector.h
> @@ -42,7 +42,8 @@ uintptr_t __stack_chk_guard;
>
> static __nolibc_no_stack_protector void __stack_chk_init(void)
> {
> - __nolibc_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard), 0);
> + __nolibc_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard),
> + GRND_INSECURE | GRND_NONBLOCK);
> /* a bit more randomness in case getrandom() fails, ensure the guard is never 0 */
> if (__stack_chk_guard != (uintptr_t) &__stack_chk_guard)
> __stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
> --
> 2.53.0
>
On 2026-05-22 11:39:27+0200, Willy Tarreau wrote:
> On Fri, May 22, 2026 at 06:07:26PM +0900, Daniel Palmer wrote:
> > We are using the getrandom syscall to get a random seed for the
> > stack protector canary but we are calling it with no flags which means
> > it'll block until there is some real randomness to return.
> >
> > This means that if the crng is not ready yet program startup will
> > block and if you are unlucky that could be for a long time and
> > look like the program has crashed.
> >
> > There is a comment in the code about mixing in the pid to make
> > sure the canary isn't 0 even if getrandom fails so it seems ok
> > to pass the non-blocking and insecure flags so it doesn't block
> > and potentially return something even if the crng is not init
> > yet.
> >
> > Fixes: 7188d4637e95 ("tools/nolibc: add support for stack protector")
> > Signed-off-by: Daniel Palmer <daniel@thingy.jp>
>
> Acked-by: Willy Tarreau <w@1wt.eu>
>
> > ---
> >
> > The insecure flag is apparently from 5.6, I think Willy said before
> > we are trying to keep nolibc working on the oldest LTS kernel.
> > That seems to be 5.10 so I think its ok?
>
> Sounds reasonable. We could also condition the flag to its existence
> if it causes issues.
IMO we could even not use GRND_INSECURE and only use GRND_NONBLOCK.
> > Anyhow, I switched compilers for my nommu target and everything
> > stopped working, tracked it down to this. my other compiler must
> > have not supported the stack protector.
Did the random pool *never* fully initialize?
That sounds weird.
(...)
Thomas
Hi Thomas, Willy,
On Fri, 22 May 2026 at 23:46, Thomas Weißschuh <linux@weissschuh.net> wrote:
>
> On 2026-05-22 11:39:27+0200, Willy Tarreau wrote:
> > > The insecure flag is apparently from 5.6, I think Willy said before
> > > we are trying to keep nolibc working on the oldest LTS kernel.
> > > That seems to be 5.10 so I think its ok?
> >
> > Sounds reasonable. We could also condition the flag to its existence
> > if it causes issues.
>
> IMO we could even not use GRND_INSECURE and only use GRND_NONBLOCK.
How about this:
static __nolibc_no_stack_protector void __stack_chk_init(void)
{
int ret = -EINVAL;
/* GRND_INSECURE is available in kernel 5.6+ */
#ifdef GRND_INSECURE
ret = __nolibc_syscall3(__NR_getrandom, &__stack_chk_guard,
sizeof(__stack_chk_guard),
GRND_INSECURE | GRND_NONBLOCK);
#endif
/* GRND_INSECURE wasn't defined at build time or the above call
to getrandom failed because
* the running kernel didn't understand it.
*/
if (ret == -EINVAL) {
__nolibc_syscall3(__NR_getrandom, &__stack_chk_guard,
sizeof(__stack_chk_guard),
GRND_NONBLOCK);
}
/* a bit more randomness in case getrandom() fails, ensure the
guard is never 0 */
if (__stack_chk_guard != (uintptr_t) &__stack_chk_guard)
__stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
}
I think that would allow building with >=5.6 headers and running on
<5.6 and building on <5.6.
Maybe its too much. :)
Thanks,
Daniel
Hi Thomas, On Fri, 22 May 2026 at 23:46, Thomas Weißschuh <linux@weissschuh.net> wrote: > > > Anyhow, I switched compilers for my nommu target and everything > > > stopped working, tracked it down to this. my other compiler must > > > have not supported the stack protector. > > Did the random pool *never* fully initialize? > That sounds weird. The crng init message is eventually printed after a while if I interact with the shell[0]. Since my init, shell, everything is written with nolibc now there is so little disk activity etc I don't think there are enough interrupts happening to collect any randomness. Maybe something to save some seeding data between boots is the next tool I need to write. 0 - https://gist.github.com/fifteenhex/d4a284f34a605702f98a3db68261f46e
On Sat, May 23, 2026 at 07:29:53AM +0900, Daniel Palmer wrote: > Hi Thomas, > > On Fri, 22 May 2026 at 23:46, Thomas Weißschuh <linux@weissschuh.net> wrote: > > > > > Anyhow, I switched compilers for my nommu target and everything > > > > stopped working, tracked it down to this. my other compiler must > > > > have not supported the stack protector. > > > > Did the random pool *never* fully initialize? > > That sounds weird. > > The crng init message is eventually printed after a while if I > interact with the shell[0]. > Since my init, shell, everything is written with nolibc now there is > so little disk activity etc I don't think there are enough interrupts > happening to collect any randomness. Yeah I've known this problem as well for years on small headless systems that never finish to boot if you ever called getrandom(), before GRND_INSECURE existed. Several of us used to patch it not to wait or used to change boot code not to call this function. > Maybe something to save some seeding data between boots is the next > tool I need to write. Since modern kernels support GRND_INSECURE, I suspect you would just be wasting your time. Better rely on this for boot code. Willy
On 2026-05-24 06:25:37+0200, Willy Tarreau wrote: > On Sat, May 23, 2026 at 07:29:53AM +0900, Daniel Palmer wrote: > > On Fri, 22 May 2026 at 23:46, Thomas Weißschuh <linux@weissschuh.net> wrote: (...) > > Maybe something to save some seeding data between boots is the next > > tool I need to write. > > Since modern kernels support GRND_INSECURE, I suspect you would just > be wasting your time. Better rely on this for boot code. If it's good enough for Willy, it is certainly good enough for me, too. Or we could switch to AT_RANDOM, but the current aproach is fine for me. Thomas
Sorry for the spam. On Fri, 22 May 2026 at 18:07, Daniel Palmer <daniel@thingy.jp> wrote: > There is a comment in the code about mixing in the pid to make > sure the canary isn't 0 even if getrandom fails so it seems ok > to pass the non-blocking and insecure flags so it doesn't block > and potentially return something even if the crng is not init > yet. My brain made the pid part up. I checked again add it's not using the pid.. anyhow the code still seems to have been prepared for getrandom failing so it seems ok to let it actually fail. Thanks, Daniel
© 2016 - 2026 Red Hat, Inc.