Different Hard Link Permissions Behavior in CentOS 6 vs CentOS 7

centoshard linkpermissions

I'm getting a permissions error in CentOS 7 when I try to create a hard link. With the same permissions set in CentOS 6 I do not get the error. The issue centers on group permissions. I'm not sure which OS version is right and which is wrong.

Let me illustrate what's happening. In my current working directory, I have two directories: source and destination. At the start, destination is empty; source contains a text file.

[root@tc-dlx-nba cwd]# ls -l
total 0
drwxrwxrwx. 2 root root  6 Jun 12 14:33 destination
drwxrwxrwx. 2 root root 21 Jun 12 14:33 source
[root@tc-dlx-nba cwd]# ls -l destination/
total 0
[root@tc-dlx-nba cwd]# ls -l source/
total 4
-rw-r--r--. 1 root root 8 Jun 12 14:20 test.txt
[root@tc-dlx-nba cwd]# 

As you can see, regarding the permissions the two directories are 777, with both the owner and group set to root. The text file's owner and group are also both set to root. However, the text file's permissions are read-write for the owner but read-only for the group.

When I'm logged in as root, I have no problem creating a hard-link in the destination directory pointing to the text file (in the source directory).

[root@tc-dlx-nba cwd]# ln source/test.txt destination/
[root@tc-dlx-nba cwd]# ls destination/
test.txt

However, if I log in as another user, in this case, admin, I cannot create the link. I get: "Operation not permitted."

[root@tc-dlx-nba cwd]# rm -f destination/test.txt 
[root@tc-dlx-nba cwd]# su admin
bash-4.2$ pwd
/root/cwd
bash-4.2$ ln source/test.txt destination/
ln: failed to create hard link ‘destination/test.txt’ => ‘source/test.txt’: Operation not permitted

What happens actually makes sense to me, but since the above is allowed in CentOS 6, I wanted to check to see if I was misunderstanding something. To me, it seems like a bug in CentOS 6 that has been fixed in CentOS 7.

Anyone know what gives? Am I right believing that the above behavior is the correct behavior? Is it CentOS 6 that is correct? Or, are both right and perhaps there is some subtle group permissions issue that I'm missing? Thanks.


Edit: I tried the same test just now on a Debian v7 VM that I have. Debian agrees with CentOS 7: "Operation not permitted."


Edit #2: I just tried the same thing on Mac OS X (Yosemite). That worked the way CentOS 6 did. In other words, it allowed the link to be created. (Note: On OS X, the root group is called "wheel." That's the only difference, as far as I can tell.)

Best Answer

I spun up some fresh CentOS 6 and 7 vm's and was able to recreate the exact behavior you showed. After doing some digging, it turns out that this is actually a change in the kernel regarding default behavior with respect to hard and soft links for the sake of security. The following pages pointed me in the right direction:

http://kernel.opensuse.org/cgit/kernel/commit/?id=561ec64ae67ef25cac8d72bb9c4bfc955edfd415

http://kernel.opensuse.org/cgit/kernel/commit/?id=800179c9b8a1

If you make the file world writable, your admin user will be able to create the hard link.

To revert to the behavior of CentOS 6 system wide, new kernel parameters were added. Set the following in /etc/sysctl.conf:

fs.protected_hardlinks = 0
fs.protected_symlinks = 0

then run

sysctl -p

As for why your program opts to use links instead of copying files, why create an exact copy of a file you need to use when you can just create an entry that points to the original blocks? This saves disk space and the operation is less costly in terms of CPU and I/O. The new hard link is the same file, just with different metadata/inode. If you were to delete the original file after creating a hard link, it won't affect the link. A file is only 'deleted' once all links have been removed.

Related Question