Skip to content

Commit e450153

Browse files
author
CKI KWF Bot
committed
Merge: landlock: Add signal scoping
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7632 # Merge Request Required Information ## Summary of Changes Adds signal scoping into landlock together with some other relevant patches. Tested using kernel selftests and the steps from the bug report: Before: ``` [root@ibm-p8-kvm-03-guest-02 centos-stream-9]# podman run -it --security-opt=seccomp=unconfined --cap-add SYS_PTRACE fedora:latest /bin/bash bash-5.3# xz xz: Failed to enable the sandbox ``` After: ``` [root@ibm-p8-kvm-03-guest-02 centos-stream-9]# podman run -it --security-opt=seccomp=unconfined --cap-add SYS_PTRACE fedora:latest /bin/bash bash-5.3# xz xz: Compressed data cannot be written to a terminal xz: Try 'xz --help' for more information. ``` Omitted-fix: 0e4db4f ("selftests/landlock: Fix build with non-default pthread linking") Does not seem to cause issues. ## Approved Development Ticket(s) JIRA: https://issues.redhat.com/browse/RHEL-125143 Signed-off-by: Štěpán Horáček <shoracek@redhat.com> Approved-by: Ondrej Mosnáček <omosnacek@gmail.com> Approved-by: Richard Guy Briggs <rgb@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 97cb268 + 2c780b1 commit e450153

File tree

15 files changed

+728
-8
lines changed

15 files changed

+728
-8
lines changed

include/uapi/linux/landlock.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ struct landlock_ruleset_attr {
5757
*
5858
* - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
5959
* version.
60+
* - %LANDLOCK_CREATE_RULESET_ERRATA: Get a bitmask of fixed issues.
6061
*/
6162
/* clang-format off */
6263
#define LANDLOCK_CREATE_RULESET_VERSION (1U << 0)
64+
#define LANDLOCK_CREATE_RULESET_ERRATA (1U << 1)
6365
/* clang-format on */
6466

6567
/**
@@ -296,9 +298,12 @@ struct landlock_net_port_attr {
296298
* - %LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET: Restrict a sandboxed process from
297299
* connecting to an abstract UNIX socket created by a process outside the
298300
* related Landlock domain (e.g. a parent domain or a non-sandboxed process).
301+
* - %LANDLOCK_SCOPE_SIGNAL: Restrict a sandboxed process from sending a signal
302+
* to another process outside the domain.
299303
*/
300304
/* clang-format off */
301305
#define LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET (1ULL << 0)
306+
#define LANDLOCK_SCOPE_SIGNAL (1ULL << 1)
302307
/* clang-format on*/
303308

304309
#endif /* _UAPI_LINUX_LANDLOCK_H */

security/landlock/cred.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ landlock_cred(const struct cred *cred)
2626
return cred->security + landlock_blob_sizes.lbs_cred;
2727
}
2828

29-
static inline const struct landlock_ruleset *landlock_get_current_domain(void)
29+
static inline struct landlock_ruleset *landlock_get_current_domain(void)
3030
{
3131
return landlock_cred(current_cred())->domain;
3232
}

security/landlock/errata.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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+
#define LANDLOCK_ERRATA_ABI 5
67+
#if __has_include("errata/abi-5.h")
68+
#include "errata/abi-5.h"
69+
#endif
70+
#undef LANDLOCK_ERRATA_ABI
71+
72+
#define LANDLOCK_ERRATA_ABI 6
73+
#if __has_include("errata/abi-6.h")
74+
#include "errata/abi-6.h"
75+
#endif
76+
#undef LANDLOCK_ERRATA_ABI
77+
78+
/*
79+
* For each new erratum, we need to include all the ABI files up to the impacted
80+
* ABI to make all potential future intermediate errata easy to backport.
81+
*
82+
* If such change involves more than one ABI addition, then it must be in a
83+
* dedicated commit with the same Fixes tag as used for the actual fix.
84+
*
85+
* Each commit creating a new security/landlock/errata/abi-*.h file must have a
86+
* Depends-on tag to reference the commit that previously added the line to
87+
* include this new file, except if the original Fixes tag is enough.
88+
*
89+
* Each erratum must be documented in its related ABI file, and a dedicated
90+
* commit must update Documentation/userspace-api/landlock.rst to include this
91+
* erratum. This commit will not be backported.
92+
*/
93+
94+
#endif
95+
96+
{}
97+
};
98+
99+
#endif /* _SECURITY_LANDLOCK_ERRATA_H */

