Wow, this is a lot to go through, but I really do appreciate it. It may take me a bit to sort through these, Could send them to me as discrete patches (e.g. like a git send-email patch series)? That would make them easier to sort through and apply individually?
On Jul 16, 2014, at 5:02 PM, Jonas 'Sortie' Termansen <sor...@maxsi.org> wrote: > Hi, > > I ported libressl to my custom hobby OS and it has been a pleasant > experience. Nonetheless, I did run into some minor portability problems > that I wish to share: What sort of OS is this? > * apps/Makefile.am.tpl links libcrypto and libssl in the wrong order. > The libssl library depends on libcrypto and libcrypto doesn't depend > on libssl. Linking the openssl program as -lcrypto -lssl breaks on > static linking if the main program didn't pull in parts of libcrypto > that libssl needs. Right, sounds good. > * The POSIX <sys/select.h> header is not used to get the select > function. While <sys/time.h> is required to also provide it (though > that seems transitional to me), there is no requirement <sys/time.h> > also provide the FD_* macros needed to actually use select. This > inclusion needs to be added in apps/ocsp.c, apps/s_client.c, > apps/s_server.c and apps/s_time.c. > * ioctl(FIONBIO) is used in a few files to make sockets non-blocking > rather than using fcntl to set the the standard O_NONBLOCK bit. The > files apps/s_client.c and apps/s_server.c should use BIO_socket_nbio() > instead of directly using BIO_socket_ioctl(). The bio/b_sock.c file > should implement BIO_shock_nbio() using fcntl, F_GETFL/F_SETFL and > O_NONBLOCK. > * include/machine/endian.h wraps the <endian.h> header if Linux and the > <machine/endian.h> header if non-Linux. However, it may be the case > that a non-Linux system (such as mine) has <endian.h> and not > <machine/endian.h>. The POSIX committee has accepted <endian.h> into > the next revision of POSIX. guenther recently implemented this draft > in OpenBSD and the header is already present on many modern Unix > systems. It would be better if the compatibility layer instead > implement <endian.h> rather than <machine/endian.h>. There were some recent updates to OpenBSD as well to become more POSIX compliant in this area, so <machine/endian.h> will soon move. > * The build system defaults --program-transform-name to the host triplet > when cross-compiling. It shouldn't do that as the library doesn't have > a target and is not a cross-compiler (as far as I know). It certainly > doesn't make sense to do when the library itself is being > cross-compiled. This also caused unexpected trouble during the man > page installation as the real man pages got installed under the > transformed name, but the hard links to the man pages wasn't > transformed and broke the build. > * The non-standard err(3) family is used a few places. In the main > library it is only used in the apps/openssl.c file, while it is used a > few times in the regression tests. The convenience of using these > functions is not worth the portability concerns when the calling code > can easily use fprintf and exit instead. We had half started some a compat err.h at the hackathon, but fair enough. > * The configure.ac file doesn't check if explicit_bzero is provided by > the operating system but unconditionally uses the internal one. There are some OS-provided explicit_bzero implementations that use a function pointer to beat the compiler optimization. This pointer can possibly be overwritten with a different function. But generally, we can probably make that happen. > I also have a list of minor portability issues I don't mind patching > locally and other stray suggestions: > > * crypto/compat/issetugid_linux.c is used on non-Linux platforms. This > fail on including glibc internal headers which is hardly elegant. > Perhaps another file should be used for unknown operating systems that > assumes the worst and throws a #warning? It could also be handled like > getentropy where it fails with linker errors. That could work. If it is your own OS, you could perhaps implement issetugid and bypass the compatibility layer entirely. > * ssl/d1_lib.c includes the non-standard header <sys/param.h>. It worked > when I removed the inclusion, so it seems redundant. > * The non-standard u_char and u_int types are used a few places in the > random compatibility code. It would work just as well if those were > replaced with explicit unsigned char and unsigned int types. Yah, I have a local patch I need to push that gets rid of these. Old habits are hard to break. > * Consider using _DEFAULT_SOURCE or _ALL_SOURCE as feature macros on > unknown platforms. > * My strerror() (when certain feature macros are defined) return a const > char* as it would be an error to modify the storage. This triggered on > a strerror() invocation in crypto/err/err.c where it stores the result > in a char * rather than a safe const char *. This didn’t cause a const-ripple through the code? Color me surprised! > * There should be an explicit counterpart of memset called > explicit_memset. My libc has such a function, but no explicit_bzero as > I have no regular bzero. If an explicit_memset is added (or detected > in the host system), it could be used in the compatibility > implementation of explicit_bzero (which is currently implemented by > calling memset). I would much prefer if the library uses a safe > zeroing function from the standard library (rather than its own) as > that would give the standard library a chance to be better: I'm quite > interested in using new compiler extensions to robustly ensure memory > is cleared even in the face of link-time optimization and sufficiently > advanced compilers. I don't have absolute confidence that the weak > symbol trick used in explicit_bzero.c is good enough. Fair enough, though I believe we have a pretty good test that verifies correctness. > * The timingsafe_bcmp function could be implemented using > timingsafe_memcmp for the same reasons. > * The compatibility wrapper headers doesn't check whether the standard > library already provides prototypes. The #include_next mechanism is a > good solution, but duplicate function prototypes would happen if the > standard library happens to provide the extensions. Though, I think > that should be harmless, I don't know how that interacts with > __attribute__'s used in the system headers, if they are implemented as > macros, or any other imaginable situation. > * The <sys/stat.h> and <sys/time.h> inclusions in include/stdlib.h seems > redundant. > * The <sys/types.h> inclusion in string.h seems redundant, size_t is > always provided by <string.h>. Yes, likely some leaky BSDisms that we’ll fix upstream wherever is needed. > * The header inclusion guard macro in include/machine/endian.h is > _COMPAT_BYTE_ORDER_H_ (in the reserved namespace) while the other > headers use the macro LIBCRYPTOCOMPAT_FOO_H. > * The <stdint.h> inclusion in include/sys/types.h seems like a > non-standard extension. Files relying on <sys/types.h> pulling in > <stdint.h> should be rewritten to include <stdint.h> explicitly. You’re right - that was to work around some earlier u_int definitions that should probably be removed. > > Below you'll find the reasonably-finished parts of my local patch that > solves some of the above issues. > > Thanks, > > Jonas 'Sortie' Termansen > > diff -Nur libressl-2.0.2/apps/Makefile.am libssl/apps/Makefile.am > --- libressl-2.0.2/apps/Makefile.am 2014-07-16 05:25:52.000000000 +0200 > +++ libssl/apps/Makefile.am 2014-07-16 13:26:55.425448073 +0200 > @@ -4,8 +4,8 @@ > > openssl_CFLAGS = $(USER_CFLAGS) > openssl_LDADD = $(PLATFORM_LDADD) > -openssl_LDADD += $(top_builddir)/crypto/libcrypto.la > openssl_LDADD += $(top_builddir)/ssl/libssl.la > +openssl_LDADD += $(top_builddir)/crypto/libcrypto.la > > openssl_SOURCES = > noinst_HEADERS = > diff -Nur libressl-2.0.2/apps/ocsp.c libssl/apps/ocsp.c > --- libressl-2.0.2/apps/ocsp.c 2014-07-16 05:25:50.000000000 +0200 > +++ libssl/apps/ocsp.c 2014-07-16 13:26:55.429448073 +0200 > @@ -57,6 +57,8 @@ > */ > #ifndef OPENSSL_NO_OCSP > > +#include <sys/select.h> > + > #include <stdio.h> > #include <stdlib.h> > #include <limits.h> > diff -Nur libressl-2.0.2/apps/openssl.c libssl/apps/openssl.c > --- libressl-2.0.2/apps/openssl.c 2014-07-16 05:25:50.000000000 +0200 > +++ libssl/apps/openssl.c 2014-07-16 13:26:55.429448073 +0200 > @@ -109,7 +109,6 @@ > * > */ > > -#include <err.h> > #include <signal.h> > #include <stdio.h> > #include <string.h> > @@ -256,8 +255,10 @@ > arg.count = 0; > > bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); > - if (bio_err == NULL) > - errx(1, "failed to initialise bio_err"); > + if (bio_err == NULL) { > + fprintf(stderr, "%s: failed to initialize bio_err\n", argv[0]); > + exit(1); > + } > > CRYPTO_set_locking_callback(lock_dbg_cb); > > diff -Nur libressl-2.0.2/apps/s_client.c libssl/apps/s_client.c > --- libressl-2.0.2/apps/s_client.c 2014-07-16 05:25:50.000000000 +0200 > +++ libssl/apps/s_client.c 2014-07-16 13:26:55.429448073 +0200 > @@ -137,6 +137,7 @@ > > #include <sys/types.h> > #include <sys/ioctl.h> > +#include <sys/select.h> > #include <sys/socket.h> > > #include <netinet/in.h> > @@ -830,9 +831,8 @@ > BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); > > if (c_nbio) { > - unsigned long l = 1; > BIO_printf(bio_c_out, "turning on non blocking io\n"); > - if (BIO_socket_ioctl(s, FIONBIO, &l) < 0) { > + if (BIO_socket_nbio(s, 1) < 0) { > ERR_print_errors(bio_err); > goto end; > } > diff -Nur libressl-2.0.2/apps/s_server.c libssl/apps/s_server.c > --- libressl-2.0.2/apps/s_server.c 2014-07-16 05:25:50.000000000 +0200 > +++ libssl/apps/s_server.c 2014-07-16 13:26:55.429448073 +0200 > @@ -148,6 +148,7 @@ > > #include <sys/types.h> > #include <sys/ioctl.h> > +#include <sys/select.h> > #include <sys/socket.h> > > #include <assert.h> > @@ -1363,11 +1364,9 @@ > goto err; > } > if (s_nbio) { > - unsigned long sl = 1; > - > if (!s_quiet) > BIO_printf(bio_err, "turning on non blocking io\n"); > - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) > + if (!BIO_socket_nbio(s, 1)) > ERR_print_errors(bio_err); > } > > @@ -1798,11 +1797,9 @@ > goto err; > > if (s_nbio) { > - unsigned long sl = 1; > - > if (!s_quiet) > BIO_printf(bio_err, "turning on non blocking io\n"); > - if (BIO_socket_ioctl(s, FIONBIO, &sl) < 0) > + if (!BIO_socket_nbio(s, 1)) > ERR_print_errors(bio_err); > } > > diff -Nur libressl-2.0.2/apps/s_time.c libssl/apps/s_time.c > --- libressl-2.0.2/apps/s_time.c 2014-07-16 05:25:50.000000000 +0200 > +++ libssl/apps/s_time.c 2014-07-16 13:26:55.433448073 +0200 > @@ -64,6 +64,7 @@ > -----------------------------------------*/ > > #include <sys/socket.h> > +#include <sys/select.h> > > #include <stdio.h> > #include <stdlib.h> > diff -Nur libressl-2.0.2/configure.ac libssl/configure.ac > --- libressl-2.0.2/configure.ac 2014-07-16 05:25:48.000000000 +0200 > +++ libssl/configure.ac 2014-07-16 05:25:48.000000000 +0200 > @@ -25,7 +25,9 @@ > *openbsd*) > AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD gcc has > bounded]) > ;; > - *) ;; > + *) > + CFLAGS="$CFLAGS -D_ALL_SOURCE" > + ;; > esac > > AM_CONDITIONAL(TARGET_DARWIN, test x$TARGET_OS = xdarwin) > diff -Nur libressl-2.0.2/crypto/bio/b_sock.c libssl/crypto/bio/b_sock.c > --- libressl-2.0.2/crypto/bio/b_sock.c 2014-07-16 05:25:49.000000000 > +0200 > +++ libssl/crypto/bio/b_sock.c 2014-07-16 13:26:55.437448072 +0200 > @@ -65,6 +65,7 @@ > #include <netinet/tcp.h> > > #include <errno.h> > +#include <fcntl.h> > #include <limits.h> > #include <netdb.h> > #include <stdio.h> > @@ -462,5 +463,10 @@ > int > BIO_socket_nbio(int s, int mode) > { > - return (BIO_socket_ioctl(s, FIONBIO, &mode) == 0); > + int flags = fcntl(s, F_GETFD); > + if ( mode && !(flags & O_NONBLOCK) ) > + return (fcntl(s, F_SETFL, flags | O_NONBLOCK) == 0); > + else if ( !mode && (flags & O_NONBLOCK) ) > + return (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) == 0); > + return 1; > } > diff -Nur libressl-2.0.2/crypto/err/err.c libssl/crypto/err/err.c > --- libressl-2.0.2/crypto/err/err.c 2014-07-16 05:25:49.000000000 +0200 > +++ libssl/crypto/err/err.c 2014-07-16 13:26:55.437448072 +0200 > @@ -596,7 +596,7 @@ > if (str->string == NULL) { > char (*dest)[LEN_SYS_STR_REASON] = > &(strerror_tab[i - 1]); > - char *src = strerror(i); > + const char *src = strerror(i); > if (src != NULL) { > strlcpy(*dest, src, sizeof *dest); > str->string = *dest; > diff -Nur libressl-2.0.2/ssl/d1_lib.c libssl/ssl/d1_lib.c > --- libressl-2.0.2/ssl/d1_lib.c 2014-07-16 05:25:48.000000000 +0200 > +++ libssl/ssl/d1_lib.c 2014-07-16 13:26:55.441448071 +0200 > @@ -57,7 +57,6 @@ > * > */ > > -#include <sys/param.h> > #include <sys/socket.h> > > #include <netinet/in.h> >