Charles Duffy
Charles Duffy

Reputation: 295472

EACCES during hardlink creation on Linux not matching any reason in link(2) man page

I have a service which assembles hardlinks to a group of files to which it has read but not write access (and traversal permissions for all parent directory trees) into a transient staging directory.

This worked perfectly, until my AWS-hosted nodes were rebooted. It appears that they're on a newer kernel now, and the link(2) calls now return EACCES.

Checking the (Linux) man page for this syscall:

EACCES - Write access to the directory containing newpath is denied, or search permission is denied for one of the directories in the path prefix of oldpath or new‐path. (See also path_resolution(7).)

For comparison, the BSD version appears to describe similar semantics, perhaps in slightly more detail:

[EACCES] A component of either path prefix denies search permission.

[EACCES] The requested link requires writing in a directory with a mode that denies write permission.

[EACCES] The current process cannot access the existing file.

None of these situations applies: As the user running the service, I can read the source file (including traversing to its directory), and write to the temporary staging directory (which, indeed, I created); moreover, that staging directory is on the same filesystem (though this would have caused a different error).

What gives?

Upvotes: 2

Views: 42

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295472

When rebooting, the new kernel booted into set fs.protected_hardlinks=1 by default. This was added as default behavior in late 2012. When this sysctl is set, Linux requires write access to a file before another user is allowed to create a hardlink to it.

This is technically compatible with the relevant POSIX specification, which states in part:

The implementation may require that the calling process has permission to access the existing file.


However, newer upstream kernels have this off by default, due to its observed ability to break third-party software. Thus, it was in the present instance either reenabled by a vendor, or based on an upstream kernel from the time period between when it was introduced and later disabled.

Upvotes: 2

Related Questions