Call to ldopen is failing when a POSIX capability is set on the file and a $ORIGIN relative path is given. Relative path is used in some major tool such as the Java VM when required to grant bind on port less than 1024 without giving the SU rights (for obvious security reasons). The impacted applications are : applications server, mail servers, etc ... all running Java. But other modular softwares in C/C++ are impacted as well. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6919633 And https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/565002 For capability priviledge port bind, the only work-around are : - patch the binary containing the $ORIGIN an replace it with code absolute path (ugly, isn't it?) - use a iptable PAT redirection (prevent dynamic bind as you have to know beforehand the port value to create a rule) : make configuration complex and bring some limitations. For other capabilities, there might be no workaround but to go with the setuid :( Here is example of a program helping to reveal the potential bug : #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> #include <unistd.h> int main(int argc, char *argv[]){ void *handle; double (*cosine)(double); char *error; printf("UID=%d EffUID=%d\n", getuid(), geteuid()); handle = dlopen (argv[1], RTLD_LAZY); if (!handle) { fprintf (stderr, "%s\n", dlerror()); exit(1); } dlerror(); /* Clear any existing error */ cosine = dlsym(handle, argv[2]); if ((error = dlerror()) != NULL) { fprintf (stderr, "%s\n", error); exit(1); } printf ("res:%f\n", (*cosine)(2.0)); dlclose(handle); return 0; } Let's compile that : gcc -o bug-cap-origin -ldl bug-cap-origin.c cp bug-cap-origin ~ cd ~ Step 1 : Initial checkings getcap bug-cap-origin -> empty result (= no capabilities set at this time) ./bug-cap-origin '/usr/lib64/libm.so' sin -> OK: display the sin result ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> OK: display the sin result sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> OK: display the sin result Step 2 : Assign a capability to the file and check again ... to get the problem sudo setcap cap_net_bind_service=+epi bug-cap-origin --> empty result (=capability was set) ./bug-cap-origin '/usr/lib64/libm.so' sin -> OK: display the sin result ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> KO !!! : Message displayed = "$ORIGIN/../../usr/lib64/libm.so: cannot open shared object file: No such file or directory" sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> OK: display the sin result Step 3 : Removing the capability solve the problem sudo setcap -r bug-cap-origin -> empty result (= capability was removed) ./bug-cap-origin '/usr/lib64/libm.so' sin -> OK: display the sin result ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> OK: display the sin result sudo ./bug-cap-origin '$ORIGIN/../../usr/lib64/libm.so' sin -> OK: display the sin result Am I wrong somewhere ($ORIGIN see http://sources.redhat.com/bugzilla/show_bug.cgi?id=4177 )or is the ldopen having issues with relative path when Linux capabilities are set ? Test was done on : ld-2.11.1 gcc 4.3.3 Linux 2.6.32-20-generic Ubuntu 10.04
This is not a bug. It's a security feature. $ORIGIN can be abused to load different libraries into the process and effect a privilege escalation. So, like LD_LIBRARY_PATH, it is disabled in a process that is setuid or similarly privileged. The Linux kernel decides what constitutes "setuid-like" by setting the AT_SECURE parameter at exec time. libc just follows that. If you want the rules for that changed, take it up with the kernel people.
My understanding is that, when AT_SECURE is set it is up to the glibc to decide what to do with it, and as in the example given UID=EUID there is no superuser escalation possible. So $ORIGIN chould be safe, as the only extra feature granted on the process is set using the capabilities (file system level granted by root) and no other capabilities can be added by the user. In that context, this means that when AT_SECURE is set glibc should perform its own check. Something like : if EUID==UID then grantOriginEscaping else forbidOriginEscaping
You seem to misunderstand the nature of security checks and privilege escalation risks. This is not the place to get educated. Do not reopen this bug.
Either #4177 is obsolete, or my guess is that I will be quite difficult for anyone to "get educated" on $ORIGIN behaviour "nominal behavior" and the expected impact on security when wokring with POSIX capabilities. I know "code is the reference" but having to dig in glibc internals and even kernel (!!) for only making sure how something should behave "by design" always taste bitter to me. So, I will have to a pickaxe and dig the Web & the ML ;) Anyway, thanks Roland.
Roland's point is that bugzilla is for actual bugs, this is not an obvious bug more of a discussion point; if you'd have questions about it, you should ask at libc-help. (Before you do that, consider that AT_SECURE is set by the kernel when the process has more privileges than the user starting it, and thus means for the user to plug in custom code to the process context should be limited - more privileges does not just mean "superuser", the whole point of capabilities is that specific privileges can be abused as well. The moment you allow $ORIGIN for a process with a certain capability, it's just as if you'd simply give all users on the system the capability right away.)
Hello Petr, Thanks for this explanation, this helps to solve the puzzle. To me this is an obvious Bug : I can not use POSIX capabilities and the only workaround is to give SUID ! My understanding of Capabilities was that this is something "less harmfull" than SUID. Because, if you are SUID you don't need them, you own all the caps ! My understanding was also that they are implemented in a secured way. Which means that if I have given somebody a right, he can not goes any further and get nother one "for free" and thus gaining a complete SU status. Am I correct ? In a way, we could rephrase your points by asking : Is POSIX capabilities secured ? Should we use POSIX capabilities as a way of securing Linux based system and removing as much as SU/Sticky bits headaches ? I will try to question the ML, but keep the possibility of reopening this if nobody clarify this security situation. I understand that this is not a simple issue, but I would not have bugged people with something that RFM would solve. Cheers, JB