]>
Commit | Line | Data |
---|---|---|
f0588f72 GKH |
1 | From f69e749a49353d96af1a293f56b5b56de59c668a Mon Sep 17 00:00:00 2001 |
2 | From: Alexander Lochmann <alexander.lochmann@tu-dortmund.de> | |
3 | Date: Fri, 14 Dec 2018 11:55:52 +0100 | |
4 | Subject: Abort file_remove_privs() for non-reg. files | |
5 | ||
6 | From: Alexander Lochmann <alexander.lochmann@tu-dortmund.de> | |
7 | ||
8 | commit f69e749a49353d96af1a293f56b5b56de59c668a upstream. | |
9 | ||
10 | file_remove_privs() might be called for non-regular files, e.g. | |
11 | blkdev inode. There is no reason to do its job on things | |
12 | like blkdev inodes, pipes, or cdevs. Hence, abort if | |
13 | file does not refer to a regular inode. | |
14 | ||
15 | AV: more to the point, for devices there might be any number of | |
16 | inodes refering to given device. Which one to strip the permissions | |
17 | from, even if that made any sense in the first place? All of them | |
18 | will be observed with contents modified, after all. | |
19 | ||
20 | Found by LockDoc (Alexander Lochmann, Horst Schirmeier and Olaf | |
21 | Spinczyk) | |
22 | ||
23 | Reviewed-by: Jan Kara <jack@suse.cz> | |
24 | Signed-off-by: Alexander Lochmann <alexander.lochmann@tu-dortmund.de> | |
25 | Signed-off-by: Horst Schirmeier <horst.schirmeier@tu-dortmund.de> | |
26 | Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> | |
27 | Cc: Zubin Mithra <zsm@chromium.org> | |
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
29 | ||
30 | --- | |
31 | fs/inode.c | 9 +++++++-- | |
32 | 1 file changed, 7 insertions(+), 2 deletions(-) | |
33 | ||
34 | --- a/fs/inode.c | |
35 | +++ b/fs/inode.c | |
36 | @@ -1817,8 +1817,13 @@ int file_remove_privs(struct file *file) | |
37 | int kill; | |
38 | int error = 0; | |
39 | ||
40 | - /* Fast path for nothing security related */ | |
41 | - if (IS_NOSEC(inode)) | |
42 | + /* | |
43 | + * Fast path for nothing security related. | |
44 | + * As well for non-regular files, e.g. blkdev inodes. | |
45 | + * For example, blkdev_write_iter() might get here | |
46 | + * trying to remove privs which it is not allowed to. | |
47 | + */ | |
48 | + if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode)) | |
49 | return 0; | |
50 | ||
51 | kill = dentry_needs_remove_privs(dentry); |