diff options
| -rw-r--r-- | fs/notify/fsnotify.c | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 1 | ||||
| -rw-r--r-- | include/linux/fsnotify.h | 19 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 11 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 3 | 
5 files changed, 30 insertions, 6 deletions
| diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9e483fface1e..32b461c5d04b 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -688,7 +688,7 @@ static __init int fsnotify_init(void)  {  	int ret; -	BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 23); +	BUILD_BUG_ON(HWEIGHT32(ALL_FSNOTIFY_BITS) != 24);  	ret = init_srcu_struct(&fsnotify_mark_srcu);  	if (ret) diff --git a/include/linux/fs.h b/include/linux/fs.h index 5f7ac5b548a4..3f4d59464965 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1265,6 +1265,7 @@ extern int send_sigurg(struct file *file);  #define SB_I_RETIRED	0x00000800	/* superblock shouldn't be reused */  #define SB_I_NOUMASK	0x00001000	/* VFS does not apply umask */  #define SB_I_NOIDMAP	0x00002000	/* No idmapped mounts on this superblock */ +#define SB_I_ALLOW_HSM	0x00004000	/* Allow HSM events on this superblock */  /* Possible states of 'frozen' field */  enum { diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 8d1849137a96..d91aa064f0e4 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -144,12 +144,29 @@ static inline int fsnotify_file_area_perm(struct file *file, int perm_mask,  	 */  	lockdep_assert_once(file_write_not_started(file)); -	if (!(perm_mask & MAY_READ)) +	if (!(perm_mask & (MAY_READ | MAY_WRITE | MAY_ACCESS)))  		return 0;  	if (likely(!FMODE_FSNOTIFY_PERM(file->f_mode)))  		return 0; +	/* +	 * read()/write() and other types of access generate pre-content events. +	 */ +	if (unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) { +		int ret = fsnotify_path(&file->f_path, FS_PRE_ACCESS); + +		if (ret) +			return ret; +	} + +	if (!(perm_mask & MAY_READ)) +		return 0; + +	/* +	 * read() also generates the legacy FS_ACCESS_PERM event, so content +	 * scanners can inspect the content filled by pre-content event. +	 */  	return fsnotify_path(&file->f_path, FS_ACCESS_PERM);  } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index c38762b62bf1..9bda354b5538 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -57,6 +57,8 @@  #define FS_OPEN_EXEC_PERM	0x00040000	/* open/exec event in a permission hook */  /* #define FS_DIR_MODIFY	0x00080000 */	/* Deprecated (reserved) */ +#define FS_PRE_ACCESS		0x00100000	/* Pre-content access hook */ +  /*   * Set on inode mark that cares about things that happen to its children.   * Always set for dnotify and inotify. @@ -78,11 +80,14 @@   */  #define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | FS_RENAME) +/* Content events can be used to inspect file content */ +#define FSNOTIFY_CONTENT_PERM_EVENTS (FS_OPEN_PERM | FS_OPEN_EXEC_PERM | \ +				      FS_ACCESS_PERM)  /* Pre-content events can be used to fill file content */ -#define FSNOTIFY_PRE_CONTENT_EVENTS 0 +#define FSNOTIFY_PRE_CONTENT_EVENTS  (FS_PRE_ACCESS) -#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \ -				  FS_OPEN_EXEC_PERM) +#define ALL_FSNOTIFY_PERM_EVENTS (FSNOTIFY_CONTENT_PERM_EVENTS | \ +				  FSNOTIFY_PRE_CONTENT_EVENTS)  /*   * This is a list of all events that may get sent to a parent that is watching diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f5a08f94e094..97a2c04c2b37 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3404,7 +3404,8 @@ static int selinux_path_notify(const struct path *path, u64 mask,  		perm |= FILE__WATCH_WITH_PERM;  	/* watches on read-like events need the file:watch_reads permission */ -	if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE)) +	if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_PRE_ACCESS | +		    FS_CLOSE_NOWRITE))  		perm |= FILE__WATCH_READS;  	return path_has_perm(current_cred(), path, perm); | 
