27

I create a file as regular user testuser:

$ cat > /tmp/zz

the file is owned by that user (as expected):

$ ls -lA /tmp/zz 
-rw------- 1 testuser testuser 0 Feb 20 15:32 zz

Now when I try to truncate it as root, I get permission denied:

# truncate --size=0 /tmp/zz
truncate: cannot open '/tmp/zz' for writing: Permission denied

When I try with strace, I see the following:

openat(AT_FDCWD, "/tmp/zz", O_WRONLY|O_CREAT|O_NONBLOCK, 0666) = -1 EACCES (Permission denied)
write(2, "truncate: ", 10truncate: )              = 10
write(2, "cannot open '/tmp/zz' for writin"..., 33cannot open '/tmp/zz' for writing) = 33
...
write(2, ": Permission denied", 19: Permission denied)     = 19
write(2, "\n", 1

Why does root not have permissions to write to that file? Root can delete the file, but not write.

4

1 Answer 1

52

This is a new behavior available on Linux kernels since version 4.19 to prevent attacks using /tmp/ tricks. The default value of the option might have been enabled later or be different depending on the distribution.

(FEATURED) Avoid unintentional writes to an attacker-controlled FIFO or regular file: disallow open of FIFOs or regular files not owned by the user in world writable sticky directories, unless the owner is the same as that of the directory or the file is opened without the O_CREAT flag. The purpose is to make data spoofing attacks harder. This protection can be turned on and off separately for FIFOs (protected_fifos) and regular files (protected_regular) via sysctl, just like the symlinks/hardlinks protection commit

This is intended to protect an user (including root which normally has always enough privileges) to write to a preexisting file in a directory like /tmp or /var/tmp while it would have intended to create it itself.

It's enabled with this sysctl toggle: fs.protected_regular. One can revert to former behavior with:

sysctl -w fs.protected_regular=0

but this will likely lower overall security, while making some strange "bugs" like OP's case disappear.

As for why root could still delete the file, that is because the additional security feature is triggered only for opening a file for writing, not for unlink-ing it: truncate -s ... does open the file for writing, rm doesn't (it uses unlink or unlinkat).

11
  • 5
    This one is going to make a mess. There's going to be bugs back and forth forever.
    – Joshua
    Feb 21, 2022 at 4:01
  • 18
    @Joshua Kernel 4.19 has been out for over 3 years, and the world hasn't ended. I think we'll survive this change.
    – marcelm
    Feb 21, 2022 at 10:28
  • 5
    @trlkly this feature is especially intended to affect the root user: the target of a privilege escalation.
    – A.B
    Feb 21, 2022 at 11:18
  • 3
    @400theCat If an user can guess the file name in advance, it can preseed it with data that an other account (root) thought it would have written on its own. If this data participates in any way to authentication... last CVE in the list (cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7489) has an example: vapidlabs.com/advisory.php?v=173 . It's a feature to prevent a category of bugs in applications. Of course the application should be fixed but...
    – A.B
    Feb 21, 2022 at 17:13
  • 4
    @Joshua Fair enough, it appears it was turned off by default initially. It does seem this was enabled in Ubuntu starting in 20.04, almost two years ago. More conservative distributions may be slower to enable this by default, but with ~2 years exposure in a popular distribution, I still think the fallout of this change isn't all that dramatic.
    – marcelm
    Feb 21, 2022 at 19:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .