This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/11643] New: ldopen failing with relative path ($ORIGIN) when a capability is set
- From: "bugeaud at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 28 May 2010 16:28:48 -0000
- Subject: [Bug libc/11643] New: ldopen failing with relative path ($ORIGIN) when a capability is set
- Reply-to: sourceware-bugzilla at sourceware dot org
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
--
Summary: ldopen failing with relative path ($ORIGIN) when a
capability is set
Product: glibc
Version: unspecified
Status: NEW
Severity: critical
Priority: P2
Component: libc
AssignedTo: drepper at redhat dot com
ReportedBy: bugeaud at gmail dot com
CC: glibc-bugs at sources dot redhat dot com
http://sourceware.org/bugzilla/show_bug.cgi?id=11643
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.