On 03/26/2014 08:21 PM, Linda Walsh wrote: > > > Pádraig Brady wrote: >> On 03/26/2014 06:08 PM, Linda Walsh wrote: >>> have a simple test case: >>> as root (w /umask 002): >>> >>> mkdir -p dir/{a,b} >>> touch dir/b/file >>> ln -s ../b/file dir/a/symfile >>> --- >>> >>> So now tree should look like: >>> >>>> tree -AFugp dir >>> dir >>> +-- [drwxrwxr-x root root ] a/ >>> | +-- [lrwxrwxrwx root root ] symfile -> ../b/file >>> +-- [drwxrwxr-x root root ] b/ >>> +-- [-rw-rw-r-- root root ] file >>> ---- >>> >>> Now, w/normal user, who is in group root, try: >>> >>> cp -al dir dir2 >>> cp: cannot create hard link ‘dir2/dir/a/symfile’ to ‘dir/a/symfile’: >>> Operation not permitted >>> ----- >>> >>> Trying to link to a symlink is the bug -- >>> it used to duplicate the symlink. >>> >>> This is a recent behavior >>> change -- i.e. looking at earlier behavior, the symlinks, >>> like the directories are created as the 'user', and >>> only files are linked to. >>> >>> Core utils version: 8.21 (suse rpm coreutils-8.21-7.7.7.x86_64) >>> >>> Any idea how this managed to be broken? >> >> So I think the change to use hardlinks to symlinks rather than new symlinks >> happened with: >> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=594292a1 >> >> I.E. The "new symlink" behaviour only happened between v8.0 and v8.10 >> inclusive. >> >> So why is the hardlink to symlink being disallowed? >> I wonder is it due to "protected_hardlinks": >> http://danwalsh.livejournal.com/64493.html > ---- > As far as I know, you could never hardlink > to a symlink. only to a file. A symlink is more like > a directory in that regard. > > Looking at the article, it doesn't seem it should apply...it > says > 1) The solution is to permit symlinks to only be followed when outside a > sticky world-writable directory, > [it isn't in 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. > [in the created dir, the symlink and directory owner match] > 2) The solution is to permit hardlinks to only be created when the user is > already the existing file's owner, or if they already have read/write access > to the existing file. > [ Already have r/w access to the file via being in group root and the group > having write access] > > I think I did run into this change, though, and because of it, my system > is less secure. ... I.e. in my use case, am copying a source tree > into a 2nd tree. I am the directory owner of all dirs in the 2nd tree, > but all the source files should allow my linking to it as the permissions > on the inode protect the contents of the inode. The access to create a > hardlink to that inode has always been controlled by the directory owner, > but it never gives them write access to the content. > > Their exploit case was for a stupid admin who chowned all files in a user's > dir "for them" -- why would that EVER be done? I.e. the root admin should > be immediately suspicious as to why they'd need that done. Since you > can't hardlink directories, the only way for a foreign owned directory > to get into someone's home space, would be if they opened the permissions > on the parent then later closed them. > > The whole premise of their change relies on the user tricking the admin. > > But if that's so easy, the user already has root access, effectively, > and the games up. > > >> >> If we fell back to using symlinks, would that only >> push the perm issue on to when the symlink was followed? > ---- > No, the file it points to, if you look at my example > is rw for the 'group' members.
That is true, but I confirmed that this is caused by "protected_hardlinks" Perhaps there is a blanket ban on symlinks if you're not the owner, since the symlink could be later changed to point somewhere more sensitive? Kees do you know if this is the case? $ ln dir/b/file flink $ ln dir/a/symfile slink ln: failed to create hard link ‘slink’ => ‘dir/a/symfile’: Operation not permitted tp2:lt$ echo 0 | sudo tee /proc/sys/fs/protected_hardlinks 0 $ ln dir/a/symfile slink $ rm slink # And to demonstrate that "protected_symlinks" doesn't seem to be significant here: $ echo 1 | sudo tee /proc/sys/fs/protected_hardlinks 1 $ echo 0 | sudo tee /proc/sys/fs/protected_symlinks 0 $ ln dir/a/symfile slink ln: failed to create hard link ‘slink’ => ‘dir/a/symfile’: Operation not permitted So should we fall back to our symlink emulation if we get EPERM from linkat() ? I'd like to get some more info on this behavior before doing that though. thanks, Pádraig.