Commit e9b4c589 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'landlock-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux

Pull Landlock updates from Mickaël Salaün:
 "New tests, a slight optimization, and some cosmetic changes"

* tag 'landlock-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux:
  landlock: Optimize the number of calls to get_access_mask slightly
  selftests/landlock: Rename "permitted" to "allowed" in ftruncate tests
  landlock: Remove remaining "inline" modifiers in .c files [v6.6]
  landlock: Remove remaining "inline" modifiers in .c files [v6.1]
  landlock: Remove remaining "inline" modifiers in .c files [v5.15]
  selftests/landlock: Add tests to check unhandled rule's access rights
  selftests/landlock: Add tests to check unknown rule's access rights
parents 063a7ce3 0daaa610
...@@ -193,7 +193,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, ...@@ -193,7 +193,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
* *
* Returns NULL if no rule is found or if @dentry is negative. * Returns NULL if no rule is found or if @dentry is negative.
*/ */
static inline const struct landlock_rule * static const struct landlock_rule *
find_rule(const struct landlock_ruleset *const domain, find_rule(const struct landlock_ruleset *const domain,
const struct dentry *const dentry) const struct dentry *const dentry)
{ {
...@@ -220,7 +220,7 @@ find_rule(const struct landlock_ruleset *const domain, ...@@ -220,7 +220,7 @@ find_rule(const struct landlock_ruleset *const domain,
* sockfs, pipefs), but can still be reachable through * sockfs, pipefs), but can still be reachable through
* /proc/<pid>/fd/<file-descriptor> * /proc/<pid>/fd/<file-descriptor>
*/ */
static inline bool is_nouser_or_private(const struct dentry *dentry) static bool is_nouser_or_private(const struct dentry *dentry)
{ {
return (dentry->d_sb->s_flags & SB_NOUSER) || return (dentry->d_sb->s_flags & SB_NOUSER) ||
(d_is_positive(dentry) && (d_is_positive(dentry) &&
...@@ -264,7 +264,7 @@ static const struct landlock_ruleset *get_current_fs_domain(void) ...@@ -264,7 +264,7 @@ static const struct landlock_ruleset *get_current_fs_domain(void)
* *
* @layer_masks_child2: Optional child masks. * @layer_masks_child2: Optional child masks.
*/ */
static inline bool no_more_access( static bool no_more_access(
const layer_mask_t (*const layer_masks_parent1)[LANDLOCK_NUM_ACCESS_FS], const layer_mask_t (*const layer_masks_parent1)[LANDLOCK_NUM_ACCESS_FS],
const layer_mask_t (*const layer_masks_child1)[LANDLOCK_NUM_ACCESS_FS], const layer_mask_t (*const layer_masks_child1)[LANDLOCK_NUM_ACCESS_FS],
const bool child1_is_directory, const bool child1_is_directory,
...@@ -316,7 +316,7 @@ static inline bool no_more_access( ...@@ -316,7 +316,7 @@ static inline bool no_more_access(
* *
* Returns true if the request is allowed, false otherwise. * Returns true if the request is allowed, false otherwise.
*/ */
static inline bool static bool
scope_to_request(const access_mask_t access_request, scope_to_request(const access_mask_t access_request,
layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS])
{ {
...@@ -335,7 +335,7 @@ scope_to_request(const access_mask_t access_request, ...@@ -335,7 +335,7 @@ scope_to_request(const access_mask_t access_request,
* Returns true if there is at least one access right different than * Returns true if there is at least one access right different than
* LANDLOCK_ACCESS_FS_REFER. * LANDLOCK_ACCESS_FS_REFER.
*/ */
static inline bool static bool
is_eacces(const layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS], is_eacces(const layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS],
const access_mask_t access_request) const access_mask_t access_request)
{ {
...@@ -551,9 +551,9 @@ static bool is_access_to_paths_allowed( ...@@ -551,9 +551,9 @@ static bool is_access_to_paths_allowed(
return allowed_parent1 && allowed_parent2; return allowed_parent1 && allowed_parent2;
} }
static inline int check_access_path(const struct landlock_ruleset *const domain, static int check_access_path(const struct landlock_ruleset *const domain,
const struct path *const path, const struct path *const path,
access_mask_t access_request) access_mask_t access_request)
{ {
layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {};
...@@ -565,8 +565,8 @@ static inline int check_access_path(const struct landlock_ruleset *const domain, ...@@ -565,8 +565,8 @@ static inline int check_access_path(const struct landlock_ruleset *const domain,
return -EACCES; return -EACCES;
} }
static inline int current_check_access_path(const struct path *const path, static int current_check_access_path(const struct path *const path,
const access_mask_t access_request) const access_mask_t access_request)
{ {
const struct landlock_ruleset *const dom = get_current_fs_domain(); const struct landlock_ruleset *const dom = get_current_fs_domain();
...@@ -575,7 +575,7 @@ static inline int current_check_access_path(const struct path *const path, ...@@ -575,7 +575,7 @@ static inline int current_check_access_path(const struct path *const path,
return check_access_path(dom, path, access_request); return check_access_path(dom, path, access_request);
} }
static inline access_mask_t get_mode_access(const umode_t mode) static access_mask_t get_mode_access(const umode_t mode)
{ {
switch (mode & S_IFMT) { switch (mode & S_IFMT) {
case S_IFLNK: case S_IFLNK:
...@@ -600,7 +600,7 @@ static inline access_mask_t get_mode_access(const umode_t mode) ...@@ -600,7 +600,7 @@ static inline access_mask_t get_mode_access(const umode_t mode)
} }
} }
static inline access_mask_t maybe_remove(const struct dentry *const dentry) static access_mask_t maybe_remove(const struct dentry *const dentry)
{ {
if (d_is_negative(dentry)) if (d_is_negative(dentry))
return 0; return 0;
...@@ -1086,7 +1086,7 @@ static int hook_path_truncate(const struct path *const path) ...@@ -1086,7 +1086,7 @@ static int hook_path_truncate(const struct path *const path)
* Returns the access rights that are required for opening the given file, * Returns the access rights that are required for opening the given file,
* depending on the file type and open mode. * depending on the file type and open mode.
*/ */
static inline access_mask_t static access_mask_t
get_required_file_open_access(const struct file *const file) get_required_file_open_access(const struct file *const file)
{ {
access_mask_t access = 0; access_mask_t access = 0;
......
...@@ -305,7 +305,7 @@ int landlock_insert_rule(struct landlock_ruleset *const ruleset, ...@@ -305,7 +305,7 @@ int landlock_insert_rule(struct landlock_ruleset *const ruleset,
return insert_rule(ruleset, id, &layers, ARRAY_SIZE(layers)); return insert_rule(ruleset, id, &layers, ARRAY_SIZE(layers));
} }
static inline void get_hierarchy(struct landlock_hierarchy *const hierarchy) static void get_hierarchy(struct landlock_hierarchy *const hierarchy)
{ {
if (hierarchy) if (hierarchy)
refcount_inc(&hierarchy->usage); refcount_inc(&hierarchy->usage);
...@@ -723,11 +723,12 @@ landlock_init_layer_masks(const struct landlock_ruleset *const domain, ...@@ -723,11 +723,12 @@ landlock_init_layer_masks(const struct landlock_ruleset *const domain,
/* Saves all handled accesses per layer. */ /* Saves all handled accesses per layer. */
for (layer_level = 0; layer_level < domain->num_layers; layer_level++) { for (layer_level = 0; layer_level < domain->num_layers; layer_level++) {
const unsigned long access_req = access_request; const unsigned long access_req = access_request;
const access_mask_t access_mask =
get_access_mask(domain, layer_level);
unsigned long access_bit; unsigned long access_bit;
for_each_set_bit(access_bit, &access_req, num_access) { for_each_set_bit(access_bit, &access_req, num_access) {
if (BIT_ULL(access_bit) & if (BIT_ULL(access_bit) & access_mask) {
get_access_mask(domain, layer_level)) {
(*layer_masks)[access_bit] |= (*layer_masks)[access_bit] |=
BIT_ULL(layer_level); BIT_ULL(layer_level);
handled_accesses |= BIT_ULL(access_bit); handled_accesses |= BIT_ULL(access_bit);
......
...@@ -589,7 +589,7 @@ TEST_F_FORK(layout1, file_and_dir_access_rights) ...@@ -589,7 +589,7 @@ TEST_F_FORK(layout1, file_and_dir_access_rights)
ASSERT_EQ(0, close(ruleset_fd)); ASSERT_EQ(0, close(ruleset_fd));
} }
TEST_F_FORK(layout0, unknown_access_rights) TEST_F_FORK(layout0, ruleset_with_unknown_access)
{ {
__u64 access_mask; __u64 access_mask;
...@@ -605,6 +605,67 @@ TEST_F_FORK(layout0, unknown_access_rights) ...@@ -605,6 +605,67 @@ TEST_F_FORK(layout0, unknown_access_rights)
} }
} }
TEST_F_FORK(layout0, rule_with_unknown_access)
{
__u64 access;
struct landlock_path_beneath_attr path_beneath = {};
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = ACCESS_ALL,
};
const int ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
path_beneath.parent_fd =
open(TMP_DIR, O_PATH | O_DIRECTORY | O_CLOEXEC);
ASSERT_LE(0, path_beneath.parent_fd);
for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) {
path_beneath.allowed_access = access;
EXPECT_EQ(-1, landlock_add_rule(ruleset_fd,
LANDLOCK_RULE_PATH_BENEATH,
&path_beneath, 0));
EXPECT_EQ(EINVAL, errno);
}
ASSERT_EQ(0, close(path_beneath.parent_fd));
ASSERT_EQ(0, close(ruleset_fd));
}
TEST_F_FORK(layout1, rule_with_unhandled_access)
{
struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
};
struct landlock_path_beneath_attr path_beneath = {};
int ruleset_fd;
__u64 access;
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
path_beneath.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
ASSERT_LE(0, path_beneath.parent_fd);
for (access = 1; access > 0; access <<= 1) {
int err;
path_beneath.allowed_access = access;
err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
&path_beneath, 0);
if (access == ruleset_attr.handled_access_fs) {
EXPECT_EQ(0, err);
} else {
EXPECT_EQ(-1, err);
EXPECT_EQ(EINVAL, errno);
}
}
EXPECT_EQ(0, close(path_beneath.parent_fd));
EXPECT_EQ(0, close(ruleset_fd));
}
static void add_path_beneath(struct __test_metadata *const _metadata, static void add_path_beneath(struct __test_metadata *const _metadata,
const int ruleset_fd, const __u64 allowed_access, const int ruleset_fd, const __u64 allowed_access,
const char *const path) const char *const path)
...@@ -3627,7 +3688,7 @@ FIXTURE_TEARDOWN(ftruncate) ...@@ -3627,7 +3688,7 @@ FIXTURE_TEARDOWN(ftruncate)
FIXTURE_VARIANT(ftruncate) FIXTURE_VARIANT(ftruncate)
{ {
const __u64 handled; const __u64 handled;
const __u64 permitted; const __u64 allowed;
const int expected_open_result; const int expected_open_result;
const int expected_ftruncate_result; const int expected_ftruncate_result;
}; };
...@@ -3636,7 +3697,7 @@ FIXTURE_VARIANT(ftruncate) ...@@ -3636,7 +3697,7 @@ FIXTURE_VARIANT(ftruncate)
FIXTURE_VARIANT_ADD(ftruncate, w_w) { FIXTURE_VARIANT_ADD(ftruncate, w_w) {
/* clang-format on */ /* clang-format on */
.handled = LANDLOCK_ACCESS_FS_WRITE_FILE, .handled = LANDLOCK_ACCESS_FS_WRITE_FILE,
.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE, .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
.expected_open_result = 0, .expected_open_result = 0,
.expected_ftruncate_result = 0, .expected_ftruncate_result = 0,
}; };
...@@ -3645,7 +3706,7 @@ FIXTURE_VARIANT_ADD(ftruncate, w_w) { ...@@ -3645,7 +3706,7 @@ FIXTURE_VARIANT_ADD(ftruncate, w_w) {
FIXTURE_VARIANT_ADD(ftruncate, t_t) { FIXTURE_VARIANT_ADD(ftruncate, t_t) {
/* clang-format on */ /* clang-format on */
.handled = LANDLOCK_ACCESS_FS_TRUNCATE, .handled = LANDLOCK_ACCESS_FS_TRUNCATE,
.permitted = LANDLOCK_ACCESS_FS_TRUNCATE, .allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
.expected_open_result = 0, .expected_open_result = 0,
.expected_ftruncate_result = 0, .expected_ftruncate_result = 0,
}; };
...@@ -3654,7 +3715,7 @@ FIXTURE_VARIANT_ADD(ftruncate, t_t) { ...@@ -3654,7 +3715,7 @@ FIXTURE_VARIANT_ADD(ftruncate, t_t) {
FIXTURE_VARIANT_ADD(ftruncate, wt_w) { FIXTURE_VARIANT_ADD(ftruncate, wt_w) {
/* clang-format on */ /* clang-format on */
.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE, .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE,
.expected_open_result = 0, .expected_open_result = 0,
.expected_ftruncate_result = EACCES, .expected_ftruncate_result = EACCES,
}; };
...@@ -3663,8 +3724,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_w) { ...@@ -3663,8 +3724,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_w) {
FIXTURE_VARIANT_ADD(ftruncate, wt_wt) { FIXTURE_VARIANT_ADD(ftruncate, wt_wt) {
/* clang-format on */ /* clang-format on */
.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
.permitted = LANDLOCK_ACCESS_FS_WRITE_FILE | .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
LANDLOCK_ACCESS_FS_TRUNCATE,
.expected_open_result = 0, .expected_open_result = 0,
.expected_ftruncate_result = 0, .expected_ftruncate_result = 0,
}; };
...@@ -3673,7 +3733,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_wt) { ...@@ -3673,7 +3733,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_wt) {
FIXTURE_VARIANT_ADD(ftruncate, wt_t) { FIXTURE_VARIANT_ADD(ftruncate, wt_t) {
/* clang-format on */ /* clang-format on */
.handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE,
.permitted = LANDLOCK_ACCESS_FS_TRUNCATE, .allowed = LANDLOCK_ACCESS_FS_TRUNCATE,
.expected_open_result = EACCES, .expected_open_result = EACCES,
}; };
...@@ -3683,7 +3743,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate) ...@@ -3683,7 +3743,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate)
const struct rule rules[] = { const struct rule rules[] = {
{ {
.path = path, .path = path,
.access = variant->permitted, .access = variant->allowed,
}, },
{}, {},
}; };
...@@ -3724,7 +3784,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes) ...@@ -3724,7 +3784,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes)
const struct rule rules[] = { const struct rule rules[] = {
{ {
.path = path, .path = path,
.access = variant->permitted, .access = variant->allowed,
}, },
{}, {},
}; };
......
...@@ -1260,7 +1260,7 @@ TEST_F(mini, network_access_rights) ...@@ -1260,7 +1260,7 @@ TEST_F(mini, network_access_rights)
} }
/* Checks invalid attribute, out of landlock network access range. */ /* Checks invalid attribute, out of landlock network access range. */
TEST_F(mini, unknown_access_rights) TEST_F(mini, ruleset_with_unknown_access)
{ {
__u64 access_mask; __u64 access_mask;
...@@ -1276,6 +1276,63 @@ TEST_F(mini, unknown_access_rights) ...@@ -1276,6 +1276,63 @@ TEST_F(mini, unknown_access_rights)
} }
} }
TEST_F(mini, rule_with_unknown_access)
{
const struct landlock_ruleset_attr ruleset_attr = {
.handled_access_net = ACCESS_ALL,
};
struct landlock_net_port_attr net_port = {
.port = sock_port_start,
};
int ruleset_fd;
__u64 access;
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
for (access = 1ULL << 63; access != ACCESS_LAST; access >>= 1) {
net_port.allowed_access = access;
EXPECT_EQ(-1,
landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
&net_port, 0));
EXPECT_EQ(EINVAL, errno);
}
EXPECT_EQ(0, close(ruleset_fd));
}
TEST_F(mini, rule_with_unhandled_access)
{
struct landlock_ruleset_attr ruleset_attr = {
.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
};
struct landlock_net_port_attr net_port = {
.port = sock_port_start,
};
int ruleset_fd;
__u64 access;
ruleset_fd =
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
ASSERT_LE(0, ruleset_fd);
for (access = 1; access > 0; access <<= 1) {
int err;
net_port.allowed_access = access;
err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
&net_port, 0);
if (access == ruleset_attr.handled_access_net) {
EXPECT_EQ(0, err);
} else {
EXPECT_EQ(-1, err);
EXPECT_EQ(EINVAL, errno);
}
}
EXPECT_EQ(0, close(ruleset_fd));
}
TEST_F(mini, inval) TEST_F(mini, inval)
{ {
const struct landlock_ruleset_attr ruleset_attr = { const struct landlock_ruleset_attr ruleset_attr = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment