3

Anyone know why rocky can't write to /tmp/afile? Giving rocky permission as an other user with chmod o+w doesn't seem to work either 🤔

I updated the acl with: setfacl -m u:rocky:rw /tmp/afile

id as rocky and owner:

rocky@jammy:~$ id
uid=1001(rocky) gid=1001(rocky) groups=1001(rocky)
seb@jammy:~$ id
uid=1000(seb) gid=1000(seb) groups=1000(seb),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),134(lxd),135(sambashare)

ls -ld output

seb@jammy:~$ ls -ld /tmp/afile
-rw-rw-rw-+ 1 seb seb 0 Jul  3 14:25 /tmp/afile

Owner is able to write without issue:

seb@jammy:~$ echo rounders > /tmp/afile
seb@jammy:~$ cat /tmp/afile 
rounders

getfacl -n output:

seb@jammy:~$ getfacl -n /tmp/afile getfacl: Removing leading '/' from
absolute path names
# file: tmp/afile
# owner: 1000
# group: 1000
user::rw- 
user:1001:rw- 
group::rw- 
mask::rw- 
other::rw-

df -T and mount output:

seb@jammy:~$ df -T /tmp
Filesystem     Type 1K-blocks     Used Available Use% Mounted on
/dev/sda2      ext4 120044288 18487840  95412296  17% /
seb@jammy:~$ mount | grep /dev/sda2
/dev/sda2 on / type ext4 (rw,relatime,errors=remount-ro)
/dev/sda2 on /var/snap/firefox/common/host-hunspell type ext4 (ro,noexec,noatime,errors=remount-ro)

Attempt to write to file as rocky:

seb@jammy:~$ getfacl /tmp/afile
getfacl: Removing leading '/' from absolute path names
# file: tmp/afile
# owner: seb
# group: seb
user::rw-
user:rocky:rw-
group::rw-
mask::rw-
other::rw-

seb@jammy:~$ su - rocky
#Password: 
rocky@jammy:~$ echo hello > /tmp/afile
-bash: /tmp/afile: Permission denied
5
  • ls -ld /tmp/afile please. (Added to your question.). And id run as both seb and rocky users Commented Jul 3, 2023 at 14:18
  • Thanks @roaima, added :) Commented Jul 3, 2023 at 14:32
  • Please also add the output of: getfacl -n /tmp/afile. And I assume that you have no issues writing to the file as user seb. Commented Jul 3, 2023 at 15:30
  • Also add the output of df -T /tmp. From the output of df take the filesystem (/dev/...) and show it's mount options by running mount | grep /dev/.... Commented Jul 3, 2023 at 15:41
  • @aviro Thank you :) I've run those and I can confirm that the owner can write without issue Commented Jul 3, 2023 at 15:55

2 Answers 2

6

Your expectation is correct: the permissions should allow rocky to write to afile, since rocky has the write permission on the file and execute permission on all the containing directories. However, you've run into an additional security hardening mechanism on Linux. When this mechanism is active, certain writes to files in directories with the sticky bit are prevented.

The sticky bit on a directory is indicated by t as the last of the 10 characters of the file mode/permissions in the ls -l listing, and can be set with chmod +t. Normally, the effect of the sticky bit on a directory is that only the owner of a file can remove or rename it. It does not affect writing to an existing file.

However, when the fs.protected_regular sysctl is enabled, the sticky bit has an additional consequence: users cannot open a file for writing in a sticky directory unless they own the file, if they open the file in a way that would create it if the file did not exist, which the program indicates by passing the O_CREAT file to the open system call. Note the subtlety here: the normal behavior is solely based on whether the file exists, whereas the hardened behavior is based on whether the file would be created if it didn't exist. This only affects opening the file in a way that might create it: other ways to write to the file are still permitted.

Note that this does not affect files in a directory that doesn't have the sticky bit. In particular, if you create a directory /tmp/foo and /tmp/foo does not have the sticky bit, then permissions of files in /tmp/foo behave normally.

The following table summarizes the behavior of the open system call when opening the file for writing in the relevant scenarios (where the directory exists and the program can access files in it, and if the file exists then the program has write permission on it):

directory file with O_CREAT without O_CREAT
rwxr-xr-x (755) exists, writable (666) ok ok
rwxr-xr-x (755) does not exist ok ENOENT
rwxrwxrwx (777) exists, writable (666) ok ok
rwxrwxrwx (777) does not exist ok ENOENT
rwxr-xr-t (1755) exists, writable (666) ok ok
rwxr-xr-t (1755) does not exist ok ENOENT
rwxrwxrwt (1777) normally exists, writable (666) ok ok
rwxrwxrwt (1777) normally does not exist ok ENOENT
rwxrwxrwt (1777) on hardened Linux exists, writable (666) EACCES ok
rwxrwxrwt (1777) on hardened Linux does not exist ok ENOENT

(ENOENT is the error “No such file or directory”. EACCES is the error “Permission denied”.)

