Skip to content

Commit e17c89a

Browse files
l0kodvijay-suman
authored andcommitted
landlock: Add the errata interface
commit 15383a0d63dbcd63dc7e8d9ec1bf3a0f7ebf64ac upstream. Some fixes may require user space to check if they are applied on the running kernel before using a specific feature. For instance, this applies when a restriction was previously too restrictive and is now getting relaxed (e.g. for compatibility reasons). However, non-visible changes for legitimate use (e.g. security fixes) do not require an erratum. Because fixes are backported down to a specific Landlock ABI, we need a way to avoid cherry-pick conflicts. The solution is to only update a file related to the lower ABI impacted by this issue. All the ABI files are then used to create a bitmask of fixes. The new errata interface is similar to the one used to get the supported Landlock ABI version, but it returns a bitmask instead because the order of fixes may not match the order of versions, and not all fixes may apply to all versions. The actual errata will come with dedicated commits. The description is not actually used in the code but serves as documentation. Create the landlock_abi_version symbol and use its value to check errata consistency. Update test_base's create_ruleset_checks_ordering tests and add errata tests. This commit is backportable down to the first version of Landlock. Fixes: 3532b0b ("landlock: Enable user space to infer supported features") Cc: Günther Noack <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mickaël Salaün <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit 6955fd3a6fb9aece02c53aa342bbc3f4586b2814) Signed-off-by: Vijayendra Suman <[email protected]>
1 parent c99c911 commit e17c89a

File tree

6 files changed

+185
-5
lines changed

6 files changed

+185
-5
lines changed

include/uapi/linux/landlock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ struct landlock_ruleset_attr {
3232
*
3333
* - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
3434
* version.
35+
* - %LANDLOCK_CREATE_RULESET_ERRATA: Get a bitmask of fixed issues.
3536
*/
3637
/* clang-format off */
3738
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
39+
#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
3840
/* clang-format on */
3941

4042
/**

security/landlock/errata.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Landlock - Errata information
4+
*
5+
* Copyright © 2025 Microsoft Corporation
6+
*/
7+
8+
#ifndef _SECURITY_LANDLOCK_ERRATA_H
9+
#define _SECURITY_LANDLOCK_ERRATA_H
10+
11+
#include <linux/init.h>
12+
13+
struct landlock_erratum {
14+
const int abi;
15+
const u8 number;
16+
};
17+
18+
/* clang-format off */
19+
#define LANDLOCK_ERRATUM(NUMBER) \
20+
{ \
21+
.abi = LANDLOCK_ERRATA_ABI, \
22+
.number = NUMBER, \
23+
},
24+
/* clang-format on */
25+
26+
/*
27+
* Some fixes may require user space to check if they are applied on the running
28+
* kernel before using a specific feature. For instance, this applies when a
29+
* restriction was previously too restrictive and is now getting relaxed (for
30+
* compatibility or semantic reasons). However, non-visible changes for
31+
* legitimate use (e.g. security fixes) do not require an erratum.
32+
*/
33+
static const struct landlock_erratum landlock_errata_init[] __initconst = {
34+
35+
/*
36+
* Only Sparse may not implement __has_include. If a compiler does not
37+
* implement __has_include, a warning will be printed at boot time (see
38+
* setup.c).
39+
*/
40+
#ifdef __has_include
41+
42+
#define LANDLOCK_ERRATA_ABI 1
43+
#if __has_include("errata/abi-1.h")
44+
#include "errata/abi-1.h"
45+
#endif
46+
#undef LANDLOCK_ERRATA_ABI
47+
48+
#define LANDLOCK_ERRATA_ABI 2
49+
#if __has_include("errata/abi-2.h")
50+
#include "errata/abi-2.h"
51+
#endif
52+
#undef LANDLOCK_ERRATA_ABI
53+
54+
#define LANDLOCK_ERRATA_ABI 3
55+
#if __has_include("errata/abi-3.h")
56+
#include "errata/abi-3.h"
57+
#endif
58+
#undef LANDLOCK_ERRATA_ABI
59+
60+
#define LANDLOCK_ERRATA_ABI 4
61+
#if __has_include("errata/abi-4.h")
62+
#include "errata/abi-4.h"
63+
#endif
64+
#undef LANDLOCK_ERRATA_ABI
65+
66+
/*
67+
* For each new erratum, we need to include all the ABI files up to the impacted
68+
* ABI to make all potential future intermediate errata easy to backport.
69+
*
70+
* If such change involves more than one ABI addition, then it must be in a
71+
* dedicated commit with the same Fixes tag as used for the actual fix.
72+
*
73+
* Each commit creating a new security/landlock/errata/abi-*.h file must have a
74+
* Depends-on tag to reference the commit that previously added the line to
75+
* include this new file, except if the original Fixes tag is enough.
76+
*
77+
* Each erratum must be documented in its related ABI file, and a dedicated
78+
* commit must update Documentation/userspace-api/landlock.rst to include this
79+
* erratum. This commit will not be backported.
80+
*/
81+
82+
#endif
83+
84+
{}
85+
};
86+
87+
#endif /* _SECURITY_LANDLOCK_ERRATA_H */

security/landlock/setup.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
* Copyright © 2018-2020 ANSSI
77
*/
88

9+
#include <linux/bits.h>
910
#include <linux/init.h>
1011
#include <linux/lsm_hooks.h>
1112

1213
#include "common.h"
1314
#include "cred.h"
15+
#include "errata.h"
1416
#include "fs.h"
1517
#include "ptrace.h"
1618
#include "setup.h"
@@ -23,8 +25,36 @@ struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
2325
.lbs_superblock = sizeof(struct landlock_superblock_security),
2426
};
2527

