Bug 3441 - Build openssh with sanitizer flags enabled
Summary: Build openssh with sanitizer flags enabled
Status: NEW
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: Build system (show other bugs)
Version: 8.7p1
Hardware: amd64 Linux
: P5 enhancement
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-06-03 21:16 AEST by Dmitry Belyavskiy
Modified: 2022-07-01 18:02 AEST (History)
1 user (show)

See Also:


Attachments
Skip rlimit+select check if sandbox is disabled. (637 bytes, patch)
2022-06-04 20:21 AEST, Darren Tucker
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry Belyavskiy 2022-06-03 21:16:38 AEST
$ ./configure CFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address

ends with 

configure: error: *** compiler cannot create working executables, check config.log ***
Comment 1 Darren Tucker 2022-06-03 21:44:41 AEST
What did it say when you checked config.log?
Comment 2 Darren Tucker 2022-06-03 21:51:16 AEST
Also, what platform, compiler, and architecture (Hardware = "Other"?) was this on?
Comment 3 Dmitry Belyavskiy 2022-06-03 21:56:42 AEST
The 1st error was caused by lack of libasan.

After I installed it, the configure hangs on 
checking if select and/or poll works with descriptor rlimit...

I test on x86_64 Fedora 35 Linux, 

$ gcc --version
gcc (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2)
Copyright (C) 2021 Free Software Foundation, Inc.
Comment 4 Dmitry Belyavskiy 2022-06-03 22:04:58 AEST
See also https://bugzilla.redhat.com/show_bug.cgi?id=2070137
Comment 5 Darren Tucker 2022-06-04 20:16:48 AEST
Th(In reply to Dmitry Belyavskiy from comment #4)
> See also https://bugzilla.redhat.com/show_bug.cgi?id=2070137

I split out the rlimit+select check before I read that bug but got the same result:

$ ./a.out 
==2109378==Can't open /proc/2109377/task for reading.
==2109377==LeakSanitizer has encountered a fatal error.
==2109377==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==2109377==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)

You can work around that by skipping the rlimit+select check if --without-sandbox is set, which gets to the dlsym problem:

usr/bin/ld: ./libssh.a(ssh-pkcs11.o): undefined reference to symbol 'dlsym@@GLIBC_2.2.5'
//usr/lib64/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

which you can work around by disabling the things that need dlsym ("--disable-security-key --disable-pkcs11") which brings us to the final problem: the leak checker in the preauth privsep process can't open /proc because that process is in a chroot and fails when the process exits: 

$ sudo `pwd`/sshd -ddde -p 2022
[...]
debug3: mm_send_keystate: Finished sending state [preauth]
==2194517==Can't open /proc/2194515/task for reading.
==2194515==LeakSanitizer has encountered a fatal error.
==2194515==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==2194515==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)

This one is a dealbreaker as long as the leak checker needs access to /proc since privsep is required.  You could try hacking the code to disable privsep for testing purposes but be aware that's now an untested and unsupported configuration.
Comment 6 Darren Tucker 2022-06-04 20:21:06 AEST
Created attachment 3596 [details]
Skip rlimit+select check if sandbox is disabled.
Comment 7 Dmitry Belyavskiy 2022-06-06 19:27:10 AEST
Thank you!
Comment 8 Darren Tucker 2022-06-06 19:32:04 AEST
Oh, one other possibility for testing purposes: you could also mount /proc inside the privsep chroot.  Obviously this would be a terrible idea  to run in production since in this context /proc is probably more than 50% attack surface and chroot escapes by weight.
Comment 9 Darren Tucker 2022-07-01 16:01:23 AEST
I committed a change to configure.ac to skip the check in this case.

With that and the following configure invocation on an unmodified current source tree I got it to work, at least as far as getting a leak report from the preauth privsep process.  This seems to work for both gcc and clang, although the reports from clang seem much better.

$ sudo mkdir -p /chroot/proc
$ sudo mount -t proc proc /chroot/proc
$ CC=clang-14 ./configure --disable-security-key --disable-pkcs11 --without-sandbox --with-cflags=-fsanitize=address --with-ldflags=-fsanitize=address --with-privsep-path=/chroot --with-privsep-user=root

Obviously, using "root" as the privsep user is not suitable for production use.
Comment 10 Dmitry Belyavskiy 2022-07-01 18:02:44 AEST
Thank you very much!