Re: file system permissions regression affecting root

2020-05-16 Thread Christian Kujau
On Wed, 13 May 2020, Patrick Donnelly wrote:
> However, it seems odd that this depends on the owner of the directory.
> i.e. this protection only seems to be enforced if the sticky directory
> is owned by root. That's expected?

According to the documentation[0] this appears to be intentional:

 protected_regular:
   [...]
   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.

C.

[0] https://www.kernel.org/doc/Documentation/sysctl/fs.txt
-- 
BOFH excuse #263:

It's stuck in the Web.


Re: file system permissions regression affecting root

2020-05-13 Thread Patrick Donnelly
On Wed, May 13, 2020 at 9:11 AM Al Viro  wrote:
>
> On Wed, May 13, 2020 at 08:00:28AM -0700, Patrick Donnelly wrote:
> > 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:
>
> Yes.  Controlled by /proc/sys/fs/protected_regular, which systemd crowd
> has decided to enable in commit 2732587540035227fe59e4b64b60127352611b35
>  [...]

Thanks for the information Al!

However, it seems odd that this depends on the owner of the directory.
i.e. this protection only seems to be enforced if the sticky directory
is owned by root. That's expected?


-- 
Patrick Donnelly


Re: file system permissions regression affecting root

2020-05-13 Thread Al Viro
On Wed, May 13, 2020 at 08:00:28AM -0700, Patrick Donnelly wrote:
> 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:

Yes.  Controlled by /proc/sys/fs/protected_regular, which systemd crowd
has decided to enable in commit 2732587540035227fe59e4b64b60127352611b35
Author: Lucas Werkmeister 
Date:   Wed Jan 16 00:16:10 2019 +0100

Enable regular file and FIFO protection

These sysctls were added in Linux 4.19 (torvalds/linux@30aba6656f), and
we should enable them just like we enable the older hardlink/symlink
protection since v199. Implements #11414.

in their tree.  The relevant part is this:
diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf
index b0645f33e7..27084f6242 100644
--- a/sysctl.d/50-default.conf
+++ b/sysctl.d/50-default.conf
@@ -36,3 +36,7 @@ net.core.default_qdisc = fq_codel
 # Enable hard and soft link protection
 fs.protected_hardlinks = 1
 fs.protected_symlinks = 1
+
+# Enable regular file and FIFO protection
+fs.protected_regular = 1
+fs.protected_fifos = 1

so if you want the normal behaviour (and I certainly agree that the value
of that "protection" is not terribly high - I don't enable it on any of
my boxen and I don't use systemd, so they can't make those decisions for
me), I would suggest going into /etc/sysctl.d/ and telling the damn
thing _not_ to enable that.

>From the same commit:
+* The fs.protected_regular and fs.protected_fifos sysctls, which were
+  added in Linux 4.19 to make some data spoofing attacks harder, are
+  now enabled by default. While this will hopefully improve the
+  security of most installations, it is technically a backwards
+  incompatible change; to disable these sysctls again, place the
+  following lines in /etc/sysctl.d/60-protected.conf or a similar file:
+
+  fs.protected_regular = 0
+  fs.protected_fifos = 0
+
+  Note that the similar hardlink and symlink protection has been
+  enabled since v199, and may be disabled likewise.



file system permissions regression affecting root

2020-05-13 Thread Patrick Donnelly
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: 0Namelen: 255 Type: tmpfs
Block size: 4096   Fundamental block size: 4096
Blocks: Total: 2005160Free: 2005092Available: 2005092
Inodes: Total: 2005160Free: 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 +
Modify: 2020-05-13 14:35:44.161036943 +
Change: 2020-05-13 14:35:44.161036943 +
 Birth: -
$ stat -f /dev/shm
  File: "/dev/shm"
ID: 0Namelen: 255 Type: tmpfs
Block size: 4096   Fundamental block size: 4096
Blocks: Total: 9243647Free: 9243604Available: 9243604
Inodes: Total: 9243647Free: 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 +
Modify: 2020-05-13 14:44:55.121908033 +
Change: 2020-05-13 14:44:55.121908033 +
 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: 4096Blocks: 8  IO Block: 4096   directory
Device: fe04h/65028dInode: 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: 8991668Available: 7120360
Inodes: Total: 9338880Free: 8147228
$ touch gtmp/foo
$ stat gtmp/foo
  File: gtmp/foo
  Size: 0   Blocks: 0  IO Block: 4096   regular empty file
Device: fe04h/65028dInode: 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/65028dInode: 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