Skip to content

Commit f156524

Browse files
amir73iljankara
authored andcommitted
fsnotify: introduce pre-content permission events
The new FS_PRE_ACCESS permission event is similar to FS_ACCESS_PERM, but it meant for a different use case of filling file content before access to a file range, so it has slightly different semantics. Generate FS_PRE_ACCESS/FS_ACCESS_PERM as two seperate events, so content scanners could inspect the content filled by pre-content event handler. Unlike FS_ACCESS_PERM, FS_PRE_ACCESS is also called before a file is modified by syscalls as write() and fallocate(). FS_ACCESS_PERM is reported also on blockdev and pipes, but the new pre-content events are only reported for regular files and dirs. The pre-content events are meant to be used by hierarchical storage managers that want to fill the content of files on first access. There are some specific requirements from filesystems that could be used with pre-content events, so add a flag for fs to opt-in for pre-content events explicitly before they can be used. Signed-off-by: Amir Goldstein <[email protected]> Signed-off-by: Jan Kara <[email protected]> Link: https://patch.msgid.link/b934c5e3af205abc4e0e4709f6486815937ddfdf.1731684329.git.josef@toxicpanda.com
1 parent 0a07603 commit f156524

File tree

5 files changed

+30
-6
lines changed

5 files changed

+30
-6
lines changed

fs/notify/fsnotify.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ static __init int fsnotify_init(void)
688688
{
689689
int ret;
690690

691-
BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 23);
691+
BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 24);
692692

693693
ret = init_srcu_struct(&fsnotify_mark_srcu);
694694
if (ret)

include/linux/fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,7 @@ extern int send_sigurg(struct file *file);
12651265
#define SB_I_RETIRED 0x00000800 /* superblock shouldn't be reused */
12661266
#define SB_I_NOUMASK 0x00001000 /* VFS does not apply umask */
12671267
#define SB_I_NOIDMAP 0x00002000 /* No idmapped mounts on this superblock */
1268+
#define SB_I_ALLOW_HSM 0x00004000 /* Allow HSM events on this superblock */
12681269

12691270
/* Possible states of 'frozen' field */
12701271
enum {

include/linux/fsnotify.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,29 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,
144144
*/
145145
lockdep_assert_once(file_write_not_started(file));
146146

147-
if (!(perm_mask & MAY_READ))
147+
if (!(perm_mask & (MAY_READ | MAY_WRITE | MAY_ACCESS)))
148148
return 0;
149149

150150
if (likely(!FMODE_FSNOTIFY_PERM(file->f_mode)))
151151
return 0;
152152

153+
/*
154+
* read()/write() and other types of access generate pre-content events.
155+
*/
156+
if (unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) {
157+
int ret = fsnotify_path(&file->f_path, FS_PRE_ACCESS);
158+
159+
if (ret)
160+
return ret;
161+
}
162+
163+
if (!(perm_mask & MAY_READ))
164+
return 0;
165+
166+
/*
167+
* read() also generates the legacy FS_ACCESS_PERM event, so content
168+
* scanners can inspect the content filled by pre-content event.
169+
*/
153170
return fsnotify_path(&file->f_path, FS_ACCESS_PERM);
154171
}
155172

include/linux/fsnotify_backend.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */
5858
/* #define FS_DIR_MODIFY 0x00080000 */ /* Deprecated (reserved) */
5959

60+
#define FS_PRE_ACCESS 0x00100000 /* Pre-content access hook */
61+
6062
/*
6163
* Set on inode mark that cares about things that happen to its children.
6264
* Always set for dnotify and inotify.
@@ -78,11 +80,14 @@
7880
*/
7981
#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | FS_RENAME)
8082

83+
/* Content events can be used to inspect file content */
84+
#define FSNOTIFY_CONTENT_PERM_EVENTS (FS_OPEN_PERM | FS_OPEN_EXEC_PERM | \
85+
FS_ACCESS_PERM)
8186
/* Pre-content events can be used to fill file content */
82-
#define FSNOTIFY_PRE_CONTENT_EVENTS 0
87+
#define FSNOTIFY_PRE_CONTENT_EVENTS (FS_PRE_ACCESS)
8388

84-
#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \
85-
FS_OPEN_EXEC_PERM)
89+
#define ALL_FSNOTIFY_PERM_EVENTS (FSNOTIFY_CONTENT_PERM_EVENTS | \
90+
FSNOTIFY_PRE_CONTENT_EVENTS)
8691

8792
/*
8893
* This is a list of all events that may get sent to a parent that is watching

security/selinux/hooks.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3404,7 +3404,8 @@ static int selinux_path_notify(const struct path *path, u64 mask,
34043404
perm |= FILE__WATCH_WITH_PERM;
34053405

34063406
/* watches on read-like events need the file:watch_reads permission */
3407-
if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
3407+
if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_PRE_ACCESS |
3408+
FS_CLOSE_NOWRITE))
34083409
perm |= FILE__WATCH_READS;
34093410

34103411
return path_has_perm(current_cred(), path, perm);

0 commit comments

Comments
 (0)