From: Skye Soss Date: Sat, 18 Jul 2026 19:54:43 +0000 (-0500) Subject: setpriv: limit landlock-rule to access restrictions X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=e8d691feb917f6e7ab46493ecb9b80db3c169dcc;p=thirdparty%2Futil-linux.git setpriv: limit landlock-rule to access restrictions 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 --- diff --git a/sys-utils/setpriv-landlock.c b/sys-utils/setpriv-landlock.c index aeaf1b12f..a40a2990a 100644 --- a/sys-utils/setpriv-landlock.c +++ b/sys-utils/setpriv-landlock.c @@ -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")); } diff --git a/tests/ts/setpriv/landlock b/tests/ts/setpriv/landlock index a6e85c437..c38656da4 100755 --- a/tests/ts/setpriv/landlock +++ b/tests/ts/setpriv/landlock @@ -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