stack: synthesize AT_RANDOM when the kernel omits it - #3
Conversation
AT_RANDOM was only added to the auxv in Linux 2.6.29. On older kernels getauxval(AT_RANDOM) returns NULL, so the existing assert! panics and user-land exec (and anything built on it, e.g. sharun AppImages) cannot start at all. Fall back to 16 random bytes from /dev/urandom so the interpreter we hand control to can still initialise its stack canary / pointer guard.
talaria0101
left a comment
There was a problem hiding this comment.
Reviewed at 05f52a7, re-fetched immediately before reviewing (head unchanged since fetch). Built and A/B tested on this machine.
The change is correct. AT_RANDOM appeared in Linux 2.6.29, the comment is accurate, and the fallback chain (parent auxv -> /dev/urandom -> zeros) is fine. The all-zero worst case is no worse than what glibc itself does when _dl_random is NULL (it fills a fixed terminator canary), and the previous code panicked in that spot, so this only ever runs where the alternative was death.
Regression check, measured: built v0.3.1 (9249ef1) and this head side by side and ran both over /bin/true, /bin/false, /bin/sh -c, and /usr/bin/env: identical output and exit codes. On any kernel that supplies AT_RANDOM (>= 2.6.29) the pushed bytes are the same 16 bytes as before, so previously-working paths are byte-identical in behavior.
Two nits, non-blocking:
read_exactfailure is swallowed withlet _; after a partial read you push a half-random half-zero canary. Harmless, but a one-line comment that zeros are the accepted worst case would document the intent.- The urandom
Fileis dropped at end of scope so no fd leaks into the loaded image. No change needed, confirming I checked.
Merge dependency: this must be tagged before Anylinux-sharun#15 can work on < 2.6.29 kernels. sharun still pins tag = "v0.3.0" (ce43131), which predates even #2 and still contains assert!(!ptr.is_null()) in stack.rs. Without a tag containing this commit, the tracer in sharun#15 cannot help; userland_execve::exec panics inside the tracee on any kernel that omits AT_RANDOM. Please cut v0.3.2 after merging so #15 can pin it.
Review nit: make the accepted worst case explicit.
|
Thanks for the review and the A/B regression check.
|
* stack: synthesize AT_RANDOM when the kernel omits it AT_RANDOM was only added to the auxv in Linux 2.6.29. On older kernels getauxval(AT_RANDOM) returns NULL, so the existing assert! panics and user-land exec (and anything built on it, e.g. sharun AppImages) cannot start at all. Fall back to 16 random bytes from /dev/urandom so the interpreter we hand control to can still initialise its stack canary / pointer guard. * stack: document that a short /dev/urandom read leaves an all-zero canary Review nit: make the accepted worst case explicit.
What
AT_RANDOMwas only added to the auxv in Linux 2.6.29. On older kernelsgetauxval(AT_RANDOM)returnsNULL, so the existingassert!(!ptr.is_null())instack.rspanics:With
panic = "abort"(as used by sharun's release profile) that's a hardud2/SIGILL before the interpreter is ever entered, so user-land exec and everything built on it cannot start on those kernels.Fix
Fall back to 16 bytes from
/dev/urandomwhen the kernel doesn't supplyAT_RANDOM, so the interpreter we hand control to can still initialise its stack canary / pointer guard.Only triggers when
AT_RANDOMis actually absent (kernel < 2.6.29), so there's no behaviour change on newer kernels.Needed together with pkgforge-dev/Anylinux-sharun#15 to run current AppImages on very old kernels. Verified on Ubuntu 7.04 (kernel 2.6.20), where the
gtk2-ng-demo,gtk3-demo, andQt6 dbus-demoAppImages now launch.