Merge tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / security / selinux / hooks.c
index 74dd46de01b6a4a7dbde1b8d697b9888cbe85f21..9625b99e677fd33cf4abc1ebcc48fb3b79fb44d8 100644 (file)
@@ -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),