Abort file_remove_privs() for non-reg. files [Linux 4.14.129]

Abort file_remove_privs() for non-reg. files [Linux 4.14.129]

This Linux kernel change "Abort file_remove_privs() for non-reg. files" is included in the Linux 4.14.129 release. This change is authored by Alexander Lochmann <alexander.lochmann [at] tu-dortmund.de> on Fri Dec 14 11:55:52 2018 +0100. The commit for this change in Linux stable tree is 2c54624 (patch) which is from upstream commit f69e749. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream f69e749.

Abort file_remove_privs() for non-reg. files

commit f69e749a49353d96af1a293f56b5b56de59c668a upstream.

file_remove_privs() might be called for non-regular files, e.g.
blkdev inode. There is no reason to do its job on things
like blkdev inodes, pipes, or cdevs. Hence, abort if
file does not refer to a regular inode.

AV: more to the point, for devices there might be any number of
inodes refering to given device.  Which one to strip the permissions
from, even if that made any sense in the first place?  All of them
will be observed with contents modified, after all.

Found by LockDoc (Alexander Lochmann, Horst Schirmeier and Olaf
Spinczyk)

Reviewed-by: Jan Kara <[email protected]>
Signed-off-by: Alexander Lochmann <[email protected]>
Signed-off-by: Horst Schirmeier <[email protected]>
Signed-off-by: Al Viro <[email protected]>
Cc: Zubin Mithra <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 9 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 fs/inode.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index cfc36d1..76f7535 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1817,8 +1817,13 @@ int file_remove_privs(struct file *file)
    int kill;
    int error = 0;

-   /* Fast path for nothing security related */
-   if (IS_NOSEC(inode))
+   /*
+    * Fast path for nothing security related.
+    * As well for non-regular files, e.g. blkdev inodes.
+    * For example, blkdev_write_iter() might get here
+    * trying to remove privs which it is not allowed to.
+    */
+   if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
        return 0;

    kill = dentry_needs_remove_privs(dentry);

Leave a Reply

Your email address will not be published. Required fields are marked *