You can control whether this hardening is enabled with sysctl fs.protected_regular=0 (disable), sysctl fs.protected_regular=1 (enable for world-writable directories) or sysctl fs.protected_regular=2 (enable for world-writable or group-writable directories). At boot time, this may be set from /etc/sysctl.conf or /etc/sysctl.d/*. Some distributions enable it by default, others don't. The protected_regular setting applies to regular files; there is a similar setting for named pipes.

To see this for yourself (if you're running on Linux and have root access), run the following commands as root:

mkdir /tmp/experiment
mkdir -m 1777 /tmp/experiment/sticky-world
mkdir -m 777 /tmp/experiment/ordinary-world
mkdir -m 1755 /tmp/experiment/sticky-user
mkdir -m 755 /tmp/experiment/ordinary-user
for d in /tmp/experiment/*; do touch $d/file; chown nobody:nogroup $d/file; chmod 666 $d/file; done

Checking the permissions:

$ ls -l /tmp/experiment 
total 16
drwxr-xr-x 2 root root 4096 Jul  3 21:10 ordinary-user
drwxrwxrwx 2 root root 4096 Jul  3 21:10 ordinary-world
drwxr-xr-t 2 root root 4096 Jul  3 21:10 sticky-user
drwxrwxrwt 2 root root 4096 Jul  3 21:10 sticky-world
$ ls -l /tmp/experiment/*/file
-rw-rw-rw- 1 nobody nogroup 0 Jul  3 21:10 /tmp/experiment/ordinary-user/file
-rw-rw-rw- 1 nobody nogroup 0 Jul  3 21:10 /tmp/experiment/ordinary-world/file
-rw-rw-rw- 1 nobody nogroup 0 Jul  3 21:10 /tmp/experiment/sticky-user/file
-rw-rw-rw- 1 nobody nogroup 0 Jul  3 21:10 /tmp/experiment/sticky-world/file

Now, as a non-root user who isn't nobody, let's run some code that tries opening the files for writing, once with the O_CREAT flag and once without. I use Perl because the shell doesn't give direct access to O_CREAT (shell write redirections always have O_CREAT enabled except for appending in some shells when noclobber is enabled). On a hardened Linux:

$ perl -w -MFcntl -e 'foreach (@ARGV) { sysopen(F, $_, O_WRONLY | O_CREAT) or warn "$_: $!\n"; close F; }' /tmp/experiment/*/file
/tmp/experiment/sticky-world/file: Permission denied
$ perl -w -MFcntl -e 'foreach (@ARGV) { sysopen(F, $_, O_WRONLY) or warn "$_: $!\n"; close F; }' /tmp/experiment/*/file

Without the Linux hardening, all the file openings would succeed since the program has permission to write to the file.

If you have audit enabled, the attempt to write to /tmp/experiment/sticky-world/file triggers an ANOM_CREAT audit event, which is logged in /var/log/audit/audit.log (or wherever those logs go on your distribution.) (This is how I discovered this Linux mechanism, which didn't know about before.)

1
  • Super helpful! FWIW, not all Ubuntu releases handle things the same way. For instance, Bionic allows O_CREAT access to a file if the permissions allows it, regardless of whether or not the UID of the process matches the owner of the file. Jammy on other hand, does enforce that rule. The inconsistency broke something leading me to search out this page. This info was really helpful. Commented Feb 28, 2024 at 22:01
1

Because of the sticky bit (+t) on /tmp.

man 1 chmod

RESTRICTED DELETION FLAG OR STICKY BIT

   The restricted deletion flag or sticky bit is a single bit,  whose  in‐
   terpretation  depends  on  the file type.  For directories, it prevents
   unprivileged users from removing or renaming a file  in  the  directory
   unless  they  own  the  file  or  the directory; this is called the re‐
   stricted deletion flag for the directory,  and  is  commonly  found  on
   world-writable  directories like /tmp.  
14
  • 2
    This is not true for modifying a file. Your answer might have been true if he was trying to remove or delete the file, but that's not the case here. The sticky bit of the directory doesn't affect modifying the contents of the file in the directory, only the actual file permissions do. Commented Jul 3, 2023 at 14:50
  • @aviro: In Linux world the renaming/removing operation is the same write permission as modifying. If you don't believe me, try it yourself. Commented Jul 3, 2023 at 15:31
  • 1
    @aviro, roima, Ivor: You're both partly right. Normally, the sticky bit only controls file creation and removal. Writing to an existing file should only depend on the file's permissions. However Linux has an additional hardening mechanism that prevents writing to an existing file in a +t directory if the call might create a file, even if the file happens to already exist. Non-Linux systems, ancient Linux systems, or Linux systems configured without this hardening will show the expected behavior. Commented Jul 3, 2023 at 18:43
  • 1
    Thanks everyone for chipping in! :) It took me a little while to understand (and some more googling :D ). Removing the sticky bit from /tmp resolved the issue for me (I've now replaced +t to keep permissions as intended). I'm super new to Linux, when reading man chmod and searching google, the pages did state that +t prevented renaming or removing the file, but no mention of writing/appending to the file. Removing +t certainly resolved the issue, but was preventing rocky from writing to the file its intended purpose? Commented Jul 3, 2023 at 18:50
  • 2
    @Newbie *Do not remove the sticky bit from /tmp! This is likely to break stuff. Never change the permission on system directories unless you thoroughly understand what you're doing. Commented Jul 3, 2023 at 19:44

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.