Skip to content

Commit 90a855e

Browse files
committed
Merge tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux
Pull landlock fixes from Mickaël Salaün: "This fixes TCP handling, tests, documentation, non-audit elided code, and minor cosmetic changes" * tag 'landlock-6.19-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: landlock: Clarify documentation for the IOCTL access right selftests/landlock: Properly close a file descriptor landlock: Improve the comment for domain_is_scoped selftests/landlock: Use scoped_base_variants.h for ptrace_test selftests/landlock: Fix missing semicolon selftests/landlock: Fix typo in fs_test landlock: Optimize stack usage when !CONFIG_AUDIT landlock: Fix spelling landlock: Clean up hook_ptrace_access_check() landlock: Improve erratum documentation landlock: Remove useless include landlock: Fix wrong type usage selftests/landlock: NULL-terminate unix pathname addresses selftests/landlock: Remove invalid unix socket bind() selftests/landlock: Add missing connect(minimal AF_UNSPEC) test selftests/landlock: Fix TCP bind(AF_UNSPEC) test case landlock: Fix TCP handling of short AF_UNSPEC addresses landlock: Fix formatting
2 parents 6f32aa9 + 6abbb87 commit 90a855e

File tree

14 files changed

+170
-269
lines changed

14 files changed

+170
-269
lines changed

