]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fsnotify: optionally pass access range in file permission hooks
authorAmir Goldstein <amir73il@gmail.com>
Tue, 12 Dec 2023 09:44:40 +0000 (11:44 +0200)
committerChristian Brauner <brauner@kernel.org>
Tue, 12 Dec 2023 15:20:02 +0000 (16:20 +0100)
In preparation for pre-content permission events with file access range,
move fsnotify_file_perm() hook out of security_file_permission() and into
the callers.

Callers that have the access range information call the new hook
fsnotify_file_area_perm() with the access range.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://lore.kernel.org/r/20231212094440.250945-6-amir73il@gmail.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/open.c
fs/read_write.c
fs/readdir.c
fs/remap_range.c
include/linux/fsnotify.h
security/security.c

index 02dc608d40d81f90c9427695763c85d0fd111e93..d877228d5939cc474643d4bb7fc310a6d1f9a59a 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -304,6 +304,10 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (ret)
                return ret;
 
+       ret = fsnotify_file_area_perm(file, MAY_WRITE, &offset, len);
+       if (ret)
+               return ret;
+
        if (S_ISFIFO(inode->i_mode))
                return -ESPIPE;
 
index e3abf603eaaf84df6939deff567d7c33cfff7b04..d4c036e82b6c38cf706e463363d16d78e4dd3fdf 100644 (file)
@@ -354,6 +354,9 @@ out_putf:
 
 int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count)
 {
+       int mask = read_write == READ ? MAY_READ : MAY_WRITE;
+       int ret;
+
        if (unlikely((ssize_t) count < 0))
                return -EINVAL;
 
@@ -371,8 +374,11 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
                }
        }
 
-       return security_file_permission(file,
-                               read_write == READ ? MAY_READ : MAY_WRITE);
+       ret = security_file_permission(file, mask);
+       if (ret)
+               return ret;
+
+       return fsnotify_file_area_perm(file, mask, ppos, count);
 }
 EXPORT_SYMBOL(rw_verify_area);
 
index c8c46e29443139d1e496bbb2236e4faf6af9effa..278bc025473274e77ca924f801ddfd5333d7c2cf 100644 (file)
@@ -96,6 +96,10 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
        if (res)
                goto out;
 
+       res = fsnotify_file_perm(file, MAY_READ);
+       if (res)
+               goto out;
+
        res = down_read_killable(&inode->i_rwsem);
        if (res)
                goto out;
index 12131f2a6c9e8c54212a7b7cb342cabc24a88e28..f8c1120b8311f62324324b911b0aa4aebe4ccb04 100644 (file)
@@ -102,7 +102,9 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in,
 static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
                             bool write)
 {
+       int mask = write ? MAY_WRITE : MAY_READ;
        loff_t tmp;
+       int ret;
 
        if (unlikely(pos < 0 || len < 0))
                return -EINVAL;
@@ -110,7 +112,11 @@ static int remap_verify_area(struct file *file, loff_t pos, loff_t len,
        if (unlikely(check_add_overflow(pos, len, &tmp)))
                return -EINVAL;
 
-       return security_file_permission(file, write ? MAY_WRITE : MAY_READ);
+       ret = security_file_permission(file, mask);
+       if (ret)
+               return ret;
+
+       return fsnotify_file_area_perm(file, mask, &pos, len);
 }
 
 /*
index 0a9d6a8a747acedeea16bbb6f539a894d6cd2ab3..11e6434b8e714a1d03d7ea2807c795513916b58e 100644 (file)
@@ -101,9 +101,10 @@ static inline int fsnotify_file(struct file *file, __u32 mask)
 }
 
 /*
- * fsnotify_file_perm - permission hook before file access
+ * fsnotify_file_area_perm - permission hook before access to file range
  */
-static inline int fsnotify_file_perm(struct file *file, int perm_mask)
+static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
+                                         const loff_t *ppos, size_t count)
 {
        __u32 fsnotify_mask = FS_ACCESS_PERM;
 
@@ -120,6 +121,14 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask)
        return fsnotify_file(file, fsnotify_mask);
 }
 
+/*
+ * fsnotify_file_perm - permission hook before file access
+ */
+static inline int fsnotify_file_perm(struct file *file, int perm_mask)
+{
+       return fsnotify_file_area_perm(file, perm_mask, NULL, 0);
+}
+
 /*
  * fsnotify_open_perm - permission hook before file open
  */
index d7f3703c590560204b8c10f37cb8eefe8cfe6a23..2a7fc7881cbca2096fa30220c1c0bbcc53ab6e76 100644 (file)
@@ -2580,13 +2580,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir,
  */
 int security_file_permission(struct file *file, int mask)
 {
-       int ret;
-
-       ret = call_int_hook(file_permission, 0, file, mask);
-       if (ret)
-               return ret;
-
-       return fsnotify_file_perm(file, mask);
+       return call_int_hook(file_permission, 0, file, mask);
 }
 
 /**