file system permissions regression affecting root
From: Patrick Donnelly
Date: Wed May 13 2020 - 11:00:47 EST
In newer kernels (at least 5.6), it appears root is not able to write
to files owned by other users in a sticky directory:
$ uname -r
5.6.11-arch1-1
$ stat -f /tmp
File: "/tmp"
ID: 0 Namelen: 255 Type: tmpfs
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 2005160 Free: 2005092 Available: 2005092
Inodes: Total: 2005160 Free: 2005112
$ stat /tmp
File: /tmp
Size: 440 Blocks: 0 IO Block: 4096 directory
Device: 2fh/47d Inode: 21533 Links: 20
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-05-11 11:50:52.780667565 -0700
Modify: 2020-05-13 07:40:19.617941285 -0700
Change: 2020-05-13 07:40:19.617941285 -0700
Birth: -
$ touch /tmp/foo
$ stat /tmp/foo
File: /tmp/foo
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 2fh/47d Inode: 3441684 Links: 1
Access: (0640/-rw-r-----) Uid: ( 1000/pdonnell) Gid: ( 985/ users)
Access: 2020-05-13 07:40:29.218026785 -0700
Modify: 2020-05-13 07:40:29.218026785 -0700
Change: 2020-05-13 07:40:29.218026785 -0700
Birth: -
$ sudo /bin/sh -c 'echo 1 > /tmp/foo'
/bin/sh: /tmp/foo: Permission denied
$ sudo strace -f -- /bin/sh -c 'echo 1 > /tmp/foo' |& grep foo
execve("/bin/sh", ["/bin/sh", "-c", "echo 1 > /tmp/foo"],
0x7fff92dec300 /* 15 vars */) = 0
openat(AT_FDCWD, "/tmp/foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1
EACCES (Permission denied)
write(2, "/bin/sh: /tmp/foo: Permission de"..., 37/bin/sh: /tmp/foo:
Permission denied
Compare to Linux 4.18:
$ uname -r
4.18.0-147.3.1.el8_1.x86_64
$ stat /dev/shm
File: /dev/shm
Size: 100 Blocks: 0 IO Block: 4096 directory
Device: 16h/22d Inode: 15466 Links: 2
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:tmpfs_t:s0
Access: 2020-05-12 17:37:07.029131257 +0000
Modify: 2020-05-13 14:35:44.161036943 +0000
Change: 2020-05-13 14:35:44.161036943 +0000
Birth: -
$ stat -f /dev/shm
File: "/dev/shm"
ID: 0 Namelen: 255 Type: tmpfs
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 9243647 Free: 9243604 Available: 9243604
Inodes: Total: 9243647 Free: 9243643
$ touch /dev/shm/foo
$ stat /dev/shm/foo
File: /dev/shm/foo
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 16h/22d Inode: 5616861 Links: 1
Access: (0640/-rw-r-----) Uid: ( 1156/pdonnell) Gid: ( 1156/pdonnell)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2020-05-13 14:44:55.121908033 +0000
Modify: 2020-05-13 14:44:55.121908033 +0000
Change: 2020-05-13 14:44:55.121908033 +0000
Birth: -
$ sudo -- /bin/sh -c 'echo 1 > /dev/shm/foo'
$
This seems to be related to the directory being owned by root; it does
not happen when the directory is owned by the user:
$ uname -r
5.6.11-arch1-1
$ sudo chown pdonnell:users gtmp
$ stat gtmp
File: gtmp
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: fe04h/65028d Inode: 2819062 Links: 2
Access: (1777/drwxrwxrwt) Uid: ( 1000/pdonnell) Gid: ( 985/ users)
Access: 2020-05-13 07:47:06.344892575 -0700
Modify: 2020-05-13 07:50:24.709987998 -0700
Change: 2020-05-13 07:52:52.137963637 -0700
Birth: 2020-05-13 07:34:09.937974845 -0700
$ stat -f gtmp
File: "gtmp"
ID: f24a3528a175df48 Namelen: 255 Type: ext2/ext3
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 36495867 Free: 8991668 Available: 7120360
Inodes: Total: 9338880 Free: 8147228
$ touch gtmp/foo
$ stat gtmp/foo
File: gtmp/foo
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fe04h/65028d Inode: 2754033 Links: 1
Access: (0640/-rw-r-----) Uid: ( 1000/pdonnell) Gid: ( 985/ users)
Access: 2020-05-13 07:53:10.218124141 -0700
Modify: 2020-05-13 07:53:10.218124141 -0700
Change: 2020-05-13 07:53:10.218124141 -0700
Birth: 2020-05-13 07:53:10.218124141 -0700
$ sudo strace -f -- /bin/sh -c 'echo 1 > gtmp/foo' |& grep foo
execve("/bin/sh", ["/bin/sh", "-c", "echo 1 > gtmp/foo"],
0x7ffe03362430 /* 15 vars */) = 0
openat(AT_FDCWD, "gtmp/foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
$ rm gtmp/foo
$ sudo chown root:root gtmp
$ touch gtmp/foo
# stat gtmp/foo
File: gtmp/foo
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fe04h/65028d Inode: 2754033 Links: 1
Access: (0640/-rw-r-----) Uid: ( 1000/pdonnell) Gid: ( 985/ users)
Access: 2020-05-13 07:55:18.892599600 -0700
Modify: 2020-05-13 07:55:18.892599600 -0700
Change: 2020-05-13 07:55:18.892599600 -0700
Birth: 2020-05-13 07:55:18.892599600 -0700
$ sudo strace -f -- /bin/sh -c 'echo 1 > gtmp/foo' |& grep foo
execve("/bin/sh", ["/bin/sh", "-c", "echo 1 > gtmp/foo"],
0x7fff588732f0 /* 15 vars */) = 0
openat(AT_FDCWD, "gtmp/foo", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1
EACCES (Permission denied)
write(2, "/bin/sh: gtmp/foo: Permission de"..., 37/bin/sh: gtmp/foo:
Permission denied
--
Patrick Donnelly