security/landlock/errata/abi-6.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
/**
4+
* DOC: erratum_2
5+
*
6+
* Erratum 2: Scoped signal handling
7+
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
*
9+
* This fix addresses an issue where signal scoping was overly restrictive,
10+
* preventing sandboxed threads from signaling other threads within the same
11+
* process if they belonged to different domains. Because threads are not
12+
* security boundaries, user space might assume that any thread within the same
13+
* process can send signals between themselves (see :manpage:`nptl(7)` and
14+
* :manpage:`libpsx(3)`). Consistent with :manpage:`ptrace(2)` behavior, direct
15+
* interaction between threads of the same process should always be allowed.
16+
* This change ensures that any thread is allowed to send signals to any other
17+
* thread within the same process, regardless of their domain.
18+
*/
19+
LANDLOCK_ERRATUM(2)

security/landlock/fs.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include <linux/mount.h>
2828
#include <linux/namei.h>
2929
#include <linux/path.h>
30+
#include <linux/pid.h>
3031
#include <linux/rcupdate.h>
32+
#include <linux/sched/signal.h>
3133
#include <linux/spinlock.h>
3234
#include <linux/stat.h>
3335
#include <linux/types.h>
@@ -1636,6 +1638,54 @@ static int hook_file_ioctl_compat(struct file *file, unsigned int cmd,
16361638
return -EACCES;
16371639
}
16381640

1641+
/*
1642+
* Always allow sending signals between threads of the same process. This
1643+
* ensures consistency with hook_task_kill().
1644+
*/
1645+
static bool control_current_fowner(struct fown_struct *const fown)
1646+
{
1647+
struct task_struct *p;
1648+
1649+
/*
1650+
* Lock already held by __f_setown(), see commit 26f204380a3c ("fs: Fix
1651+
* file_set_fowner LSM hook inconsistencies").
1652+
*/
1653+
lockdep_assert_held(&fown->lock);
1654+
1655+
/*
1656+
* Some callers (e.g. fcntl_dirnotify) may not be in an RCU read-side
1657+
* critical section.
1658+
*/
1659+
guard(rcu)();
1660+
p = pid_task(fown->pid, fown->pid_type);
1661+
if (!p)
1662+
return true;
1663+
1664+
return !same_thread_group(p, current);
1665+
}
1666+
1667+
static void hook_file_set_fowner(struct file *file)
1668+
{
1669+
struct landlock_ruleset *prev_dom;
1670+
struct landlock_ruleset *new_dom = NULL;
1671+
1672+
if (control_current_fowner(&file->f_owner)) {
1673+
new_dom = landlock_get_current_domain();
1674+
landlock_get_ruleset(new_dom);
1675+
}
1676+
1677+
prev_dom = landlock_file(file)->fown_domain;
1678+
landlock_file(file)->fown_domain = new_dom;
1679+
1680+
/* May be called in an RCU read-side critical section. */
1681+
landlock_put_ruleset_deferred(prev_dom);
1682+
}
1683+
1684+
static void hook_file_free_security(struct file *file)
1685+
{
1686+
landlock_put_ruleset_deferred(landlock_file(file)->fown_domain);
1687+
}
1688+
16391689
static struct security_hook_list landlock_hooks[] __ro_after_init = {
16401690
LSM_HOOK_INIT(inode_free_security, hook_inode_free_security),
16411691

@@ -1660,6 +1710,8 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
16601710
LSM_HOOK_INIT(file_truncate, hook_file_truncate),
16611711
LSM_HOOK_INIT(file_ioctl, hook_file_ioctl),
16621712
LSM_HOOK_INIT(file_ioctl_compat, hook_file_ioctl_compat),
1713+
LSM_HOOK_INIT(file_set_fowner, hook_file_set_fowner),
1714+
LSM_HOOK_INIT(file_free_security, hook_file_free_security),
16631715
};
16641716

16651717
__init void landlock_add_fs_hooks(void)

security/landlock/fs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ struct landlock_file_security {
5252
* needed to authorize later operations on the open file.
5353
*/
5454
access_mask_t allowed_access;
55+
/**
56+
* @fown_domain: Domain of the task that set the PID that may receive a
57+
* signal e.g., SIGURG when writing MSG_OOB to the related socket.
58+
* This pointer is protected by the related file->f_owner->lock, as for
59+
* fown_struct's members: pid, uid, and euid.
60+
*/
61+
struct landlock_ruleset *fown_domain;
5562
};
5663

