Skip to content

Commit 0fa3ecd

Browse files
committed
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]>
1 parent d02d21e commit 0fa3ecd

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

fs/inode.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,8 +1999,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir,
19991999
inode->i_uid = current_fsuid();
20002000
if (dir && dir->i_mode & S_ISGID) {
20012001
inode->i_gid = dir->i_gid;
2002+
2003+
/* Directories are special, and always inherit S_ISGID */
20022004
if (S_ISDIR(mode))
20032005
mode |= S_ISGID;
2006+
else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) &&
2007+
!in_group_p(inode->i_gid) &&
2008+
!capable_wrt_inode_uidgid(dir, CAP_FSETID))
2009+
mode &= ~S_ISGID;
20042010
} else
20052011
inode->i_gid = current_fsgid();
20062012
inode->i_mode = mode;

0 commit comments

Comments
 (0)