Don't forget to BIO_flush() a memory BIO in OpenSSL if you're using a BIO chain (via BIO_push() and BIO_pop()) and write a small amount of data to the BIO!
Otherwise, if you're like me, you'll keep wondering why no data has been written to the bottom BIO.
Also, you should really call
BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL)
to make sure that the base64 BIO *b64 doesn't add (or expect) a newline at the end of each encoded chunk
Posted on 14 May 2007 12:17. Permalink
Another interesting problem in auth_call. When it sets up argv to pass to execve login_passwd, it sets argv[0] to the first value of the va_list that was passed to auth_call.
This would be no problem in general, since login_passwd, like most progams, pretty much ignores argv[0], since it's supposed to be the name that was used to call the program. Unfortunately, in this case, login_passwd is really just a hard link to a large crunched binary. Crunched binaries use argv[0] to decide which crunched main function to call. As it happens, auth_call when called by login (via auth_verify in /usr/src/lib/libc/gen/authenticate.c) ends up setting argv[0] to be "passwd".
Of course, I also crunched a binary called "passwd", so the binary generated by crunchgen ends up invoking passwd's main function instead of login_passwd's main function! Naturally, passwd is confused by the arguments that should have been passed to login_passwd, and fails. Thus, login also fails.
Right now, my workaround is to modify line 858 of /usr/src/lib/libc/gen/auth_subr.c
/* ...snip... */ argv[0] = path; /* WORKAROUND: fix a bug in the way login_passwd is called */ execve(path, argv, auth_environ); /* ...snip... */
But, really I should fix how the arguments are being copied from the va_list earlier on; I just don't know if anyone is depending on that strange first argument.
Posted on 05 January 2007 07:53. Permalink
I just solved a bug that had been haunting me for a few days.
I've been building a large crunched binary with crunchgen, and ran into a problem with login. I could build the standard binary in /usr/src/usr.bin/login and it ran with no problems, but when I crunched it into my binary, every username I tried to use to login would fail with the error
dup of backchannel: Bad file descriptor
A rather mysterious error. It turns out that it comes from a call to dup2 in libc in /usr/src/lib/libc/gen/auth_sub.c in auth_call, the main call for authenticating logins. I added some code to the kernel to give me better information about why dup2 was failing, and it turned out that sys_dup2 (the system call in kern/kern_descrip.c) was not even getting called! ktrace confirmed this result.
The problem is that dup2 in libc is almost entirely a passthrough to int 0x80 with parameter 90 (the syscall number for dup2), so I was stumped as to how the couple lines of assembly in dup2 could possibly be returning EBADF.
I eventually discovered that libpthread also contains a definition of dup2, and this definition seems to be shadowing the libc definition in the crunched binary. The pthread version, of course, checks some other structures first, and may return EBADF without calling to the kernel.
Indeed, removing the program that needed libpthread (and of course removing the library from linking) solved the problem, and login works again.
The solution, it turns out, is actually trivial. All you need to do is link the offending program that requires pthreads to /usr/lib/libpthread.a directly. Then crunchgen's makefile will call crunchide on the resulting .o file, thus ensuring that the symbols in libpthread.a don't shadow those of libc.
Posted on 04 January 2007 17:37. Permalink