landlock: Refactor landlock_add_rule() syscall
authorKonstantin Meskhidze <konstantin.meskhidze@huawei.com>
Thu, 26 Oct 2023 01:47:46 +0000 (09:47 +0800)
committerMickaël Salaün <mic@digikod.net>
Thu, 26 Oct 2023 19:07:14 +0000 (21:07 +0200)
Change the landlock_add_rule() syscall to support new rule types with
next commits. Add the add_rule_path_beneath() helper to support current
filesystem rules.

Signed-off-by: Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
Link: https://lore.kernel.org/r/20231026014751.414649-8-konstantin.meskhidze@huawei.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
security/landlock/syscalls.c

index d35cd5d..e87f572 100644 (file)
@@ -274,6 +274,44 @@ out_fdput:
        return err;
 }
 
+static int add_rule_path_beneath(struct landlock_ruleset *const ruleset,
+                                const void __user *const rule_attr)
+{
+       struct landlock_path_beneath_attr path_beneath_attr;
+       struct path path;
+       int res, err;
+       access_mask_t mask;
+
+       /* Copies raw user space buffer, only one type for now. */
+       res = copy_from_user(&path_beneath_attr, rule_attr,
+                            sizeof(path_beneath_attr));
+       if (res)
+               return -EFAULT;
+
+       /*
+        * Informs about useless rule: empty allowed_access (i.e. deny rules)
+        * are ignored in path walks.
+        */
+       if (!path_beneath_attr.allowed_access)
+               return -ENOMSG;
+
+       /* Checks that allowed_access matches the @ruleset constraints. */
+       mask = landlock_get_raw_fs_access_mask(ruleset, 0);
+       if ((path_beneath_attr.allowed_access | mask) != mask)
+               return -EINVAL;
+
+       /* Gets and checks the new rule. */
+       err = get_path_from_fd(path_beneath_attr.parent_fd, &path);
+       if (err)
+               return err;
+
+       /* Imports the new rule. */
+       err = landlock_append_fs_rule(ruleset, &path,
+                                     path_beneath_attr.allowed_access);
+       path_put(&path);
+       return err;
+}
+
 /**
  * sys_landlock_add_rule - Add a new rule to a ruleset
  *
@@ -306,11 +344,8 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
                const enum landlock_rule_type, rule_type,
                const void __user *const, rule_attr, const __u32, flags)
 {
-       struct landlock_path_beneath_attr path_beneath_attr;
-       struct path path;
        struct landlock_ruleset *ruleset;
-       int res, err;
-       access_mask_t mask;
+       int err;
 
        if (!landlock_initialized)
                return -EOPNOTSUPP;
@@ -324,48 +359,14 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
        if (IS_ERR(ruleset))
                return PTR_ERR(ruleset);
 
-       if (rule_type != LANDLOCK_RULE_PATH_BENEATH) {
-               err = -EINVAL;
-               goto out_put_ruleset;
-       }
-
-       /* Copies raw user space buffer, only one type for now. */
-       res = copy_from_user(&path_beneath_attr, rule_attr,
-                            sizeof(path_beneath_attr));
-       if (res) {
-               err = -EFAULT;
-               goto out_put_ruleset;
-       }
-
-       /*
-        * Informs about useless rule: empty allowed_access (i.e. deny rules)
-        * are ignored in path walks.
-        */
-       if (!path_beneath_attr.allowed_access) {
-               err = -ENOMSG;
-               goto out_put_ruleset;
-       }
-       /*
-        * Checks that allowed_access matches the @ruleset constraints
-        * (ruleset->access_masks[0] is automatically upgraded to 64-bits).
-        */
-       mask = landlock_get_raw_fs_access_mask(ruleset, 0);
-       if ((path_beneath_attr.allowed_access | mask) != mask) {
+       switch (rule_type) {
+       case LANDLOCK_RULE_PATH_BENEATH:
+               err = add_rule_path_beneath(ruleset, rule_attr);
+               break;
+       default:
                err = -EINVAL;
-               goto out_put_ruleset;
+               break;
        }
-
-       /* Gets and checks the new rule. */
-       err = get_path_from_fd(path_beneath_attr.parent_fd, &path);
-       if (err)
-               goto out_put_ruleset;
-
-       /* Imports the new rule. */
-       err = landlock_append_fs_rule(ruleset, &path,
-                                     path_beneath_attr.allowed_access);
-       path_put(&path);
-
-out_put_ruleset:
        landlock_put_ruleset(ruleset);
        return err;
 }