5764
/**

security/landlock/limits.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#define LANDLOCK_MASK_ACCESS_NET ((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
2727
#define LANDLOCK_NUM_ACCESS_NET __const_hweight64(LANDLOCK_MASK_ACCESS_NET)
2828

29-
#define LANDLOCK_LAST_SCOPE LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
29+
#define LANDLOCK_LAST_SCOPE LANDLOCK_SCOPE_SIGNAL
3030
#define LANDLOCK_MASK_SCOPE ((LANDLOCK_LAST_SCOPE << 1) - 1)
3131
#define LANDLOCK_NUM_SCOPE __const_hweight64(LANDLOCK_MASK_SCOPE)
3232
/* clang-format on */

security/landlock/setup.c

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

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

1314
#include "common.h"
1415
#include "cred.h"
16+
#include "errata.h"
1517
#include "fs.h"
1618
#include "net.h"
1719
#include "setup.h"
@@ -31,8 +33,36 @@ const struct lsm_id landlock_lsmid = {
3133
.id = LSM_ID_LANDLOCK,
3234
};
3335

36+
int landlock_errata __ro_after_init;
37+
38+
static void __init compute_errata(void)
39+
{
40+
size_t i;
41+
42+
#ifndef __has_include
43+
/*
44+
* This is a safeguard to make sure the compiler implements
45+
* __has_include (see errata.h).
46+
*/
47+
WARN_ON_ONCE(1);
48+
return;
49+
#endif
50+
51+
for (i = 0; landlock_errata_init[i].number; i++) {
52+
const int prev_errata = landlock_errata;
53+
54+
if (WARN_ON_ONCE(landlock_errata_init[i].abi >
55+
landlock_abi_version))
56+
continue;
57+
58+
landlock_errata |= BIT(landlock_errata_init[i].number - 1);
59+
WARN_ON_ONCE(prev_errata == landlock_errata);
60+
}
61+
}
62+
3463
static int __init landlock_init(void)
3564
{
65+
compute_errata();
3666
landlock_add_cred_hooks();
3767
landlock_add_task_hooks();
3868
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
extern const struct lsm_id landlock_lsmid;

security/landlock/syscalls.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ static const struct file_operations ruleset_fops = {
159159
* the new ruleset.
160160
* @size: Size of the pointed &struct landlock_ruleset_attr (needed for
161161
* backward and forward compatibility).
162-
* @flags: Supported value: %LANDLOCK_CREATE_RULESET_VERSION.
162+
* @flags: Supported value:
163+
* - %LANDLOCK_CREATE_RULESET_VERSION
164+
* - %LANDLOCK_CREATE_RULESET_ERRATA
163165
*
164166
* This system call enables to create a new Landlock ruleset, and returns the
165167
* related file descriptor on success.
@@ -168,6 +170,10 @@ static const struct file_operations ruleset_fops = {
168170
* 0, then the returned value is the highest supported Landlock ABI version
169171
* (starting at 1).
170172
*
173+
* If @flags is %LANDLOCK_CREATE_RULESET_ERRATA and @attr is NULL and @size is
174+
* 0, then the returned value is a bitmask of fixed issues for the current
175+
* Landlock ABI version.
176+
*
171177
* Possible returned errors are:
172178
*
173179
* - %EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
@@ -191,9 +197,15 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
191197
return -EOPNOTSUPP;
192198

193199
if (flags) {
194-
if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr &&
195-
!size)
196-
return LANDLOCK_ABI_VERSION;
200+
if (attr || size)
201+
return -EINVAL;
202+
203+
if (flags == LANDLOCK_CREATE_RULESET_VERSION)
204+
return landlock_abi_version;
205+
206+
if (flags == LANDLOCK_CREATE_RULESET_ERRATA)
207+
return landlock_errata;
208+
197209
return -EINVAL;
198210
}
199211

@@ -234,6 +246,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
234246
return ruleset_fd;
235247
}
236248

249+
const int landlock_abi_version = LANDLOCK_ABI_VERSION;
250+
237251
/*
238252
* Returns an owned ruleset from a FD. It is thus needed to call
239253
* landlock_put_ruleset() on the return value.

0 commit comments

Comments
 (0)