Skip to content

Commit 3532b0b

Browse files
l0kodJames Morris
authored andcommitted
landlock: Enable user space to infer supported features
Add a new flag LANDLOCK_CREATE_RULESET_VERSION to landlock_create_ruleset(2). This enables to retreive a Landlock ABI version that is useful to efficiently follow a best-effort security approach. Indeed, it would be a missed opportunity to abort the whole sandbox building, because some features are unavailable, instead of protecting users as much as possible with the subset of features provided by the running kernel. This new flag enables user space to identify the minimum set of Landlock features supported by the running kernel without relying on a filesystem interface (e.g. /proc/version, which might be inaccessible) nor testing multiple syscall argument combinations (i.e. syscall bisection). New Landlock features will be documented and tied to a minimum version number (greater than 1). The current version will be incremented for each new kernel release supporting new Landlock features. User space libraries can leverage this information to seamlessly restrict processes as much as possible while being compatible with newer APIs. This is a much more lighter approach than the previous landlock_get_features(2): the complexity is pushed to user space libraries. This flag meets similar needs as securityfs versions: selinux/policyvers, apparmor/features/*/version* and tomoyo/version. Supporting this flag now will be convenient for backward compatibility. Cc: Arnd Bergmann <[email protected]> Cc: James Morris <[email protected]> Cc: Jann Horn <[email protected]> Cc: Kees Cook <[email protected]> Cc: Serge E. Hallyn <[email protected]> Signed-off-by: Mickaël Salaün <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: James Morris <[email protected]>
1 parent 5526b45 commit 3532b0b

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

include/uapi/linux/landlock.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ struct landlock_ruleset_attr {
2727
__u64 handled_access_fs;
2828
};
2929

30+
/*
31+
* sys_landlock_create_ruleset() flags:
32+
*
33+
* - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
34+
* version.
35+
*/
36+
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
37+
3038
/**
3139
* enum landlock_rule_type - Landlock rule type
3240
*

security/landlock/syscalls.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,28 @@ static const struct file_operations ruleset_fops = {
128128
.write = fop_dummy_write,
129129
};
130130

131+
#define LANDLOCK_ABI_VERSION 1
132+
131133
/**
132134
* sys_landlock_create_ruleset - Create a new ruleset
133135
*
134136
* @attr: Pointer to a &struct landlock_ruleset_attr identifying the scope of
135137
* the new ruleset.
136138
* @size: Size of the pointed &struct landlock_ruleset_attr (needed for
137139
* backward and forward compatibility).
138-
* @flags: Must be 0.
140+
* @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION.
139141
*
140142
* This system call enables to create a new Landlock ruleset, and returns the
141143
* related file descriptor on success.
142144
*
145+
* If @flags is %LANDLOCK_CREATE_RULESET_VERSION and @attr is NULL and @size is
146+
* 0, then the returned value is the highest supported Landlock ABI version
147+
* (starting at 1).
148+
*
143149
* Possible returned errors are:
144150
*
145151
* - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
146-
* - EINVAL: @flags is not 0, or unknown access, or too small @size;
152+
* - EINVAL: unknown @flags, or unknown access, or too small @size;
147153
* - E2BIG or EFAULT: @attr or @size inconsistencies;
148154
* - ENOMSG: empty &landlock_ruleset_attr.handled_access_fs.
149155
*/
@@ -161,9 +167,12 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
161167
if (!landlock_initialized)
162168
return -EOPNOTSUPP;
163169

164-
/* No flag for now. */
165-
if (flags)
170+
if (flags) {
171+
if ((flags == LANDLOCK_CREATE_RULESET_VERSION)
172+
&& !attr && !size)
173+
return LANDLOCK_ABI_VERSION;
166174
return -EINVAL;
175+
}
167176

168177
/* Copies raw user space buffer. */
169178
err = copy_min_struct_from_user(&ruleset_attr, sizeof(ruleset_attr),

tools/testing/selftests/landlock/base_test.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,53 @@ TEST(inconsistent_attr) {
6363
free(buf);
6464
}
6565

66+
TEST(abi_version) {
67+
const struct landlock_ruleset_attr ruleset_attr = {
68+
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
69+
};
70+
ASSERT_EQ(1, landlock_create_ruleset(NULL, 0,
71+
LANDLOCK_CREATE_RULESET_VERSION));
72+
73+
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
74+
LANDLOCK_CREATE_RULESET_VERSION));
75+
ASSERT_EQ(EINVAL, errno);
76+
77+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
78+
LANDLOCK_CREATE_RULESET_VERSION));
79+
ASSERT_EQ(EINVAL, errno);
80+
81+
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
82+
sizeof(ruleset_attr),
83+
LANDLOCK_CREATE_RULESET_VERSION));
84+
ASSERT_EQ(EINVAL, errno);
85+
86+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
87+
LANDLOCK_CREATE_RULESET_VERSION | 1 << 31));
88+
ASSERT_EQ(EINVAL, errno);
89+
}
90+
91+
TEST(inval_create_ruleset_flags) {
92+
const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
93+
const int invalid_flag = last_flag << 1;
94+
const struct landlock_ruleset_attr ruleset_attr = {
95+
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
96+
};
97+
98+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0, invalid_flag));
99+
ASSERT_EQ(EINVAL, errno);
100+
101+
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, invalid_flag));
102+
ASSERT_EQ(EINVAL, errno);
103+
104+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
105+
invalid_flag));
106+
ASSERT_EQ(EINVAL, errno);
107+
108+
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
109+
sizeof(ruleset_attr), invalid_flag));
110+
ASSERT_EQ(EINVAL, errno);
111+
}
112+
66113
TEST(empty_path_beneath_attr) {
67114
const struct landlock_ruleset_attr ruleset_attr = {
68115
.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,

0 commit comments

Comments
 (0)