I'm filing this bug to find a different way to transparently reconfigure libcap to use the libpsx functions when a binary is linked with both -lcap and -lpsx. The intention being that this linking arrangement causes libcap to operate with a shared security context over the process. Today, libcap recognizes that libpsx has been linked by calling psx_load_syscall() at library initialization time. Inside libcap, this function is actually defined as __attribute__((weak)) psx_load_syscall(...) and the same function is defined in libpsx, but not with a weak attribute. So, if libpsx is linked into the application, libpsx's version dominates that of libcap. This combines to cause the libpsx version to provide the needed functions when libcap:cap_set_syscall() calls it. In libcap-2.71 and earlier, libpsx could be forced to be linked because it was the library that provided the only definition of __real_pthread_create() and the linkage instructions for -lpsx were: -wrap,pthread_create -lpsx which required __real_thread_create() to exist somewhere in the linked binary. With libpsx-2.72 (not yet released) we've rewritten libpsx to not implement its functionality with respect to the pthread abstraction, but against Linux's native thread implementation. As such, the only remaining reason for the wrapping is to force libpsx to be linked against the binary. So, strictly speaking, the pthread_create() function is no longer important to libpsx use. However, I've not yet found an alternate way to force libpsx.a or libpsx.so to actually link in the quiet libcap linking mode I want. So, I've had to retain the -wrap stuff with what will become libcap-2.72. This bug is to find a better way to silently help libcap recognize it has been linked to a binary with libpsx, and to force -lpsx to actually link against a binary when nothing in that binary calls libpsx functions.
https://stackoverflow.com/questions/35425185/is-it-possible-to-determine-at-runtime-if-a-function-has-been-implemented looks interesting.
This seems to explain what I see with the static link: https://stackoverflow.com/a/37191811/14760867 Namely, with --- a/Make.Rules +++ b/Make.Rules @@ -107,7 +107,7 @@ endif USE_GPERF ?= $(shell which gperf >/dev/null 2>/dev/null && echo yes) LIBCAPLIB := -L$(topdir)/libcap -lcap -PSXLINKFLAGS := -lpthread -Wl,-wrap,pthread_create +PSXLINKFLAGS := -lpthread LIBPSXLIB := -L$(topdir)/libcap -lpsx $(PSXLINKFLAGS) INCS=$(topdir)/libcap/include/sys/capability.h $ make clean all test sudotest [...] sudo ./noexploit ; if [ $? -eq 0 ]; then exit 0; else exit 1 ; fi program starting started privileged thread dropping privilege from main process thread no privilege in main process thread: len:1, caps:"=" greatest privilege in main process thread: len:3, caps:"=ep" exploit succeeded So, without the wrapping the exploit succeeds. The reason appears to be that nothing is forcing the linking of libpsx.a in this static link case. If I manually run: $ cd tests $ gcc -O2 -Wall -Wwrite-strings -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wshadow -Wunreachable-code --static exploit.o -o noexploit -L/home/andrew/gits/libcap/tests/../libcap -lcap -Wl,--whole-archive -lpsx -Wl,--no-whole-archive -lpthread $ sudo ./noexploit program starting started privileged thread dropping privilege from main process thread no privilege in main process thread: len:1, caps:"=" greatest privilege in main process thread: len:1, caps:"=" exploit failed Evidently the `-Wl,--whole-archive -lpsx -Wl,--no-whole-archive` flags seem to force the linking I want.
This is an interesting detail that may help with shared libraries: https://stackoverflow.com/a/27973583/14760867
I think I may have a new linkage strategy. More with the commits when I have more completely tested them.
Fixed with: https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=b017fcff26c5fc7a37e607b881c84abddfc946a5