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 @@ | |||
89 | #include <linux/kernfs.h> | 89 | #include <linux/kernfs.h> |
90 | #include <linux/stringhash.h> /* for hashlen_string() */ | 90 | #include <linux/stringhash.h> /* for hashlen_string() */ |
91 | #include <uapi/linux/mount.h> | 91 | #include <uapi/linux/mount.h> |
92 | #include <linux/fsnotify.h> | ||
93 | #include <linux/fanotify.h> | ||
92 | 94 | ||
93 | #include "avc.h" | 95 | #include "avc.h" |
94 | #include "objsec.h" | 96 | #include "objsec.h" |
@@ -3275,6 +3277,50 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | |||
3275 | return -EACCES; | 3277 | return -EACCES; |
3276 | } | 3278 | } |
3277 | 3279 | ||
3280 | static int selinux_path_notify(const struct path *path, u64 mask, | ||
3281 | unsigned int obj_type) | ||
3282 | { | ||
3283 | int ret; | ||
3284 | u32 perm; | ||
3285 | |||
3286 | struct common_audit_data ad; | ||
3287 | |||
3288 | ad.type = LSM_AUDIT_DATA_PATH; | ||
3289 | ad.u.path = *path; | ||
3290 | |||
3291 | /* | ||
3292 | * Set permission needed based on the type of mark being set. | ||
3293 | * Performs an additional check for sb watches. | ||
3294 | */ | ||
3295 | switch (obj_type) { | ||
3296 | case FSNOTIFY_OBJ_TYPE_VFSMOUNT: | ||
3297 | perm = FILE__WATCH_MOUNT; | ||
3298 | break; | ||
3299 | case FSNOTIFY_OBJ_TYPE_SB: | ||
3300 | perm = FILE__WATCH_SB; | ||
3301 | ret = superblock_has_perm(current_cred(), path->dentry->d_sb, | ||
3302 | FILESYSTEM__WATCH, &ad); | ||
3303 | if (ret) | ||
3304 | return ret; | ||
3305 | break; | ||
3306 | case FSNOTIFY_OBJ_TYPE_INODE: | ||
3307 | perm = FILE__WATCH; | ||
3308 | break; | ||
3309 | default: | ||
3310 | return -EINVAL; | ||
3311 | } | ||
3312 | |||
3313 | /* blocking watches require the file:watch_with_perm permission */ | ||
3314 | if (mask & (ALL_FSNOTIFY_PERM_EVENTS)) | ||
3315 | perm |= FILE__WATCH_WITH_PERM; | ||
3316 | |||
3317 | /* watches on read-like events need the file:watch_reads permission */ | ||
3318 | if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE)) | ||
3319 | perm |= FILE__WATCH_READS; | ||
3320 | |||
3321 | return path_has_perm(current_cred(), path, perm); | ||
3322 | } | ||
3323 | |||
3278 | /* | 3324 | /* |
3279 | * Copy the inode security context value to the user. | 3325 | * Copy the inode security context value to the user. |
3280 | * | 3326 | * |
@@ -3403,7 +3449,7 @@ static int selinux_inode_copy_up_xattr(const char *name) | |||
3403 | static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, | 3449 | static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, |
3404 | struct kernfs_node *kn) | 3450 | struct kernfs_node *kn) |
3405 | { | 3451 | { |
3406 | const struct task_security_struct *tsec = current_security(); | 3452 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
3407 | u32 parent_sid, newsid, clen; | 3453 | u32 parent_sid, newsid, clen; |
3408 | int rc; | 3454 | int rc; |
3409 | char *context; | 3455 | char *context; |
@@ -6818,6 +6864,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
6818 | LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), | 6864 | LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), |
6819 | LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), | 6865 | LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), |
6820 | LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), | 6866 | LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), |
6867 | LSM_HOOK_INIT(path_notify, selinux_path_notify), | ||
6821 | 6868 | ||
6822 | LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security), | 6869 | LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security), |
6823 | 6870 | ||