yesterday the “portable” version of libressl was released.
i set up a package in sabotage linux, and went on a voyage to investigate whether the full set of packages can be used with libressl instead of openssl.
first of all, i had to fight some obstacles to get libressl compiling though…
obstacle 1 – -Werror
../include/openssl/bio.h:622:3: error: '__bounded__' attribute directive ignored [-Werror=attributes]
-Werror is hardcoded in the configure script, which is a very bad idea, and the opposite of portable.
using -Werror is a guarantueed build break whenever the build is tried on a system the original developer had no access to.
it’s sufficient to use a different compiler version, different libc version, etc to make new warnings pop up.
sed -i 's/-Werror//' configure
obstacle 2 – unconditional inclusion of internal glibc header
compat/issetugid_linux.c:7:30: fatal error: gnu/libc-version.h: No such file or directory
many people assume linux == glibc, but that is not the reality.
sabotage linux uses musl libc, and there are at least 4 other libcs that could be used instead (uclibc, dietlibc, klibc, bionic).
looking at issetugid_linux.c uncovers a dubious hack:
if glibc 2.19 is detected, getauxval(AT_SECURE) is not used, because there was once a bug (see comment in source code).
however it’s common practice in distros to backport bugfixes, without updating the version number.
so this hack prevents proper usage of getauxval even if your libc version is long fixed.
the mentioned bug is very likely already fixed in any distro using glibc 2.19.
to get the thing out of my way and compilation going on, the quick fix was to cover everything with #ifdef __GLIBC__.
what the code really should do though is to just use the getauxval call unconditionally without the glibc version check.
obstacle 3 – unnecessary unconditional inclusion of sys/sysctl.h
compat/getentropy_linux.c:27:24: fatal error: sys/sysctl.h: No such file or directory
musl does not have sys/sysctl.h, because:
(citing musl’s author Rich Felker)
sysctl does not work, and NEVER worked. using it is bogus.
it was a bogus experimental syscall that was deprecated before it was ever used (basically, a broken binary version of /proc/sys, without any stability between kernel versions for what the binary constants meant).
since the code in question does not use the sysctl function (declared in sys/sysctl.h) and does the syscall() directly,
it was safe and sufficient to just remove the include statement.
still it leaves a bad taste in my mouth that it was used at all…
having fixed these 3 issues, libressl built successfully.
on the plus side: using 8 cores, libressl builds in about 1 minute, while openssl requires 1:45.
also openssl depends on perl, which takes an additional 2 minutes buildtime.
so if nothing else depends on perl, it’s about 3x faster.
with libressl in place, a “world” metapackage (contains almost all packages) build was started.
wget failed to build due to lack of RAND_egd() function.
fixed by using a patch from openbsd.
stunnel failed to build due to lack of RAND_egd() function.
fixed by using a custom patch conceptually equivalent to the wget one.
cryptsetup and others failed to detect openssl due to lack of pkgconfig files.
i modified my package build script to create these .pc files (copies from openssl).
php, xorg-server and others failed to build subtly due to an ugly hack used in libressl’s libcompat.a, linked into libcrypto.so:
$ gcc test.c -lcrypto -fvisibility=hidden
/bin/ld: a.out: hidden symbol `main' in /tmp/ccobhDjc.o is referenced by DSO
/bin/ld: final link failed: Bad value
$ readelf -a /lib/libcrypto.so | grep main
000000345708 000a00000006 R_X86_64_GLOB_DAT 0000000000000000 main + 0
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND main
2146: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND main
extern int main(int, char *argv);
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
HD(main); /* an addr in program */
the address of main() is used to gather entropy… very smart… NOT.
most of the methods used in this file to gather entropy are very dubious.
the crypto experts from OpenBSD should know better and just use /dev/urandom and/or getauxval(AT_RANDOM)
instead of all these hacks.
with that fixed, most programs expecting openssl seem to compile and work correctly.
mysql’s CMAKE build system fails to detect SSL libraries.
-- OPENSSL_INCLUDE_DIR = /usr/include
-- OPENSSL_LIBRARY = /usr/lib/libssl.so
-- CRYPTO_LIBRARY = /usr/lib/libcrypto.so
-- OPENSSL_MAJOR_VERSION = 2
-- Looking for SHA512_DIGEST_LENGTH
-- Looking for SHA512_DIGEST_LENGTH - found
CMake Error at cmake/ssl.cmake:231 (MESSAGE):
Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to
enable SSL support
not patched yet.
the last build error was in apache:
ssl_engine_init.c:445:28: error: ‘ENGINE_CTRL_CHIL_SET_FORKCHECK’ undeclared
this is a macro which is available in openssl’s engine.h, and was removed from libressl for unknown reasons.
not patched yet.
apart from these two, everything seems to be usable without big effort.
so if the libressl developers rip out all their dubious entropy generation methods in favor of /dev/urandom on linux it might be well worth switching to it.
the whole adventure is documented in the libressl_replaces_openssl branch.
OpenBSD released an updated version 2.0.1 earlier today.
the new release fixes the following problems
– reference to main() which breaks packages using -fvisibility=hidden
– usage of -Werror
– generation of pkg-config files
– unconditional inclusion of sys/sysctl.h
so the portability concerns have largely been addressed.
the only portability issue not fixed is the glibc-specific stuff in issetugid_linux.c.
instead, a patch containing an issetugid implementation for inclusion in musl
was sent to the musl maillist.
on the application compatibility side nothing seems to have changed.
RAND_egd() is still missing, as well as the macros used by apache.
the dubious fallbacks for getentropy (obsolete sysctl syscall, function addresses) are still present.
this blog about similar testing done on gentoo (recommended read) has a link to a patch for the apache build.
there is also a patch for a segfault in openssh.
“if the libressl developers rip out all their dubious entropy generation methods in favor of /dev/urandom on linux”
Did you read the whole getentropy_linux.c file before writing this? Hint: it even comes with comments.
yes, i see that those hacks serve only as fallback, however that doesn’t make them less dubious or hackish.
opening /dev/urandom may for example fail on resource exhaustion, in that case the only reliable fallback is getauxval(AT_RANDOM) plus maybe a few clock_gettime calls…
in such a case reporting error early is better than trying to use non-random or weak entropy (the address of main will be constant on non-PIE binaries, and ASLR entropy is only a few bits anyway).