]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
landlock: Use scoped guards for ruleset
authorMickaël Salaün <mic@digikod.net>
Mon, 13 Jan 2025 16:11:09 +0000 (17:11 +0100)
committerMickaël Salaün <mic@digikod.net>
Tue, 14 Jan 2025 10:57:45 +0000 (11:57 +0100)
Simplify error handling by replacing goto statements with automatic
calls to landlock_put_ruleset() when going out of scope.

This change will be easy to backport to v6.6 if needed, only the
kernel.h include line conflicts.  As for any other similar changes, we
should be careful when backporting without goto statements.

Add missing include file.

Reviewed-by: Günther Noack <gnoack@google.com>
Link: https://lore.kernel.org/r/20250113161112.452505-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
security/landlock/ruleset.c
security/landlock/ruleset.h
security/landlock/syscalls.c

index a93bdbf52fff856a346d7aa6bb3e4df1e61103c1..f27b7bdb19b9286986eeb8246094d2ba36656f3b 100644 (file)
@@ -8,11 +8,13 @@
 
 #include <linux/bits.h>
 #include <linux/bug.h>
+#include <linux/cleanup.h>
 #include <linux/compiler_types.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/lockdep.h>
+#include <linux/mutex.h>
 #include <linux/overflow.h>
 #include <linux/rbtree.h>
 #include <linux/refcount.h>
@@ -537,7 +539,7 @@ struct landlock_ruleset *
 landlock_merge_ruleset(struct landlock_ruleset *const parent,
                       struct landlock_ruleset *const ruleset)
 {
-       struct landlock_ruleset *new_dom;
+       struct landlock_ruleset *new_dom __free(landlock_put_ruleset) = NULL;
        u32 num_layers;
        int err;
 
@@ -557,29 +559,25 @@ landlock_merge_ruleset(struct landlock_ruleset *const parent,
        new_dom = create_ruleset(num_layers);
        if (IS_ERR(new_dom))
                return new_dom;
+
        new_dom->hierarchy =
                kzalloc(sizeof(*new_dom->hierarchy), GFP_KERNEL_ACCOUNT);
-       if (!new_dom->hierarchy) {
-               err = -ENOMEM;
-               goto out_put_dom;
-       }
+       if (!new_dom->hierarchy)
+               return ERR_PTR(-ENOMEM);
+
        refcount_set(&new_dom->hierarchy->usage, 1);
 
        /* ...as a child of @parent... */
        err = inherit_ruleset(parent, new_dom);
        if (err)
-               goto out_put_dom;
+               return ERR_PTR(err);
 
        /* ...and including @ruleset. */
        err = merge_ruleset(new_dom, ruleset);
        if (err)
-               goto out_put_dom;
-
-       return new_dom;
+               return ERR_PTR(err);
 
-out_put_dom:
-       landlock_put_ruleset(new_dom);
-       return ERR_PTR(err);
+       return no_free_ptr(new_dom);
 }
 
 /*
index 631e24d4ffe969a2946879238c117ddaf34d51f0..70e5b53d1c71b4c85ece12fe98823279fd2c5bc0 100644 (file)
@@ -11,6 +11,8 @@
 
 #include <linux/bitops.h>
 #include <linux/build_bug.h>
+#include <linux/cleanup.h>
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
@@ -252,6 +254,9 @@ landlock_create_ruleset(const access_mask_t access_mask_fs,
 void landlock_put_ruleset(struct landlock_ruleset *const ruleset);
 void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset);
 
+DEFINE_FREE(landlock_put_ruleset, struct landlock_ruleset *,
+           if (!IS_ERR_OR_NULL(_T)) landlock_put_ruleset(_T))
+
 int landlock_insert_rule(struct landlock_ruleset *const ruleset,
                         const struct landlock_id id,
                         const access_mask_t access);
index 4ed8e70c25ede6e4dbaf4d77d0e4df8428af9500..5a7f1f77292ed7af126bd3b9a87408d49e9994db 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/anon_inodes.h>
 #include <linux/build_bug.h>
 #include <linux/capability.h>
+#include <linux/cleanup.h>
 #include <linux/compiler_types.h>
 #include <linux/dcache.h>
 #include <linux/err.h>
@@ -456,10 +457,10 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
 SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
                flags)
 {
-       struct landlock_ruleset *new_dom, *ruleset;
+       struct landlock_ruleset *new_dom,
+               *ruleset __free(landlock_put_ruleset) = NULL;
        struct cred *new_cred;
        struct landlock_cred_security *new_llcred;
-       int err;
 
        if (!is_initialized())
                return -EOPNOTSUPP;
@@ -483,10 +484,9 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
 
        /* Prepares new credentials. */
        new_cred = prepare_creds();
-       if (!new_cred) {
-               err = -ENOMEM;
-               goto out_put_ruleset;
-       }
+       if (!new_cred)
+               return -ENOMEM;
+
        new_llcred = landlock_cred(new_cred);
 
        /*
@@ -495,21 +495,12 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
         */
        new_dom = landlock_merge_ruleset(new_llcred->domain, ruleset);
        if (IS_ERR(new_dom)) {
-               err = PTR_ERR(new_dom);
-               goto out_put_creds;
+               abort_creds(new_cred);
+               return PTR_ERR(new_dom);
        }
 
        /* Replaces the old (prepared) domain. */
        landlock_put_ruleset(new_llcred->domain);
        new_llcred->domain = new_dom;
-
-       landlock_put_ruleset(ruleset);
        return commit_creds(new_cred);
-
-out_put_creds:
-       abort_creds(new_cred);
-
-out_put_ruleset:
-       landlock_put_ruleset(ruleset);
-       return err;
 }