diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 49 | 
1 files changed, 48 insertions, 1 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 74dd46de01b6..9625b99e677f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -89,6 +89,8 @@  #include <linux/kernfs.h>  #include <linux/stringhash.h>	/* for hashlen_string() */  #include <uapi/linux/mount.h> +#include <linux/fsnotify.h> +#include <linux/fanotify.h>  #include "avc.h"  #include "objsec.h" @@ -3275,6 +3277,50 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name)  	return -EACCES;  } +static int selinux_path_notify(const struct path *path, u64 mask, +						unsigned int obj_type) +{ +	int ret; +	u32 perm; + +	struct common_audit_data ad; + +	ad.type = LSM_AUDIT_DATA_PATH; +	ad.u.path = *path; + +	/* +	 * Set permission needed based on the type of mark being set. +	 * Performs an additional check for sb watches. +	 */ +	switch (obj_type) { +	case FSNOTIFY_OBJ_TYPE_VFSMOUNT: +		perm = FILE__WATCH_MOUNT; +		break; +	case FSNOTIFY_OBJ_TYPE_SB: +		perm = FILE__WATCH_SB; +		ret = superblock_has_perm(current_cred(), path->dentry->d_sb, +						FILESYSTEM__WATCH, &ad); +		if (ret) +			return ret; +		break; +	case FSNOTIFY_OBJ_TYPE_INODE: +		perm = FILE__WATCH; +		break; +	default: +		return -EINVAL; +	} + +	/* blocking watches require the file:watch_with_perm permission */ +	if (mask & (ALL_FSNOTIFY_PERM_EVENTS)) +		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)) +		perm |= FILE__WATCH_READS; + +	return path_has_perm(current_cred(), path, perm); +} +  /*   * Copy the inode security context value to the user.   * @@ -3403,7 +3449,7 @@ static int selinux_inode_copy_up_xattr(const char *name)  static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,  					struct kernfs_node *kn)  { -	const struct task_security_struct *tsec = current_security(); +	const struct task_security_struct *tsec = selinux_cred(current_cred());  	u32 parent_sid, newsid, clen;  	int rc;  	char *context; @@ -6818,6 +6864,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {  	LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid),  	LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up),  	LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), +	LSM_HOOK_INIT(path_notify, selinux_path_notify),  	LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security),  |