28+
int landlock_errata __ro_after_init;
29+
30+
static void __init compute_errata(void)
31+
{
32+
size_t i;
33+
34+
#ifndef __has_include
35+
/*
36+
* This is a safeguard to make sure the compiler implements
37+
* __has_include (see errata.h).
38+
*/
39+
WARN_ON_ONCE(1);
40+
return;
41+
#endif
42+
43+
for (i = 0; landlock_errata_init[i].number; i++) {
44+
const int prev_errata = landlock_errata;
45+
46+
if (WARN_ON_ONCE(landlock_errata_init[i].abi >
47+
landlock_abi_version))
48+
continue;
49+
50+
landlock_errata |= BIT(landlock_errata_init[i].number - 1);
51+
WARN_ON_ONCE(prev_errata == landlock_errata);
52+
}
53+
}
54+
2655
static int __init landlock_init(void)
2756
{
57+
compute_errata();
2858
landlock_add_cred_hooks();
2959
landlock_add_ptrace_hooks();
3060
landlock_add_fs_hooks();

security/landlock/setup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
#include <linux/lsm_hooks.h>
1313

14+
extern const int landlock_abi_version;
15+
1416
extern bool landlock_initialized;
17+
extern int landlock_errata;
1518

1619
extern struct lsm_blob_sizes landlock_blob_sizes;
1720

security/landlock/syscalls.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ static const struct file_operations ruleset_fops = {
150150
* the new ruleset.
151151
* @size: Size of the pointed &struct landlock_ruleset_attr (needed for
152152
* backward and forward compatibility).
153-
* @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION.
153+
* @flags: Supported value:
154+
* - %LANDLOCK_CREATE_RULESET_VERSION
155+
* - %LANDLOCK_CREATE_RULESET_ERRATA
154156
*
155157
* This system call enables to create a new Landlock ruleset, and returns the
156158
* related file descriptor on success.
@@ -159,6 +161,10 @@ static const struct file_operations ruleset_fops = {
159161
* 0, then the returned value is the highest supported Landlock ABI version
160162
* (starting at 1).
161163
*
164+
* If @flags is %LANDLOCK_CREATE_RULESET_ERRATA and @attr is NULL and @size is
165+
* 0, then the returned value is a bitmask of fixed issues for the current
166+
* Landlock ABI version.
167+
*
162168
* Possible returned errors are:
163169
*
164170
* - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
@@ -181,9 +187,15 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
181187
return -EOPNOTSUPP;
182188

183189
if (flags) {
184-
if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr &&
185-
!size)
186-
return LANDLOCK_ABI_VERSION;
190+
if (attr || size)
191+
return -EINVAL;
192+
193+
if (flags == LANDLOCK_CREATE_RULESET_VERSION)
194+
return landlock_abi_version;
195+
196+
if (flags == LANDLOCK_CREATE_RULESET_ERRATA)
197+
return landlock_errata;
198+
187199
return -EINVAL;
188200
}
189201

@@ -213,6 +225,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
213225
return ruleset_fd;
214226
}
215227

228+
const int landlock_abi_version = LANDLOCK_ABI_VERSION;
229+
216230
/*
217231
* Returns an owned ruleset from a FD. It is thus needed to call
218232
* landlock_put_ruleset() on the return value.

tools/testing/selftests/landlock/base_test.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,54 @@ TEST(abi_version)
9898
ASSERT_EQ(EINVAL, errno);
9999
}
100100

101+
/*
102+
* Old source trees might not have the set of Kselftest fixes related to kernel
103+
* UAPI headers.
104+
*/
105+
#ifndef LANDLOCK_CREATE_RULESET_ERRATA
106+
#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
107+
#endif
108+
109+
TEST(errata)
110+
{
111+
const struct landlock_ruleset_attr ruleset_attr = {
112+
.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
113+
};
114+
int errata;
115+
116+
errata = landlock_create_ruleset(NULL, 0,
117+
LANDLOCK_CREATE_RULESET_ERRATA);
118+
/* The errata bitmask will not be backported to tests. */
119+
ASSERT_LE(0, errata);
120+
TH_LOG("errata: 0x%x", errata);
121+
122+
ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
123+
LANDLOCK_CREATE_RULESET_ERRATA));
124+
ASSERT_EQ(EINVAL, errno);
125+
126+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
127+
LANDLOCK_CREATE_RULESET_ERRATA));
128+
ASSERT_EQ(EINVAL, errno);
129+
130+
ASSERT_EQ(-1,
131+
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
132+
LANDLOCK_CREATE_RULESET_ERRATA));
133+
ASSERT_EQ(EINVAL, errno);
134+
135+
ASSERT_EQ(-1, landlock_create_ruleset(
136+
NULL, 0,
137+
LANDLOCK_CREATE_RULESET_VERSION |
138+
LANDLOCK_CREATE_RULESET_ERRATA));
139+
ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
140+
LANDLOCK_CREATE_RULESET_ERRATA |
141+
1 << 31));
142+
ASSERT_EQ(EINVAL, errno);
143+
}
144+
101145
/* Tests ordering of syscall argument checks. */
102146
TEST(create_ruleset_checks_ordering)
103147
{
104-
const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
148+
const int last_flag = LANDLOCK_CREATE_RULESET_ERRATA;
105149
const int invalid_flag = last_flag << 1;
106150
int ruleset_fd;
107151
const struct landlock_ruleset_attr ruleset_attr = {

0 commit comments

Comments
 (0)