]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
setpriv: limit landlock-rule to access restrictions
authorSkye Soss <skye@soss.website>
Sat, 18 Jul 2026 19:54:43 +0000 (14:54 -0500)
committerSkye Soss <skye@soss.website>
Sun, 2 Aug 2026 02:16:41 +0000 (21:16 -0500)
When `--landlock-rule` is provided without an explicit list of
restrictions (ex. `--landlock-rule path-beneath::/`), setpriv would
treat this as if it was specifying all access restrictions. If the
`--landlock-access` argument only specified a limited set of
restrictions, then the call to landlock_add_rule would fail as setpriv
would attempt to allow an access pattern that wasn't being restricted.

Now, passing an empty list of access patterns is instead treated as "all
access restrictions that are enabled". So `setpriv --landlock-access
fs:execute --landlock-rule path-beneath::/usr -- true` will now be
treated as if `--landlock-rule path-beneath:execute:/usr` was provided.

Signed-off-by: Skye Soss <skye@soss.website>
sys-utils/setpriv-landlock.c
tests/ts/setpriv/landlock

index aeaf1b12f4a4997f27697153312a22747cad80d7..a40a2990a251bfcb50a9ad62cd2dc1ac934bcdd5 100644 (file)
@@ -157,10 +157,6 @@ static uint64_t parse_landlock_fs_access(const char *list)
 {
        unsigned long r = 0;
 
-       /* without argument, match all supported by the current kernel */
-       if (list[0] == '\0')
-               return landlock_abi_fs_mask();
-
        if (string_to_bitmask(list, &r, landlock_access_to_mask))
                errx(EXIT_FAILURE,
                     _("could not parse landlock fs access: %s"), list);
@@ -172,13 +168,14 @@ void parse_landlock_access(struct setpriv_landlock_opts *opts, const char *str)
 {
        const char *type;
 
+       type = ul_startswith(str, "fs:");
+
        /* without argument, match all supported by the current kernel */
-       if (strcmp(str, "fs") == 0) {
+       if (strcmp(str, "fs") == 0 || (type && type[0] == '\0')) {
                opts->access_fs |= landlock_abi_fs_mask();
                return;
        }
 
-       type = ul_startswith(str, "fs:");
        if (type)
                opts->access_fs |= parse_landlock_fs_access(type);
 }
@@ -199,7 +196,10 @@ void parse_landlock_rule(struct setpriv_landlock_opts *opts, const char *str)
        rule->rule_type = LANDLOCK_RULE_PATH_BENEATH;
 
        accesses_part = xstrndup(accesses, path - accesses);
-       rule->path_beneath_attr.allowed_access = parse_landlock_fs_access(accesses_part);
+       if (accesses_part[0] != '\0')
+               rule->path_beneath_attr.allowed_access = parse_landlock_fs_access(accesses_part);
+       else
+               rule->path_beneath_attr.allowed_access = 0;
        free(accesses_part);
 
        path++;
@@ -223,6 +223,7 @@ void do_landlock(const struct setpriv_landlock_opts *opts)
        struct landlock_rule_entry *rule;
        struct list_head *entry;
        int fd, ret;
+       struct landlock_path_beneath_attr path_beneath_attr;
 
        list_for_each(entry, &opts->rules) {
                rule = list_entry(entry, struct landlock_rule_entry, head);
@@ -248,7 +249,11 @@ void do_landlock(const struct setpriv_landlock_opts *opts)
 
                assert(rule->rule_type == LANDLOCK_RULE_PATH_BENEATH);
 
-               ret = landlock_add_rule(fd, rule->rule_type, &rule->path_beneath_attr, 0);
+               path_beneath_attr = rule->path_beneath_attr;
+               if (!path_beneath_attr.allowed_access)
+                       path_beneath_attr.allowed_access = opts->access_fs;
+
+               ret = landlock_add_rule(fd, rule->rule_type, &path_beneath_attr, 0);
                if (ret == -1)
                        err(SETPRIV_EXIT_PRIVERR, _("adding landlock rule failed"));
        }
index a6e85c437636dcd275c8ea76f85c56d3ebb67127..c38656da405d39073192246caf4d4976de5615c2 100755 (executable)
@@ -61,4 +61,18 @@ ts_init_subtest "wildcard-access"
        &> "$TS_OUTPUT"
 ts_finalize_subtest
 
+ts_init_subtest "wildcard-partial-access"
+"$TS_CMD_SETPRIV" --landlock-access fs:execute \
+       --landlock-rule path-beneath::/ \
+       true \
+       &> "$TS_OUTPUT"
+ts_finalize_subtest
+
+ts_init_subtest "wildcard-partial-access-reversed"
+"$TS_CMD_SETPRIV" --landlock-rule path-beneath::/ \
+       --landlock-access fs:execute \
+       true \
+       &> "$TS_OUTPUT"
+ts_finalize_subtest
+
 ts_finalize