]>
Commit | Line | Data |
---|---|---|
72f9fd46 SI |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Linus Torvalds <torvalds@linux-foundation.org> | |
3 | Date: Tue, 3 Jul 2018 17:10:19 -0700 | |
4 | Subject: [PATCH] Fix up non-directory creation in SGID directories | |
5 | ||
6 | sgid directories have special semantics, making newly created files in | |
7 | the directory belong to the group of the directory, and newly created | |
8 | subdirectories will also become sgid. This is historically used for | |
9 | group-shared directories. | |
10 | ||
11 | But group directories writable by non-group members should not imply | |
12 | that such non-group members can magically join the group, so make sure | |
13 | to clear the sgid bit on non-directories for non-members (but remember | |
14 | that sgid without group execute means "mandatory locking", just to | |
15 | confuse things even more). | |
16 | ||
17 | Reported-by: Jann Horn <jannh@google.com> | |
18 | Cc: Andy Lutomirski <luto@kernel.org> | |
19 | Cc: Al Viro <viro@zeniv.linux.org.uk> | |
20 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
21 | (cherry picked from commit 0fa3ecd87848c9c93c2c828ef4c3a8ca36ce46c7) | |
22 | Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com> | |
72f9fd46 SI |
23 | --- |
24 | fs/inode.c | 6 ++++++ | |
25 | 1 file changed, 6 insertions(+) | |
26 | ||
27 | diff --git a/fs/inode.c b/fs/inode.c | |
28 | index 5c1138e9cac0..797b4cb3d20b 100644 | |
29 | --- a/fs/inode.c | |
30 | +++ b/fs/inode.c | |
31 | @@ -2008,8 +2008,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir, | |
32 | inode->i_uid = current_fsuid(); | |
33 | if (dir && dir->i_mode & S_ISGID) { | |
34 | inode->i_gid = dir->i_gid; | |
35 | + | |
36 | + /* Directories are special, and always inherit S_ISGID */ | |
37 | if (S_ISDIR(mode)) | |
38 | mode |= S_ISGID; | |
39 | + else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && | |
40 | + !in_group_p(inode->i_gid) && | |
41 | + !capable_wrt_inode_uidgid(dir, CAP_FSETID)) | |
42 | + mode &= ~S_ISGID; | |
43 | } else | |
44 | inode->i_gid = current_fsgid(); | |
45 | inode->i_mode = mode; |