|
|
@@ -0,0 +1,46 @@
|
|
|
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
+From: Linus Torvalds <[email protected]>
|
|
|
+Date: Tue, 3 Jul 2018 17:10:19 -0700
|
|
|
+Subject: [PATCH] Fix up non-directory creation in SGID directories
|
|
|
+
|
|
|
+sgid directories have special semantics, making newly created files in
|
|
|
+the directory belong to the group of the directory, and newly created
|
|
|
+subdirectories will also become sgid. This is historically used for
|
|
|
+group-shared directories.
|
|
|
+
|
|
|
+But group directories writable by non-group members should not imply
|
|
|
+that such non-group members can magically join the group, so make sure
|
|
|
+to clear the sgid bit on non-directories for non-members (but remember
|
|
|
+that sgid without group execute means "mandatory locking", just to
|
|
|
+confuse things even more).
|
|
|
+
|
|
|
+Reported-by: Jann Horn <[email protected]>
|
|
|
+Cc: Andy Lutomirski <[email protected]>
|
|
|
+Cc: Al Viro <[email protected]>
|
|
|
+Signed-off-by: Linus Torvalds <[email protected]>
|
|
|
+(cherry picked from commit 0fa3ecd87848c9c93c2c828ef4c3a8ca36ce46c7)
|
|
|
+Signed-off-by: Stoiko Ivanov <[email protected]>
|
|
|
+
|
|
|
+---
|
|
|
+ fs/inode.c | 6 ++++++
|
|
|
+ 1 file changed, 6 insertions(+)
|
|
|
+
|
|
|
+diff --git a/fs/inode.c b/fs/inode.c
|
|
|
+index 5c1138e9cac0..797b4cb3d20b 100644
|
|
|
+--- a/fs/inode.c
|
|
|
++++ b/fs/inode.c
|
|
|
+@@ -2008,8 +2008,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir,
|
|
|
+ inode->i_uid = current_fsuid();
|
|
|
+ if (dir && dir->i_mode & S_ISGID) {
|
|
|
+ inode->i_gid = dir->i_gid;
|
|
|
++
|
|
|
++ /* Directories are special, and always inherit S_ISGID */
|
|
|
+ if (S_ISDIR(mode))
|
|
|
+ mode |= S_ISGID;
|
|
|
++ else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) &&
|
|
|
++ !in_group_p(inode->i_gid) &&
|
|
|
++ !capable_wrt_inode_uidgid(dir, CAP_FSETID))
|
|
|
++ mode &= ~S_ISGID;
|
|
|
+ } else
|
|
|
+ inode->i_gid = current_fsgid();
|
|
|
+ inode->i_mode = mode;
|