include/uapi/linux/landlock.h

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ struct landlock_net_port_attr {
216216
* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with
217217
* ``O_TRUNC``. This access right is available since the third version of the
218218
* Landlock ABI.
219+
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
220+
* character or block device.
221+
*
222+
* This access right applies to all `ioctl(2)` commands implemented by device
223+
* drivers. However, the following common IOCTL commands continue to be
224+
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
225+
*
226+
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
227+
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
228+
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
229+
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
230+
* * Some IOCTL commands which do not make sense when used with devices, but
231+
* whose implementations are safe and return the right error codes
232+
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
233+
*
234+
* This access right is available since the fifth version of the Landlock
235+
* ABI.
219236
*
220237
* Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
221238
* with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -275,26 +292,6 @@ struct landlock_net_port_attr {
275292
* If multiple requirements are not met, the ``EACCES`` error code takes
276293
* precedence over ``EXDEV``.
277294
*
278-
* The following access right applies both to files and directories:
279-
*
280-
* - %LANDLOCK_ACCESS_FS_IOCTL_DEV: Invoke :manpage:`ioctl(2)` commands on an opened
281-
* character or block device.
282-
*
283-
* This access right applies to all `ioctl(2)` commands implemented by device
284-
* drivers. However, the following common IOCTL commands continue to be
285-
* invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL_DEV right:
286-
*
287-
* * IOCTL commands targeting file descriptors (``FIOCLEX``, ``FIONCLEX``),
288-
* * IOCTL commands targeting file descriptions (``FIONBIO``, ``FIOASYNC``),
289-
* * IOCTL commands targeting file systems (``FIFREEZE``, ``FITHAW``,
290-
* ``FIGETBSZ``, ``FS_IOC_GETFSUUID``, ``FS_IOC_GETFSSYSFSPATH``)
291-
* * Some IOCTL commands which do not make sense when used with devices, but
292-
* whose implementations are safe and return the right error codes
293-
* (``FS_IOC_FIEMAP``, ``FICLONE``, ``FICLONERANGE``, ``FIDEDUPERANGE``)
294-
*
295-
* This access right is available since the fifth version of the Landlock
296-
* ABI.
297-
*
298295
* .. warning::
299296
*
300297
* It is currently not possible to restrict some file-related actions

security/landlock/audit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static size_t get_denied_layer(const struct landlock_ruleset *const domain,
191191
long youngest_layer = -1;
192192

193193
for_each_set_bit(access_bit, &access_req, layer_masks_size) {
194-
const access_mask_t mask = (*layer_masks)[access_bit];
194+
const layer_mask_t mask = (*layer_masks)[access_bit];
195195
long layer;
196196

197197
if (!mask)

security/landlock/domain.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ struct landlock_hierarchy {
9797
*/
9898
atomic64_t num_denials;
9999
/**
100-
* @id: Landlock domain ID, sets once at domain creation time.
100+
* @id: Landlock domain ID, set once at domain creation time.
101101
*/
102102
u64 id;
103103
/**

security/landlock/errata/abi-6.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* This fix addresses an issue where signal scoping was overly restrictive,
1010
* preventing sandboxed threads from signaling other threads within the same
1111
* process if they belonged to different domains. Because threads are not
12-
* security boundaries, user space might assume that any thread within the same
12+
* security boundaries, user space might assume that all threads within the same
1313
* process can send signals between themselves (see :manpage:`nptl(7)` and
1414
* :manpage:`libpsx(3)`). Consistent with :manpage:`ptrace(2)` behavior, direct
1515
* interaction between threads of the same process should always be allowed.

security/landlock/fs.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,12 @@ static bool is_access_to_paths_allowed(
939939
}
940940
path_put(&walker_path);
941941

942-
if (!allowed_parent1) {
942+
/*
943+
* Check CONFIG_AUDIT to enable elision of log_request_parent* and
944+
* associated caller's stack variables thanks to dead code elimination.
945+
*/
946+
#ifdef CONFIG_AUDIT
947+
if (!allowed_parent1 && log_request_parent1) {
943948
log_request_parent1->type = LANDLOCK_REQUEST_FS_ACCESS;
944949
log_request_parent1->audit.type = LSM_AUDIT_DATA_PATH;
945950
log_request_parent1->audit.u.path = *path;
@@ -949,7 +954,7 @@ static bool is_access_to_paths_allowed(
949954
ARRAY_SIZE(*layer_masks_parent1);
950955
}
951956

952-
if (!allowed_parent2) {
957+
if (!allowed_parent2 && log_request_parent2) {
953958
log_request_parent2->type = LANDLOCK_REQUEST_FS_ACCESS;
954959
log_request_parent2->audit.type = LSM_AUDIT_DATA_PATH;
955960
log_request_parent2->audit.u.path = *path;
@@ -958,6 +963,8 @@ static bool is_access_to_paths_allowed(
958963
log_request_parent2->layer_masks_size =
959964
ARRAY_SIZE(*layer_masks_parent2);
960965
}
966+
#endif /* CONFIG_AUDIT */
967+
961968
return allowed_parent1 && allowed_parent2;
962969
}
963970

@@ -1314,7 +1321,8 @@ static void hook_sb_delete(struct super_block *const sb)
13141321
* second call to iput() for the same Landlock object. Also
13151322
* checks I_NEW because such inode cannot be tied to an object.
13161323
*/
1317-
if (inode_state_read(inode) & (I_FREEING | I_WILL_FREE | I_NEW)) {
1324+
if (inode_state_read(inode) &
1325+
(I_FREEING | I_WILL_FREE | I_NEW)) {
13181326
spin_unlock(&inode->i_lock);
13191327
continue;
13201328
}

security/landlock/net.c

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,61 @@ static int current_check_access_socket(struct socket *const sock,
7171

7272
switch (address->sa_family) {
7373
case AF_UNSPEC:
74+
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) {
75+
/*
76+
* Connecting to an address with AF_UNSPEC dissolves
77+
* the TCP association, which have the same effect as
78+
* closing the connection while retaining the socket
79+
* object (i.e., the file descriptor). As for dropping
80+
* privileges, closing connections is always allowed.
81+
*
82+
* For a TCP access control system, this request is
83+
* legitimate. Let the network stack handle potential
84+
* inconsistencies and return -EINVAL if needed.
85+
*/
86+
return 0;
87+
} else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
88+
/*
89+
* Binding to an AF_UNSPEC address is treated
90+
* differently by IPv4 and IPv6 sockets. The socket's
91+
* family may change under our feet due to
92+
* setsockopt(IPV6_ADDRFORM), but that's ok: we either
93+
* reject entirely or require
94+
* %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so
95+
* it cannot be used to bypass the policy.
96+
*
97+
* IPv4 sockets map AF_UNSPEC to AF_INET for
98+
* retrocompatibility for bind accesses, only if the
99+
* address is INADDR_ANY (cf. __inet_bind). IPv6
100+
* sockets always reject it.
101+
*
102+
* Checking the address is required to not wrongfully
103+
* return -EACCES instead of -EAFNOSUPPORT or -EINVAL.
104+
* We could return 0 and let the network stack handle
105+
* these checks, but it is safer to return a proper
106+
* error and test consistency thanks to kselftest.
107+
*/
108+
if (sock->sk->__sk_common.skc_family == AF_INET) {
109+
const struct sockaddr_in *const sockaddr =
110+
(struct sockaddr_in *)address;
111+
112+
if (addrlen < sizeof(struct sockaddr_in))
113+
return -EINVAL;
114+
115+
if (sockaddr->sin_addr.s_addr !=
116+
htonl(INADDR_ANY))
117+
return -EAFNOSUPPORT;
118+
} else {
119+
if (addrlen < SIN6_LEN_RFC2133)
120+
return -EINVAL;
121+
else
122+
return -EAFNOSUPPORT;
123+
}
124+
} else {
125+
WARN_ON_ONCE(1);
126+
}
127+
/* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */
128+
fallthrough;
74129
case AF_INET: {
75130
const struct sockaddr_in *addr4;
76131

@@ -119,57 +174,18 @@ static int current_check_access_socket(struct socket *const sock,
119174
return 0;
120175
}
121176

122-
/* Specific AF_UNSPEC handling. */
123-
if (address->sa_family == AF_UNSPEC) {
124-
/*
125-
* Connecting to an address with AF_UNSPEC dissolves the TCP
126-
* association, which have the same effect as closing the
127-
* connection while retaining the socket object (i.e., the file
128-
* descriptor). As for dropping privileges, closing
129-
* connections is always allowed.
130-
*
131-
* For a TCP access control system, this request is legitimate.
132-
* Let the network stack handle potential inconsistencies and
133-
* return -EINVAL if needed.
134-
*/
135-
if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP)
136-
return 0;
137-
138-
/*
139-
* For compatibility reason, accept AF_UNSPEC for bind
140-
* accesses (mapped to AF_INET) only if the address is
141-
* INADDR_ANY (cf. __inet_bind). Checking the address is
142-
* required to not wrongfully return -EACCES instead of
143-
* -EAFNOSUPPORT.
144-
*
145-
* We could return 0 and let the network stack handle these
146-
* checks, but it is safer to return a proper error and test
147-
* consistency thanks to kselftest.
148-
*/
149-
if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) {
150-
/* addrlen has already been checked for AF_UNSPEC. */
151-
const struct sockaddr_in *const sockaddr =
152-
(struct sockaddr_in *)address;
153-
154-
if (sock->sk->__sk_common.skc_family != AF_INET)
155-
return -EINVAL;
156-
157-
if (sockaddr->sin_addr.s_addr != htonl(INADDR_ANY))
158-
return -EAFNOSUPPORT;
159-
}
160-
} else {
161-
/*
162-
* Checks sa_family consistency to not wrongfully return
163-
* -EACCES instead of -EINVAL. Valid sa_family changes are
164-
* only (from AF_INET or AF_INET6) to AF_UNSPEC.
165-
*
166-
* We could return 0 and let the network stack handle this
167-
* check, but it is safer to return a proper error and test
168-
* consistency thanks to kselftest.
169-
*/
170-
if (address->sa_family != sock->sk->__sk_common.skc_family)
171-
return -EINVAL;
172-
}
177+
/*
178+
* Checks sa_family consistency to not wrongfully return
179+
* -EACCES instead of -EINVAL. Valid sa_family changes are
180+
* only (from AF_INET or AF_INET6) to AF_UNSPEC.
181+
*
182+
* We could return 0 and let the network stack handle this
183+
* check, but it is safer to return a proper error and test
184+
* consistency thanks to kselftest.
185+
*/
186+
if (address->sa_family != sock->sk->__sk_common.skc_family &&
187+
address->sa_family != AF_UNSPEC)
188+
return -EINVAL;
173189

174190
id.key.data = (__force uintptr_t)port;
175191
BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));

security/landlock/ruleset.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <linux/workqueue.h>
2424

2525
#include "access.h"
26-
#include "audit.h"
2726
#include "domain.h"
2827
#include "limits.h"
2928
#include "object.h"

security/landlock/task.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ static int hook_ptrace_access_check(struct task_struct *const child,
8686
const unsigned int mode)
8787
{
8888
const struct landlock_cred_security *parent_subject;
89-
const struct landlock_ruleset *child_dom;
9089
int err;
9190

9291
/* Quick return for non-landlocked tasks. */
@@ -96,7 +95,8 @@ static int hook_ptrace_access_check(struct task_struct *const child,
9695

9796
scoped_guard(rcu)
9897
{
99-
child_dom = landlock_get_task_domain(child);
98+
const struct landlock_ruleset *const child_dom =
99+
landlock_get_task_domain(child);
100100
err = domain_ptrace(parent_subject->domain, child_dom);
101101
}
102102

@@ -166,15 +166,15 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
166166
}
167167

168168
/**
169-
* domain_is_scoped - Checks if the client domain is scoped in the same
170-
* domain as the server.
169+
* domain_is_scoped - Check if an interaction from a client/sender to a
170+
* server/receiver should be restricted based on scope controls.
171171
*
172172
* @client: IPC sender domain.
173173
* @server: IPC receiver domain.
174174
* @scope: The scope restriction criteria.
175175
*
176-
* Returns: True if the @client domain is scoped to access the @server,
177-
* unless the @server is also scoped in the same domain as @client.
176+
* Returns: True if @server is in a different domain from @client, and @client
177+
* is scoped to access @server (i.e. access should be denied).
178178
*/
179179
static bool domain_is_scoped(const struct landlock_ruleset *const client,
180180
const struct landlock_ruleset *const server,

tools/testing/selftests/landlock/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ struct service_fixture {
237237
struct sockaddr_un unix_addr;
238238
socklen_t unix_addr_len;
239239
};
240+
struct sockaddr_storage _largest;
240241
};
241242
};
242243

tools/testing/selftests/landlock/fs_test.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4362,22 +4362,24 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
43624362
{
43634363
const char *const path = file1_s1d1;
43644364
int srv_fd, cli_fd, ruleset_fd;
4365-
socklen_t size;
4366-
struct sockaddr_un srv_un, cli_un;
4365+
struct sockaddr_un srv_un = {
4366+
.sun_family = AF_UNIX,
4367+
};
4368+
struct sockaddr_un cli_un = {
4369+
.sun_family = AF_UNIX,
4370+
};
43674371
const struct landlock_ruleset_attr attr = {
43684372
.handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
43694373
};
43704374

43714375
/* Sets up a server */
4372-
srv_un.sun_family = AF_UNIX;
4373-
strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
4374-
43754376
ASSERT_EQ(0, unlink(path));
43764377
srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
43774378
ASSERT_LE(0, srv_fd);
43784379

4379-
size = offsetof(struct sockaddr_un, sun_path) + strlen(srv_un.sun_path);
4380-
ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, size));
4380+
strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
4381+
ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, sizeof(srv_un)));
4382+
43814383
ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */));
43824384

