29

I experienced a strange behaviour in my /tmp directory. Although a user belongs to a group that has permissions to read/write a file, he cannot do so.

In this example, I create a new file /tmp/test.txt as user max. I give it the 777 permissions and make the file belong to the group root, but user root still cannot edit it.

su max touch /tmp/test.txt chmod 777 /tmp/test.txt su root chown max:root /tmp/test.txt # ls -l /tmp/test.txt -rwxrwxrwx 1 max root 0 26. Feb 12:08 test.txt # echo "foobar" > /tmp/test.txt bash: /tmp/test.txt: Permission denied 

When moving test.txt to a different directory, everything works as expected.

/tmp is a tmpfs mounted via fstab via the following options:

tmpfs /tmp tmpfs nodev,nosuid,size=5G 0 0 

When running ls -l /, the tmp folder looks like the following:

drwxrwxrwt 20 root root 640 26. Feb 12:01 tmp/ 

I am running Manjaro, an Arch Linux derivate.

Did I do something wrong with mounting tmpfs?

4
  • 1
    What user is doing the echo with the redirect. The prompt is that of a non-root user. Commented Feb 26, 2019 at 12:22
  • 2
    We're heading either for unix.stackexchange.com/questions/148592 or for unix.stackexchange.com/questions/336625 + unix.stackexchange.com/questions/209309 I suspect. (-: Commented Feb 26, 2019 at 12:36
  • @Kusalananda Sorry for the ambiguity. The command is run as root (not with sudo, I know about issues with it). Fixed in the answer Commented Feb 26, 2019 at 12:50
  • 1
    @JdeBP Are you sure one of those applies? I neither run the echo with sudo, nor do I work with soft/hardlinks. Commented Feb 26, 2019 at 12:52

1 Answer 1

42

The behavior you are showing seems to depend on the fs.protected_regular Linux kernel parameter, introduced along with fs.protected_fifos by this commit (converged in version 4.19, I believe), with the aim to fix security vulnerabilities.

Excerpt of the commit message (emphasis mine):

namei: allow restricted O_CREAT of FIFOs and regular files

Disallows 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. ...

The same commit message also reports a list of related Common Vulnerabilities and Exposures (CVE) numbers.

Thus, provided that userX is root or is otherwise granted write access to /tmp/file, and that /tmp is a world writable directory with the sticky bit set, they can open file for writing only if:

  • userX is the owner of file; or
  • both file and directory /tmp are owned by the same user.

In your test, root has write permissions on /tmp/test.txt, but is not the owner of the file, nor have /tmp/test.txt and /tmp the same owner (respectively max and root).

The issue appears to be totally unrelated to the way /tmp is mounted.

The relevant documentation is in Documentation/sysctl/fs.txt:

protected_fifos:

The intent of this protection is to avoid unintentional writes to an attacker-controlled FIFO, where a program expected to create a regular file.

...

protected_regular:

This protection is similar to protected_fifos, but it avoids writes to an attacker-controlled regular file, where a program expected to create one.

When set to "0", writing to regular files is unrestricted.

When set to "1" don't allow O_CREAT open on regular files that we don't own in world writable sticky directories, unless they are owned by the owner of the directory.

When set to "2" it also applies to group writable sticky directories.

That is, the protection described above can be disabled with the command:

sysctl fs.protected_regular=0 

A bit of testing to backup our hypothesis:

$ su - root # sysctl fs.protected_regular fs.protected_regular = 1 # cd / # mkdir test # chmod 1777 test # su - otheruser $ echo hello >/test/somefile $ exit logout # cat /test/somefile hello # ls -lah test/somefile -rw-r--r-- 1 otheruser otheruser 6 Feb 26 17:21 test/somefile # echo root >>test/somefile -bash: test/somefile: Permission denied # sysctl fs.protected_regular=0 fs.protected_regular = 0 # echo root >>test/somefile # cat /test/somefile hello root # sysctl fs.protected_regular=1 fs.protected_regular = 1 # echo root >>test/somefile -bash: test/somefile: Permission denied # chmod 0777 /test/ # echo root >>test/somefile # cat test/somefile hello root root 

Unlike fs.protected_hardlinks and fs.protected_symlinks, fs.protected_regular and fs.protected_fifos are not enabled by default in the kernel code.
Enabling them is a backward incompatible change (as the example you provided in this comment points out) and, as far as I can tell, systemd did it in version 241, with this recent commit.

Credits: thanks to JdeBP for pointing in the right direction with a comment to the question.

3
  • 1
    It works, thank you very much! It also affects Docker containers running on a system with fs.protected_regular=1. This for example causes an error when running openproject/community:8 Commented Feb 27, 2019 at 8:34
  • 3
    What happened to Linus' plea "Don't break user space!".? Commented Apr 30, 2021 at 10:49
  • 2
    user space isn't broken here, if user space sets a flag that later breaks user space than that's the user space's fault not Linux's Commented Aug 18, 2021 at 7:40

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.