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 <jannh@google.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[haggertk: Backported to 3.4
 - Use capable() instead of capable_wrt_inode_uidgid()]
CVE-2018-13405
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>

Change-Id: I89974ab06a8ad22496031dbfd2c5106b6e64a0b8
This commit is contained in:
Linus Torvalds 2018-07-03 17:10:19 -07:00 committed by Francescodario Cuzzocrea
parent 3d9f49f598
commit f7d4f15d15
1 changed files with 6 additions and 0 deletions

View File

@ -1739,8 +1739,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(CAP_FSETID))
mode &= ~S_ISGID;
} else
inode->i_gid = current_fsgid();
inode->i_mode = mode;