NLnetLabs / unbound

Unbound is a validating, recursive, and caching DNS resolver.
https://nlnetlabs.nl/unbound
BSD 3-Clause "New" or "Revised" License
3.15k stars 360 forks source link

Building statically linked binary for Unbound #299

Open t3lurid3 opened 4 years ago

t3lurid3 commented 4 years ago

Having a wee issue building a single statically linked binary for Unbound - wondering if you could take a peek with me? Looks like the issue is withlibevent

ub_event.o: In function `ub_get_event_sys':
/tmp/unbound-1.11.0/util/ub_event.c:182: undefined reference to `event_get_version'
ub_event.o: In function `ub_event_new':
/tmp/unbound-1.11.0/util/ub_event.c:299: undefined reference to `event_set'
/tmp/unbound-1.11.0/util/ub_event.c:300: undefined reference to `event_base_set'
ub_event.o: In function `ub_signal_new':?
/tmp/unbound-1.11.0/util/ub_event.c:329: undefined reference to `event_assign'
ub_event.o: In function `ub_timer_add':
/tmp/unbound-1.11.0/util/ub_event.c:402: undefined reference to `event_set'
/tmp/unbound-1.11.0/util/ub_event.c:403: undefined reference to `event_base_set'
ub_event.o: In function `ub_event_get_version':
/tmp/unbound-1.11.0/util/ub_event.c:148: undefined reference to `event_get_version'
ub_event.o: In function `ub_default_event_base':
/tmp/unbound-1.11.0/util/ub_event.c:233: undefined reference to `event_init'
ub_event.o: In function `ub_event_base_dispatch':
/tmp/unbound-1.11.0/util/ub_event.c:280: undefined reference to `event_base_dispatch'
ub_event.o: In function `ub_event_base_loopexit':
/tmp/unbound-1.11.0/util/ub_event.c:286: undefined reference to `event_base_loopexit'
ub_event.o: In function `ub_event_add':
/tmp/unbound-1.11.0/util/ub_event.c:389: undefined reference to `event_add'
ub_event.o: In function `ub_event_del':
/tmp/unbound-1.11.0/util/ub_event.c:395: undefined reference to `event_del'
ub_event.o: In function `ub_timer_add':
/tmp/unbound-1.11.0/util/ub_event.c:405: undefined reference to `event_add'
ub_event.o: In function `ub_timer_del':
/tmp/unbound-1.11.0/util/ub_event.c:411: undefined reference to `event_del'
ub_event.o: In function `ub_signal_add':
/tmp/unbound-1.11.0/util/ub_event.c:417: undefined reference to `event_add'
ub_event.o: In function `ub_signal_del':
/tmp/unbound-1.11.0/util/ub_event.c:423: undefined reference to `event_del'
collect2: error: ld returned 1 exit status
make: *** [unbound] Error 1

This is with LDFLAGS=-static and configure script using--with-pthreads --with-libevent=/tmp/libevent-2.0.22-stable --prefix=$TARGETDIR --with-run-dir=/usr/sbin/unbound --with-username= --with-chroot-dir= --enable-fully-static --disable-shared --enable-event-api --disable-flto

Thanks!

wcawijngaards commented 4 years ago

Perhaps there is no static library for libevent in the /tmp/ dir? Many makefiles build only dynamic .so files and not the static .a library you need. You may need to instruct it with --disable-shared like you did with unbound.

Otherwise you need to show the link line, the Makefile line that it did before the error printout, and then look at the paths for includes, and -L libs and what libevent is getting pulled in.

t3lurid3 commented 4 years ago

Tested with both libevent 2.1.12 and libevent 2.0.22 with configure commands ./configure --prefix=$TARGETDIR --enable-static but it fails at same point.

Last link line before it fails:

