Skip to main content

Linux symlink restrictions

This happened:

$ uname -sr && id
Linux 3.8-trunk-amd64
uid=1000(dummy) gid=1000(dummy) groups=1000(dummy)

$ ln -s /usr/local/src /tmp/foo
$ ^D

# id
uid=0(root) gid=0(root) groups=0(root)

# ls -l /tmp/foo
lrwxrwxrwx 1 dummy dummy 14 Mar  7 21:30 /tmp/foo -> /usr/local/src

# ls -l /tmp/foo/
ls: cannot access /tmp/foo/: Permission denied
Huh? root is not allowed to follow a user's symlink? Turns out this is a feature now:
  > The solution is to permit symlinks to only be followed when outside
  > a sticky world-writable directory, or when the uid of the symlink and
  > follower match, or when the directory owner matches the symlink's owner.
And since /tmp usually has the sticky bit set, the access to /tmp/foo is denied. This access restriction is accompanied by audit messages:
 type=1702 audit(1362720689.110:28): op=follow_link action=denied \
           pid=22758 comm="ls" path="/tmp/foo" dev="sda1" ino=252
This can be tweaked via sysctl:
# sysctl -w fs.protected_symlinks=0
fs.protected_symlinks = 0

# ls -l /tmp/foo/
total 12092
-rw-r--r-- 1 root  staff    6794 Jan  9 22:59 bar

# sysctl -a | grep protected
fs.protected_hardlinks = 1
fs.protected_symlinks = 0
...but the default (fs.protected_symlinks=1) is kinda neat, now that I know about it :-)