Whilst reading this, I found the following exploit:
% cp /usr/bin/id ~
% chmod -x ~/id
% ls -al ~/id
-rw-r--r-- 1 edd edd 22020 2012-08-01 15:06 /home/edd/id
% ~/id
zsh: permission denied: /home/edd/id
% /lib/ld-linux.so.2 ~/id
uid=1001(edd) gid=1001(edd) groups=1001(edd),1002(wheel)
This snippet shows that we can trivially sidestep the filesystem's execute permissions as a normal unprivileged user. I ran this on an Ubuntu 12.04.
Whilst the Linux loader is a shared object according to file(1), it also has an entry point which allows it to be executed directly. When executed in this way the Linux loader acts as an interpreter for ELF binaries.
On my OpenBSD machine, however, this exploit is not effective, because you may not execute the loader as a program. The OpenBSD manual page says: "ld.so is itself a shared object that is initially loaded by the kernel.".
Try this on Solaris 9, and you will get a segfault. I am not sure what happens elsewhere.
My questions are therefore:
- Why does the Linux loader (when executed directly) not check the filesystem attributes before interpreting an ELF binary?
- Why implement a mechanism which is designed disallow execution of files, if it is so trivially sidestepped? Have I missed something?
libc
(I did once, upgrading an Arch box), you'll be thankful for this little quirk.