43834385
/* Enables Landlock. */
@@ -4387,24 +4389,18 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
43874389
ASSERT_EQ(0, close(ruleset_fd));
43884390

43894391
/* Sets up a client connection to it */
4390-
cli_un.sun_family = AF_UNIX;
43914392
cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
43924393
ASSERT_LE(0, cli_fd);
43934394

4394-
size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
4395-
ASSERT_EQ(0, bind(cli_fd, (struct sockaddr *)&cli_un, size));
4396-
4397-
bzero(&cli_un, sizeof(cli_un));
4398-
cli_un.sun_family = AF_UNIX;
43994395
strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path));
4400-
size = offsetof(struct sockaddr_un, sun_path) + strlen(cli_un.sun_path);
4401-
4402-
ASSERT_EQ(0, connect(cli_fd, (struct sockaddr *)&cli_un, size));
4396+
ASSERT_EQ(0,
4397+
connect(cli_fd, (struct sockaddr *)&cli_un, sizeof(cli_un)));
44034398

44044399
/* FIONREAD and other IOCTLs should not be forbidden. */
44054400
EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
44064401

4407-
ASSERT_EQ(0, close(cli_fd));
4402+
EXPECT_EQ(0, close(cli_fd));
4403+
EXPECT_EQ(0, close(srv_fd));
44084404
}
44094405

44104406
/* clang-format off */
@@ -7074,8 +7070,8 @@ static int matches_log_fs_extra(struct __test_metadata *const _metadata,
70747070
return -E2BIG;
70757071

70767072
/*
7077-
* It is assume that absolute_path does not contain control characters nor
7078-
* spaces, see audit_string_contains_control().
7073+
* It is assumed that absolute_path does not contain control
7074+
* characters nor spaces, see audit_string_contains_control().
70797075
*/
70807076
absolute_path = realpath(path, NULL);
70817077
if (!absolute_path)

0 commit comments

Comments
 (0)