Hi Assaf, > --- se-good.c --- > extern char setfilecon(); > int main(){return setfilecon();} > > --- se-bad.c --- > extern char matchpathcon_init_prefix(); > int main(){return matchpathcon_init_prefix();} > > > $ gcc -o 1 -static se-good.c -lselinux && echo ok > ok > > $ gcc -o 1 -static se-bad.c -lselinux
When a shared library depends on other shared libraries, you don't have to specify the dependencies; ELF cares about that. But when you are linking statically, you need the dependencies. An installed .la file would provide this information, but unfortunately the distros don't ship a libselinux.la file. So you have to put the knowledge about the dependencies into the .m4 file. In this case: $ ldd /lib/x86_64-linux-gnu/libselinux.so.1 linux-vdso.so.1 => (0x00007ffda95ee000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f9f1d00a000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9f1ce06000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9f1ca3c000) /lib64/ld-linux-x86-64.so.2 (0x00007f9f1d49c000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9f1c81f000) So, you see, it depends on -lpcre and -lpthread. $ gcc -o 1 -static se-bad.c -lselinux /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libselinux.a(label_file.o): In function `closef': (.text+0x136): undefined reference to `pcre_free' ... pcre_free is contained in libpcre. $ gcc -o 1 -static se-bad.c -lselinux -lpcre /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libselinux.a(load_policy.o): In function `selinux_mkload_policy': (.text+0x11f): undefined reference to `sepol_policy_kern_vers_max' ... sepol_policy_kern_vers_max is contained in libsepol. $ gcc -o 1 -static se-bad.c -lselinux -lpcre -lsepol /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libpcre.a(libpcre_la-pcre_jit_compile.o): In function `sljit_generate_code': (.text+0x6d1): undefined reference to `pthread_mutex_lock' ... pthread_mutex_lock is contained in libpthread. $ gcc -o 1 -static se-bad.c -lselinux -lpcre -lsepol -lpthread /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libselinux.a(seusers.o): In function `getseuserbyname': (.text+0x574): warning: Using 'getgrouplist' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libselinux.a(seusers.o): In function `getseuserbyname': (.text+0x546): warning: Using 'getgrnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libselinux.a(seusers.o): In function `getseuserbyname': (.text+0x433): warning: Using 'getpwnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking $ echo $? 0 So, these are the libraries that are needed. Apparently libselinux is built in such a way that it needs libdl in the shared build, but libsepol in the static build. > Perhaps it used to be that "matchpathcon_init_prefix" was optional > when building with selinux? > > It seems that now it is required. matchpathcon_init_prefix is declared in gnulib's lib/se-selinux.in.h since the beginning. It's not a later addition. > tweaking m4/selinux combinations is beyond my comfort zone... > the following hack at least avoids the issue by detecting that > linking with "matchpathcon_init_prefix" fails, thus automatically > disabling SELinux for static builds: > > --- > diff --git a/m4/selinux-selinux-h.m4 b/m4/selinux-selinux-h.m4 > index 8bbbf0535..a35ce6cf0 100644 > --- a/m4/selinux-selinux-h.m4 > +++ b/m4/selinux-selinux-h.m4 > @@ -56,12 +56,13 @@ AC_DEFUN([gl_LIBSELINUX], > AC_SEARCH_LIBS([setfilecon], [selinux], > [test "$ac_cv_search_setfilecon" = "none required" || > LIB_SELINUX=$ac_cv_search_setfilecon]) > + AC_CHECK_LIB([selinux], [matchpathcon_init_prefix], [], []) > LIBS=$gl_save_LIBS > fi > AC_SUBST([LIB_SELINUX]) > > # Warn if SELinux is found but libselinux is absent; > - if test "$ac_cv_search_setfilecon" = no; then > + if test "$ac_cv_search_setfilecon" = no || test > "$ac_cv_lib_selinux_matchpathcon_init_prefix" = no ; then > if test "$host" = "$build" && test -d /selinux; then > AC_MSG_WARN([This system supports SELinux but libselinux is > missing.]) > AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux > support.]) > --- It would be better to instead set LIB_SELINUX to "-lselinux -lpcre -lsepol -lpthread" (in the static case). Bruno