libtool: link: gcc -I. -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -g -O2 -pthread -o unbound acl_list.o cachedump.o daemon.o shm_main.o remote.o stats.o unbound.
o worker.o dns.o infra.o rrset.o dname.o msgencode.o as112.o msgparse.o msgreply.o packed_rrset.o iterator.o iter_delegpt.o iter_donotq.o iter_fwd.o iter_hints.o iter_
priv.o iter_resptype.o iter_scrub.o iter_utils.o localzone.o mesh.o modstack.o view.o outbound_list.o alloc.o config_file.o configlexer.o configparser.o fptr_wlist.o e
dns.o locks.o log.o mini_event.o module.o net_help.o random.o rbtree.o regional.o rtt.o dnstree.o lookup3.o lruhash.o slabhash.o tcp_conn_limit.o timehist.o tube.o win
sock_event.o autotrust.o val_anchor.o rpz.o validator.o val_kcache.o val_kentry.o val_neg.o val_nsec3.o val_nsec.o val_secalgo.o val_sigcrypt.o val_utils.o dns64.o cac
hedb.o redis.o authzone.o respip.o netevent.o listen_dnsport.o outside_network.o ub_event.o keyraw.o sbuffer.o wire2str.o parse.o parseutil.o rrdef.o str2wire.o strlca
t.o strlcpy.o explicit_bzero.o reallocarray.o arc4random.o arc4random_uniform.o arc4_lock.o getentropy_linux.o  -L/tmp/libevent-2.1.12-stable/lib -lssl -lcrypto -pthread -Wl,-rpath -Wl,/tmp/libevent-2.1.12-stable/lib
ub_event.o: In function `ub_get_event_sys':
t3lurid3 commented 4 years ago

Some progress. Read the link lines again as you suggested and I added CFLAGS="-I$TARGETDIR/libevent-2.1.12-stable/include" LDFLAGS="-L$TARGETDIR/lib" to configure and it compiled.

Note: $TARGETDIR="/tmp"

libtool: link: gcc -I. -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -I/tmp/libevent-2.1.12-stable/include -pthread -o unbound-control unbound-control.o worker_cb.o dns.o infra.o rrset.o dname.o msgencode.o as112.o msgparse.o msgreply.o packed_rrset.o
iterator.o iter_delegpt.o iter_donotq.o iter_fwd.o iter_hints.o iter_priv.o iter_resptype.o iter_scrub.o iter_utils.o localzone.o mesh.o modstack.o view.o outbound_list.o alloc.o config_file.o configlexer.o configparser.o fptr_wlist.o edns.o locks.o log.o
 mini_event.o module.o net_help.o random.o rbtree.o regional.o rtt.o dnstree.o lookup3.o lruhash.o slabhash.o tcp_conn_limit.o timehist.o tube.o winsock_event.o autotrust.o val_anchor.o rpz.o validator.o val_kcache.o val_kentry.o val_neg.o val_nsec3.o val
_nsec.o val_secalgo.o val_sigcrypt.o val_utils.o dns64.o cachedb.o redis.o authzone.o respip.o netevent.o listen_dnsport.o outside_network.o ub_event.o keyraw.o sbuffer.o wire2str.o parse.o parseutil.o rrdef.o str2wire.o snprintf.o strlcat.o strlcpy.o exp
licit_bzero.o reallocarray.o arc4random.o arc4random_uniform.o arc4_lock.o getentropy_linux.o  -L/tmp/lib -L/tmp/libevent-2.1.12-stable/lib -lssl /tmp/lib/libevent.a -lcrypto -pthread -Wl,-rpath -Wl,/tmp/libevent-2.1.12-stable/lib
./libtool --tag=CC --mode=compile gcc -I.  -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -I/tmp/libevent-2.1.12-stable/include -pthread  -o unbound-anchor.lo -c smallapp/unbound-anchor.c
libtool: compile:  gcc -I. -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -I/tmp/libevent-2.1.12-stable/include -pthread -c smallapp/unbound-anchor.c -o unbound-anchor.o
./libtool --tag=CC --mode=link gcc -all-static -R/tmp/libevent-2.1.12-stable/lib -I.  -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -I/tmp/libevent-2.1.12-stable/include -pthread -L/tmp/lib -L/tmp/libevent-2.1.12-stable/lib -all-static -o unbound-ancho
r unbound-anchor.lo parseutil.lo snprintf.lo strlcat.lo strlcpy.lo explicit_bzero.lo reallocarray.lo arc4random.lo arc4random_uniform.lo arc4_lock.lo getentropy_linux.lo   -L. -L.libs -lunbound -lexpat -lssl -levent  -lcrypto
libtool: link: gcc -I. -I/tmp/libevent-2.1.12-stable/include -DSRCDIR=. -I/tmp/libevent-2.1.12-stable/include -pthread -o unbound-anchor unbound-anchor.o parseutil.o snprintf.o strlcat.o strlcpy.o explicit_bzero.o reallocarray.o arc4random.o arc4random_un
iform.o arc4_lock.o getentropy_linux.o  -L/tmp/lib -L/tmp/libevent-2.1.12-stable/lib -L. -L.libs /tmp/unbound-1.11.0/.libs/libunbound.a -lexpat -lssl /tmp/lib/libevent.a -lcrypto -pthread -Wl,-rpath -Wl,/tmp/libevent-2.1.12-stable/lib

Still some dynamic linking occurring so I'm not there yet.

$ ldd unbound
        linux-vdso.so.1 =>  (0x00007ffebbbb6000)
        libssl.so.10 => /lib64/libssl.so.10 (0x00007fcc633c3000)
        libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fcc62f60000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fcc62d44000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fcc62976000)
        libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fcc62729000)
        libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fcc62440000)
        libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fcc6223c000)
        libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fcc62021000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fcc61e1d000)
        libz.so.1 => /lib64/libz.so.1 (0x00007fcc61c07000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fcc63635000)
        libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fcc619f8000)
        libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fcc617f4000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fcc615da000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fcc613b3000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fcc61151000)
wcawijngaards commented 4 years ago

These are the link lines for unbound-control and unbound-anchor, you are looking for earlier link lines with -o unbound that links unbound. I see that unbound-anchor gets -all-static, twice even, but unbound-control does not. Also if you pass -static, but then the --enable-fully-static option sets -all-static, perhaps this causes a different result, I would think only one is what you need to do.

johanix commented 4 years ago

Hi Wouter!

I'm having the same problem. This is with unbound 1.11 on a Linux Buster machine. I use (for the purpose of trying to build a static binary) the following arguments to ./configure:

./configure --enable-static-exe --enable-fully-static --disable-flto --disable-shared

Here is the result from trying to link the "unbound" binary:

libtool: link: gcc -static -I. -DSRCDIR=. -g -O2 -pthread -o unbound acl_list.o cachedump.o daemon.o shm_main.o remote.o stats.o unbound.o worker.o dns.o infra.o rrset.o dname.o msgencode.o as112.o msgparse.o msgreply.o packed_rrset.o iterator.o iter_delegpt.o iter_donotq.o iter_fwd.o iter_hints.o iter_priv.o iter_resptype.o iter_scrub.o iter_utils.o localzone.o mesh.o modstack.o view.o outbound_list.o alloc.o config_file.o configlexer.o configparser.o fptr_wlist.o edns.o locks.o log.o mini_event.o module.o net_help.o random.o rbtree.o regional.o rtt.o dnstree.o lookup3.o lruhash.o slabhash.o tcp_conn_limit.o timehist.o tube.o winsock_event.o autotrust.o val_anchor.o rpz.o validator.o val_kcache.o val_kentry.o val_neg.o val_nsec3.o val_nsec.o val_secalgo.o val_sigcrypt.o val_utils.o dns64.o cachedb.o redis.o authzone.o respip.o netevent.o listen_dnsport.o outside_network.o ub_event.o keyraw.o sbuffer.o wire2str.o parse.o parseutil.o rrdef.o str2wire.o strlcat.o strlcpy.o arc4random.o arc4random_uniform.o arc4_lock.o -lssl -lcrypto -pthread /usr/bin/ld: unbound.o: in function perform_setup': /johani/src/unbound-1.11.0/daemon/unbound.c:599: warning: Using 'initgroups' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /johani/src/unbound-1.11.0/daemon/unbound.c:429: warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /johani/src/unbound-1.11.0/daemon/unbound.c:604: warning: Using 'endpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: remote.o: in functionadd_open': /johani/src/unbound-1.11.0/daemon/remote.c:312: warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(b_sock.o): in function BIO_gethostbyname': (.text+0x71): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: wire2str.o: in functionsldns_wire2str_wks_scan': /johani/src/unbound-1.11.0/sldns/wire2str.c:1489: warning: Using 'getprotobynumber' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /johani/src/unbound-1.11.0/sldns/wire2str.c:1526: warning: Using 'endprotoent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: str2wire.o: in function sldns_str2wire_wks_buf': /johani/src/unbound-1.11.0/sldns/str2wire.c:1720: warning: Using 'getprotobyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /johani/src/unbound-1.11.0/sldns/str2wire.c:1729: warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: wire2str.o: in functionsldns_wire2str_wks_scan': /johani/src/unbound-1.11.0/sldns/wire2str.c:1523: warning: Using 'endservent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in function dlfcn_globallookup': (.text+0x11): undefined reference todlopen' /usr/bin/ld: (.text+0x24): undefined reference to dlsym' /usr/bin/ld: (.text+0x2f): undefined reference todlclose' /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in function dlfcn_bind_func': (.text+0x1a8): undefined reference todlsym' /usr/bin/ld: (.text+0x272): undefined reference to dlerror' /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in functiondlfcn_load': (.text+0x2e1): undefined reference to dlopen' /usr/bin/ld: (.text+0x359): undefined reference todlclose' /usr/bin/ld: (.text+0x395): undefined reference to dlerror' /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in functiondlfcn_pathbyaddr': (.text+0x451): undefined reference to dladdr' /usr/bin/ld: (.text+0x4b6): undefined reference todlerror' /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcrypto.a(dso_dlfcn.o): in function dlfcn_unload': (.text+0x682): undefined reference todlclose' collect2: error: ld returned 1 exit status make: *** [Makefile:344: unbound] Error 1

Regards, Johan

wcawijngaards commented 4 years ago

Hi Johan, You are using a libssl that requires libdl. You would need to use a different openssl version, compiled for static linking without the libdl library. Unbound adds it to satisfy the libcrypto and libssl libraries from OpenSSL. Those are for the dl... symbols. The glibc symbols need a static library like musl or so and then compile with that. That is then used instead of glibc and then it should work. If you are okay with a 'less static' build, only use the --enable-static-exe option, without the --enable-fully-static option. By the way you only need --enable-fully-static, without --enable-static-exe. They should not really be there at the same time.

PikuZheng commented 2 years ago

same problem here.

/usr/local/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
dso_dlfcn.c:(.text+0x11): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x24): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x2f): undefined reference to `dlclose'
/usr/local/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_bind_func':
dso_dlfcn.c:(.text+0x1a4): undefined reference to `dlsym'
dso_dlfcn.c:(.text+0x262): undefined reference to `dlerror'
/usr/local/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_load':
dso_dlfcn.c:(.text+0x2d1): undefined reference to `dlopen'
dso_dlfcn.c:(.text+0x349): undefined reference to `dlclose'
dso_dlfcn.c:(.text+0x382): undefined reference to `dlerror'
/usr/local/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_pathbyaddr':
dso_dlfcn.c:(.text+0x421): undefined reference to `dladdr'
dso_dlfcn.c:(.text+0x481): undefined reference to `dlerror'
/usr/local/lib/libcrypto.a(dso_dlfcn.o): In function `dlfcn_unload':
dso_dlfcn.c:(.text+0x662): undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
Makefile:360: recipe for target 'unbound' failed
make: *** [unbound] Error 1

