[Toybox] mkpasswd crashes in github ci
Rob Landley
rob at landley.net
Tue Jun 24 15:37:14 PDT 2025
On 6/6/25 23:05, Rob Landley wrote:
> On 6/5/25 08:51, enh wrote:
>> doesn't affect android's build because we don't build mkpasswd, but
>> the mkpasswd tests are failing on github with sigsegv:
>
> Sigh, the updated the ASAN plumbing, didn't they?
>
> https://landley.net/notes-2024.html#04-07-2024
>
> When you enable ASAN on current gcc toolchains, crypt() drops out and
> becomes a NULL pointer dereference. I don't know why. I need to put a
> crypt() implementation in lib/hash.c.
>
> If you disable ASAN, the tests pass just fine. ASAN is what breaks them.
If I append this to lib/hash.c:
char *krypt(char *phrase, char *setting)
{
return "boom";
}
extern __typeof(crypt) crypt __attribute__((__weak__, __alias__("krypt")));
Doing "ASAN=1 make clean mkpasswd; ./mkpasswd blah" STILL fails with the
exact same null pointer dereference.
I dunno what gcc's ASAN is doing, but it appears to be failing at
runtime, not link time. I presumably need a compile time probe in
scripts/genconfig.sh to detect crypt() failing and swap it out with a
config symbol and #ifdefs, which is just sad...
Maybe I should just switch the github test to "make toybox tests" which
will build a toybox binary without ASAN and then test the existing
binary? (The test builds enable ASAN, but make tests will use the
existing binary if there is one, so listing both tests without asan...)
The other obvious alternative is just doing a new lib/crypt.c and always
using that, but I'm probably never implementing "yescrypt" because there
isn't a spec for it and the source tarball seemed intentionally
obfuscated when I gave it a quick look. I've got md5, sha1, sha256, and
sha512. I _could_ do des but... why? (I met solar at gentoo long ago, who
seems retired now, but I think Openwall's Solar Designer is a different
person. I suppose I could ask...)
Ok, the REALLY WEIRD part is it's still doing that even if I take
"crypt" out of the library list in make/make.sh. If it's ONLY using the
alias to call krypt(), it still dies in a way that smashes the stack and
forgets where it is. I stuck in a dprintf(2) right before it called
crypt in toys/*/mkpasswd.c and it printed but the stack trace denied it:
This is the line before calling crypt()
AddressSanitizer:DEADLYSIGNAL
=================================================================
==13214==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000
(pc 0x000000000000 bp 0x7ffcc3b4e1d0 sp 0x7ffcc3b4e118 T0)
==13214==Hint: pc points to the zero page.
==13214==The signal is caused by a READ memory access.
==13214==Hint: address points to the zero page.
#0 0x0 (<unknown module>)
#1 0x56255bfac8cd in main /home/landley/toybox/toybox/main.c:367
#2 0x7fbd441f7249 (/lib/x86_64-linux-gnu/libc.so.6+0x27249)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (<unknown module>)
==13214==ABORTING
There's not a lot I can do with that. It seems to be losing its marbles
on the FUNCTION PROTOTYPE somehow? Which in /usr/include/crypt.h is:
extern char *crypt (const char *__phrase, const char *__setting)
__THROW;
Ok, just to be PEDANTIC I'll add the stupid consts to my function it's
redirecting to (that CAN'T be it, ELF doesn't annotate at that level.)
Yup, made no difference.
Did ASAN special case the name "crypt" somehow? This seems unlikely...
Rob
P.S. I want to switch more of the lib/*.c vs -lblah decisions to weak
symbols in general, so I can have one "use toybox builtins instead of
external libraries" config symbol dropping out the "weak" and then the
existing $LIBRARIES plumbing in scripts/make.sh can do its thing with
--gc-sections --as-needed dropping them back out again and it's all just
one codepath... but that's not going to work around a runtime gnu/bug.
More information about the Toybox
mailing list