Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?
share|improve this question
1  
No good reason, but if you've ever managed to delete your system's libc (I did once, upgrading an Arch box), you'll be thankful for this little quirk. –  new123456 Aug 1 '12 at 14:28
1  
@new123456 oh god, the IRC channel after that upgrade was painful to be in. –  Rob Aug 1 '12 at 15:08
    
It's the loader, not the linker. –  OrangeDog Aug 1 '12 at 15:21
add comment

3 Answers

up vote 31 down vote accepted

The goal of the execute permission is not to prevent execution in general. It is (1) to tell progams which files are meant to be executed, and (2) to prevent execution as a privileged user, when the setuid bit (etc.) is specified.

The linker hack is less of an exploit than it seems. You could execute any non-executable file you have permissions to read even more easily:

$ cp unexecutable_file ~/runme
$ chmod +x ~/runme
$ ~/runme

See this discussion on the Arch Linux forum.

In summary:

Marking files that should be executed

When you write a shell script, you can mark it as executable with chmod +x. This hints to your shell that you intend it to be executable (otherwise for all the shell knows, it's just another plain text file). The shell can then show it in the tab-completion when you type ./Tab.

Similarly: something.d directories (e.g. init.d) contain startup or control shell scripts that are typically executed automatically by daemons. You might want to put a comment or README file in the directory as a plain text file. Or you might want to temporarily disable one of the scripts. You can do so by clearing the execute bit for that particular file. This tells the daemon to skip over it.

Preventing privileged execution

The setuid bit means that when you execute the file, it is executed as a specified user (e.g. root).

The forum post explains it well:

You want an executable to be setuid for some user, but you only want people from a specific group to be able to execute it as setuid. They can still execute it by copying, but the setuid flag gets lost, so they'll be executing it as themselves, rather than the user who owned the original file.

share|improve this answer
1  
Thanks -- I overlooked the fact that the user can copy any file he can read and therefore choose arbitrary permissions. –  vext01 Aug 1 '12 at 14:41
    
how about files with execute permission but no read permission? –  Lie Ryan Aug 1 '12 at 16:54
    
@LieRyan What about them? –  Brendan Long Aug 1 '12 at 20:04
    
@BrendanLong: You obviously can't copy those, so you can't change their permissions. (But why you'd want to, I can't say - the only thing you could do with the copy anyway is dropping the execute permission) –  MSalters Aug 2 '12 at 8:30
add comment

Looking at the question a little differently: as Mechanical Snail says, the execute permission on a file is not intended to prevent execution. However, the filesystem option "noexec" does prevent execution, and is not so easily circumvented (not supported by all filesystems, but certainly by the most popular linux ones). If the administrator wanted to prevent users running programs of their own, they could specify the noexec option on home and tmp directories, and any others where the users may be able to create files.

$ mount -o noexec /dev/sdd1 /test
$ cd /test
$ cp /usr/bin/id .
$ ./id
-bash: ./id: Permission denied

Apparently it used to be possible to circumvent the noexec option using the loader trick mentioned in the question, but that was fixed in the kernel a few versions back.

From http://linux.die.net/man/8/mount:

noexec

Do not allow direct execution of any binaries on the mounted filesystem. (Until recently it was possible to run binaries anyway using a command like /lib/ld*.so /mnt/binary. This trick fails since Linux 2.4.25 / 2.6.0.)

share|improve this answer
add comment

If you have read access to a file, you can always make a copy of it.

If you can make a personal copy, you can always mark that copy executable.

This doesn't explain the bahaviour of ld-linux but does indicate that it may not be a very useful security loophole.

If you want tighter security, consider SELinux

share|improve this answer
    
This is very true. –  vext01 Aug 1 '12 at 14:37
    
It was just a conceptual question. I suppose you could set nonexec on filesystems too. –  vext01 Aug 1 '12 at 14:45
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.