command:./configure --enable-systemd=libsystemd0 --enable-fully-static --enable-cachedb --with-libexpat=/usr --with-libevent

wcawijngaards commented 2 years ago

The libcrypto from openssl is compiled with the module loading functionality. This calls dlfcn functions, and these use the dlopen functions from libc. That are not present in the libc that is used, and the compilation fails. The module loading functionality of openssl is optional, and you are (edit:)probably not using it, because I guess some small VM (edit:)likely does not contain optional loadable modules, so you could just as well configure openssl to compile without the module loading functionality. Try configure options like no-dynamic-engine and no-module to disable the crypto as dynamic library code, but the Configure script for openssl notes that some libc getaddrinfo and calls like that use dlopen functionality and that then cannot be avoided.

PikuZheng commented 2 years ago

The libcrypto from openssl is compiled with the module loading functionality. This calls dlfcn functions, and these use the dlopen functions from libc. That are not present in the libc that is used, and the compilation fails. The module loading functionality of openssl is optional, and you are (edit:)probably not using it, because I guess some small VM (edit:)likely does not contain optional loadable modules, so you could just as well configure openssl to compile without the module loading functionality. Try configure options like no-dynamic-engine and no-module to disable the crypto as dynamic library code, but the Configure script for openssl notes that some libc getaddrinfo and calls like that use dlopen functionality and that then cannot be avoided.

thanks for reply and this solution worked for me as follow: after configure, modify Makefile, add -ldl at the END of line 'LIBS'

I need dns-over-tls, so I can't give up openssl

wcawijngaards commented 2 years ago

Really, just add -ldl to LIBS. There is a check in the configure of Unbound to add -ldl if needed, it must not be working right. Could you attach the output of configure and the config.log file so that I can take a look at that? If libcrypto does not link without -ldl, there should have been a check that added that to LIBS.

PikuZheng commented 2 years ago

as you wish :) config.log cofigure.out.txt also tried configure with --with-libs="-ldl" but there is LIBS=-levent -ldl -lcrypto , cause the same error at compile time.

wcawijngaards commented 2 years ago

Somehow it can link with libcrypto just fine, like this, in the config.log:

configure:18262: checking if libssl needs libdl
configure:18282: gcc -o conftest  -g -O2 -D_GNU_SOURCE -pthread  -I/usr/local/include  -L/usr/local/lib conftest.c -lssl  -lcrypto >&5

And that does not need -ldl on the link line, this is what it checked.

sbwml commented 1 year ago

Hi Guys, I built a full static unbound in GitHub runner.

https://github.com/sbwml/unbound-static