landlock: Pathname-based UNIX connect() control
Subsystems (4)
cover landlock: Pathname-based UNIX connect() control
Happy New Year!
This patch set introduces a file-system-based Landlock restriction mechanism for connecting to Unix sockets.
## Motivation
Currently, landlocked processes can connect() to named UNIX sockets through the BSD socket API described in unix(7), by invoking socket(2) followed by connect(2) with a suitable struct sockname_un holding the socket's filename. This can come as a surprise for users (e.g. in [1]) and it can be used to escape a sandbox when a Unix service offers command execution (some scenarios were listed by Tingmao Wang in [2]).
These patches are built on Justin Suess's patch which adds the LSM hook:
https://lore.kernel.org/all/[email protected]/
I am keeping this tagged as "RFC" since Justin's patch is RFC as well so far.
The original feature request is at [4].
## Alternatives and Related Work
### Alternative: Use existing LSM hooks
The existing hooks security_unix_stream_connect(), security_unix_may_send() and security_socket_connect() do not give access to the resolved file system path.
Resolving the file system path again within Landlock would in my understanding produce a TOCTOU race, so making the decision based on the struct sockaddr_un contents is not an option.
It is tempting to use the struct path that the listening socket is bound to, which can be acquired through the existing hooks. Unfortunately, the listening socket may have been bound from within a different namespace, and it is therefore a path that can not actually be referenced by the sandboxed program at the time of constructing the Landlock policy. (More details are on the Github issue at [6]).
### Related work: Scope Control for Pathname Unix Sockets
The motivation for this patch is the same as in Tingmao Wang's patch set for "scoped" control for pathname Unix sockets [2], originally proposed in the Github feature request [5].
In my reply to this patch set [3], I have discussed the differences between these two approaches. On the related discussions on Github
[4] and [5], there was consensus that the scope-based control is complimentary to the file system based control, but does not replace it. Mickael's opening remark on [5] says:
Quoted 3 lines
This scoping would be complementary to #36 which would mainly be about allowing a sandboxed process to connect to a more privileged service (identified with a path).
## Credits
The feature was originally suggested by Jann Horn in [7].
Tingmao Wang and Demi Marie Obenour have taken the initiative to revive this discussion again in [1], [4] and [5] and Tingmao Wang has sent the patch set for the scoped access control for pathname Unix sockets [2].
Justin Suess has sent the patch for the LSM hook in [8].
Ryan Sullivan has started on an initial implementation and has brought up relevant discussion points on the Github issue at [4] that lead to the current approach.
[1] https://lore.kernel.org/landlock/[email protected]/
[2] Tingmao Wang's "Implemnet scope control for pathname Unix sockets"
https://lore.kernel.org/all/[email protected]/
[3] https://lore.kernel.org/all/[email protected]/
[4] Github issue for FS-based control for named Unix sockets:
https://github.com/landlock-lsm/linux/issues/36
[5] Github issue for scope-based restriction of named Unix sockets:
https://github.com/landlock-lsm/linux/issues/51
[6] https://github.com/landlock-lsm/linux/issues/36#issuecomment-2950632277
[7] https://lore.kernel.org/linux-security-module/CAG48ez3NvVnonOqKH4oRwRqbSOLO0p9djBqgvxVwn6gtGQBPcw@mail.gmail.com/
[8] Patch for the LSM hook:
https://lore.kernel.org/linux-security-module/CAG48ez3NvVnonOqKH4oRwRqbSOLO0p9djBqgvxVwn6gtGQBPcw@mail.gmail.com/
Günther Noack (5):
landlock/selftests: add a missing close(srv_fd) call
landlock: Control connections to pathname UNIX sockets by path samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX landlock/selftests: test LANDLOCK_ACCESS_FS_CONNECT_UNIX
landlock: Document LANDLOCK_ACCESS_FS_UNIX_CONNECT
Documentation/userspace-api/landlock.rst | 14 ++- include/uapi/linux/landlock.h | 3 + samples/landlock/sandboxer.c | 11 ++- security/landlock/access.h | 2 +- security/landlock/audit.c | 1 + security/landlock/fs.c | 9 +- security/landlock/limits.h | 2 +- security/landlock/syscalls.c | 2 +- tools/testing/selftests/landlock/base_test.c | 2 +- tools/testing/selftests/landlock/fs_test.c | 94 ++++++++++++++++---- 10 files changed, 113 insertions(+), 27 deletions(-)
Signature · 1 line
2.52.0
RFC PATCH 1/5 landlock/selftests: add a missing close(srv_fd) call
--- tools/testing/selftests/landlock/fs_test.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/landlock/fs_test.c +1 -0
@@ -4400,6 +4400,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd)); }/* clang-format off */
Signature · 1 line
2.52.0
Mickaël Salaün
maintainerRe: [RFC PATCH 1/5] landlock/selftests: add a missing close(srv_fd) call
Good, I'll pick that in my -next branch.
Nit: The prefix should be "selftests/landlock"
Quoted 21 lines · Günther Noack
Signed-off-by Günther Noack <[email protected]>--- tools/testing/selftests/landlock/fs_test.c | 1 + 1 file changed, 1 insertion(+)tools/testing/selftests/landlock/fs_test.c +1
-0@@ -4400,6 +4400,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd)); }/* clang-format off */ Signature · 1 line
2.52.0
Mickaël Salaün
maintainerRe: [RFC PATCH 1/5] landlock/selftests: add a missing close(srv_fd) call
Quoted 17 lines · Mickaël Salaün
Good, I'll pick that in my -next branch.
Nit: The prefix should be "selftests/landlock"
Quoted 12 lines · Günther Noack
Signed-off-by Günther Noack <[email protected]>--- tools/testing/selftests/landlock/fs_test.c | 1 + 1 file changed, 1 insertion(+)tools/testing/selftests/landlock/fs_test.c +0
-0@@ -4400,6 +4400,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) · line 4403
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c +1
-0ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd));
I'll also replace these ASSERT_EQ() with EXPECT_EQ().
Quoted 7 lines
Quoted 7 lines
tools/testing/selftests/landlock/fs_test.c +0
-0}/* clang-format off */ Signature · 1 line
2.52.0
Re: [RFC PATCH 1/5] landlock/selftests: add a missing close(srv_fd) call
Quoted 18 lines · Mickaël Salaün
Quoted 17 lines · Mickaël Salaün
Good, I'll pick that in my -next branch.
Nit: The prefix should be "selftests/landlock"
Quoted 12 lines · Günther Noack
Signed-off-by Günther Noack <[email protected]>--- tools/testing/selftests/landlock/fs_test.c | 1 + 1 file changed, 1 insertion(+)tools/testing/selftests/landlock/fs_test.c +0
-0@@ -4400,6 +4400,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));
Quoted 4 lines
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) · line 4403
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c +1
-0ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd));I'll also replace these
ASSERT_EQ()withEXPECT_EQ().
Fair enough. I would normally prefer ASSERT here, because that would be more symmetric with the corresponding setup steps, but it feels not worth bikeshedding over this.
The selftests, both Landlock and others, are inconsistent in how they use ASSERT and EXPECT, especially for close(). I wish we had an easier way to do state teardown in the selftests without having to tie it to a FIXTURE()...
–Günther
Mickaël Salaün
maintainerRe: [RFC PATCH 1/5] landlock/selftests: add a missing close(srv_fd) call
Quoted 19 lines · Günther Noack
Quoted 18 lines · Mickaël Salaün
Quoted 17 lines · Mickaël Salaün
Good, I'll pick that in my -next branch.
Nit: The prefix should be "selftests/landlock"
Quoted 12 lines · Günther Noack
Signed-off-by Günther Noack <[email protected]>--- tools/testing/selftests/landlock/fs_test.c | 1 + 1 file changed, 1 insertion(+)tools/testing/selftests/landlock/fs_test.c +0
-0@@ -4400,6 +4400,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) · line 4403
Quoted 2 lines
tools/testing/selftests/landlock/fs_test.c +1
-0ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd));I'll also replace these
ASSERT_EQ()withEXPECT_EQ().Fair enough. I would normally prefer ASSERT here, because that would be more symmetric with the corresponding setup steps, but it feels not worth bikeshedding over this.
My thinking is that a close() call will not have any impact on the tests, and it's worth cleaning things as much as possible, but an error should not happen anyway.
As you said a few years ago (or as I remember it), we should use EXPECT as much as possible, especially when checks don't impact following checks. At least, that's how I see things now. ;)
Quoted 3 lines
The selftests, both Landlock and others, are inconsistent in how they use ASSERT and EXPECT, especially for
close().
Indeed. I try to make sure the new Landlock tests use EXPECT for close() though. It's difficult to explain when to use ASSERT or EXPECT, especially because they are used everywhere, and we may not even agree...
Quoted 6 lines
I wish we had an
easier way to do state teardown in the selftests without having to tie it to aFIXTURE()...–Günther
RFC PATCH 2/5 landlock: Control connections to pathname UNIX sockets by path
In reply to Günther Noack* Add the LANDLOCK_ACCESS_FS_CONNECT_UNIX right.
* Hook into the path lookup in unix_find_bsd() in af_unix.c, using a LSM hook. Decide based on the new access right.
* Increment the Landlock ABI version.
* Minor test adaptions to keep the tests working.
--- include/uapi/linux/landlock.h | 3 +++ security/landlock/access.h | 2 +- security/landlock/audit.c | 1 + security/landlock/fs.c | 9 ++++++++- security/landlock/limits.h | 2 +- security/landlock/syscalls.c | 2 +- tools/testing/selftests/landlock/base_test.c | 2 +- tools/testing/selftests/landlock/fs_test.c | 5 +++-- 8 files changed, 19 insertions(+), 7 deletions(-)
include/uapi/linux/landlock.h +3 -0
@@ -216,6 +216,8 @@ struct landlock_net_port_attr {* :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with * ``O_TRUNC``. This access right is available since the third version of the * Landlock ABI. +* - %LANDLOCK_ACCESS_FS_CONNECT_UNIX: Connect to named :manpage:`unix(7)` +* socket files. * * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -321,6 +323,7 @@ struct landlock_net_port_attr {#define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)#define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)#define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15) +#define LANDLOCK_ACCESS_FS_CONNECT_UNIX (1ULL << 16)/* clang-format on */ /**
security/landlock/access.h +1 -1
@@ -34,7 +34,7 @@ LANDLOCK_ACCESS_FS_IOCTL_DEV)/* clang-format on */ -typedef u16 access_mask_t ; +typedef u32 access_mask_t ;/* Makes sure all filesystem access rights can be stored. */ static_assert (BITS_PER_TYPE (access_mask_t) >=LANDLOCK_NUM_ACCESS_FS );
security/landlock/audit.c +1 -0
@@ -37,6 +37,7 @@ static const char *const fs_access_strings[] = { [BIT_INDEX(LANDLOCK_ACCESS_FS_REFER)] = "fs.refer", [BIT_INDEX(LANDLOCK_ACCESS_FS_TRUNCATE)] = "fs.truncate", [BIT_INDEX(LANDLOCK_ACCESS_FS_IOCTL_DEV)] = "fs.ioctl_dev", + [BIT_INDEX (LANDLOCK_ACCESS_FS_CONNECT_UNIX )] ="fs.connect_unix" , };static_assert (ARRAY_SIZE (fs_access_strings) ==LANDLOCK_NUM_ACCESS_FS );
security/landlock/fs.c +8 -1
@@ -314,7 +314,8 @@ static struct landlock_object *get_inode_object(struct inode *const inode)LANDLOCK_ACCESS_FS_WRITE_FILE | \LANDLOCK_ACCESS_FS_READ_FILE | \LANDLOCK_ACCESS_FS_TRUNCATE | \ - LANDLOCK_ACCESS_FS_IOCTL_DEV) +LANDLOCK_ACCESS_FS_IOCTL_DEV | \ + LANDLOCK_ACCESS_FS_CONNECT_UNIX)/* clang-format on */ /*
@@ -1588,6 +1589,11 @@ static int hook_path_truncate(const struct path *const path)return current_check_access_path (path,LANDLOCK_ACCESS_FS_TRUNCATE ); } +static int hook_unix_path_connect (const struct path *const path) +{ +return current_check_access_path (path,LANDLOCK_ACCESS_FS_CONNECT_UNIX ); +} +/* File hooks */ /**
@@ -1872,6 +1878,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {LSM_HOOK_INIT (path_unlink, hook_path_unlink),LSM_HOOK_INIT (path_rmdir, hook_path_rmdir),LSM_HOOK_INIT (path_truncate, hook_path_truncate), +LSM_HOOK_INIT (unix_path_connect, hook_unix_path_connect),LSM_HOOK_INIT (file_alloc_security, hook_file_alloc_security), LSM_HOOK_INIT(file_open, hook_file_open),
security/landlock/limits.h +1 -1
@@ -19,7 +19,7 @@#define LANDLOCK_MAX_NUM_LAYERS 16#define LANDLOCK_MAX_NUM_RULES U32_MAX -#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL_DEV +#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_CONNECT_UNIX#define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)#define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
security/landlock/syscalls.c +1 -1
@@ -161,7 +161,7 @@ static const struct file_operations ruleset_fops = {* Documentation/userspace-api/landlock.rst should be updated to reflect the * UAPI change. */ -const int landlock_abi_version =7 ; +const int landlock_abi_version =8 ;/** * sys_landlock_create_ruleset - Create a new ruleset
tools/testing/selftests/landlock/base_test.c +1 -1
@@ -76,7 +76,7 @@ TEST(abi_version)const struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs =LANDLOCK_ACCESS_FS_READ_FILE , }; -ASSERT_EQ (7 ,landlock_create_ruleset (NULL ,0 , +ASSERT_EQ (8 ,landlock_create_ruleset (NULL ,0 ,LANDLOCK_CREATE_RULESET_VERSION )); ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
tools/testing/selftests/landlock/fs_test.c +3 -2
@@ -575,9 +575,10 @@ TEST_F_FORK(layout1, inval) LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ - LANDLOCK_ACCESS_FS_IOCTL_DEV) + LANDLOCK_ACCESS_FS_IOCTL_DEV | \ + LANDLOCK_ACCESS_FS_CONNECT_UNIX) -#define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL_DEV +#define ACCESS_LAST LANDLOCK_ACCESS_FS_CONNECT_UNIX#define ACCESS_ALL ( \ ACCESS_FILE | \
Signature · 1 line
2.52.0
RFC PATCH 3/5 samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
In reply to Günther NoackAdd unix(7) connect() support to the Landlock sample tool.
The "connect UNIX" right is grouped with the read-write rights in the sample tool. Rationale: In the general case, any operations are possible through a Unix domain socket, including data-mutating operations.
--- samples/landlock/sandboxer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
samples/landlock/sandboxer.c +9 -2
@@ -295,11 +295,12 @@ static bool check_ruleset_scope(const char *const env_var, LANDLOCK_ACCESS_FS_MAKE_SYM | \ LANDLOCK_ACCESS_FS_REFER | \ LANDLOCK_ACCESS_FS_TRUNCATE | \ - LANDLOCK_ACCESS_FS_IOCTL_DEV) + LANDLOCK_ACCESS_FS_IOCTL_DEV | \ + LANDLOCK_ACCESS_FS_CONNECT_UNIX)/* clang-format on */ -#define LANDLOCK_ABI_LAST 7 +#define LANDLOCK_ABI_LAST 8#define XSTR (s) #s#define STR (s) XSTR(s)
@@ -444,6 +445,12 @@ int main(const int argc, char *const argv[], char *const *const envp)"provided by ABI version %d (instead of %d).\n" , LANDLOCK_ABI_LAST, abi); __attribute__((fallthrough)); +case 7 : +/* Removes LANDLOCK_ACCESS_FS_CONNECT_UNIX for ABI < 8 */ + ruleset_attr.handled_access_fs &= + ~LANDLOCK_ACCESS_FS_CONNECT_UNIX ; + + __attribute__((fallthrough));case LANDLOCK_ABI_LAST :break ;default :
Signature · 1 line
2.52.0
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Allow users to separately specify unix socket rights, document the variable, and make the right optional.
---
Notes:
Small fixup suggestion patch to this RFC series.
Handling the unix connect rights separate from other rights makes more sense, and makes the sandboxer much easier to use. Also connect doesn't really neatly correspond to "roughly write" in my opinion, so this puts it in a separate variable documented in the help printout.
This also makes it possible to specify rights on the socket itself, which wasn't possible.
before:
~ # LL_FS_RO=/ LL_FS_RW=/tmp/test.sock landlock-sandboxer sh -c 'echo "hello" | socat - UNIX-CONNECT:/tmp/test.sock'
Executing the sandboxed command...
2026/01/01 19:14:33 socat[78] E connect(, AF=1 "/tmp/test.sock", 16): Permission denied
after:
~ # LL_FS_RO=/ LL_FS_RW= LL_UNIX_CONNECT=/tmp/test.sock landlock-sandboxer sh -c
'echo "hello" | socat - UNIX-CONNECT:/tmp/test.sock'
Executing the sandboxed command...
hello
samples/landlock/sandboxer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
samples/landlock/sandboxer.c +19 -7
@@ -62,6 +62,7 @@ static inline int landlock_restrict_self(const int ruleset_fd,#define ENV_TCP_CONNECT_NAME "LL_TCP_CONNECT"#define ENV_SCOPED_NAME "LL_SCOPED"#define ENV_FORCE_LOG_NAME "LL_FORCE_LOG" +#define ENV_UNIX_CONNECT_NAME "LL_UNIX_CONNECT"#define ENV_DELIMITER ":"static int str2num (const char *numstr,__u64 *num_dst)
@@ -163,8 +164,14 @@ static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd, goto out_free_name; } path_beneath.allowed_access = allowed_access; -if (!S_ISDIR (statbuf.st_mode)) +if (!S_ISDIR (statbuf.st_mode)) { path_beneath.allowed_access &=ACCESS_FILE ; +/* Keep CONNECT_UNIX for socket files. */ +if (S_ISSOCK (statbuf.st_mode)) + path_beneath.allowed_access |= + allowed_access & +LANDLOCK_ACCESS_FS_CONNECT_UNIX ; + }if (landlock_add_rule (ruleset_fd,LANDLOCK_RULE_PATH_BENEATH , &path_beneath,0 )) { fprintf(stderr,
@@ -295,8 +302,7 @@ static bool check_ruleset_scope(const char *const env_var,LANDLOCK_ACCESS_FS_MAKE_SYM | \LANDLOCK_ACCESS_FS_REFER | \LANDLOCK_ACCESS_FS_TRUNCATE | \ -LANDLOCK_ACCESS_FS_IOCTL_DEV | \ - LANDLOCK_ACCESS_FS_CONNECT_UNIX) + LANDLOCK_ACCESS_FS_IOCTL_DEV)/* clang-format on */
@@ -326,6 +332,7 @@ static const char help[] ="* " ENV_SCOPED_NAME ": actions denied on the outside of the landlock domain\n" " - \"a\" to restrict opening abstract unix sockets\n" " - \"s\" to restrict sending signals\n" +"* " ENV_UNIX_CONNECT_NAME ": paths of unix sockets connections are allowed to\n" "\n" "A sandboxer should not log denied access requests to avoid spamming logs, " "but to test audit we can set " ENV_FORCE_LOG_NAME "=1\n"
@@ -353,7 +360,7 @@ int main(const int argc, char *const argv[], char *const *const envp) access_fs_rw =ACCESS_FS_ROUGHLY_READ |ACCESS_FS_ROUGHLY_WRITE ;struct landlock_ruleset_attr ruleset_attr = { - .handled_access_fs = access_fs_rw, + .handled_access_fs = access_fs_rw |LANDLOCK_ACCESS_FS_CONNECT_UNIX , .handled_access_net =LANDLOCK_ACCESS_NET_BIND_TCP |LANDLOCK_ACCESS_NET_CONNECT_TCP , .scoped = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
@@ -460,9 +467,6 @@ int main(const int argc, char *const argv[], char *const *const envp)"provided by ABI version %d (instead of %d).\n" , abi, LANDLOCK_ABI_LAST); } - access_fs_ro &= ruleset_attr.handled_access_fs; - access_fs_rw &= ruleset_attr.handled_access_fs; -/* Removes bind access attribute if not supported by a user. */ env_port_name =getenv (ENV_TCP_BIND_NAME );if (!env_port_name) {
@@ -476,6 +480,9 @@ int main(const int argc, char *const argv[], char *const *const envp) ~LANDLOCK_ACCESS_NET_CONNECT_TCP ; } + access_fs_ro &= ruleset_attr.handled_access_fs; + access_fs_rw &= ruleset_attr.handled_access_fs; +if (check_ruleset_scope (ENV_SCOPED_NAME , &ruleset_attr))return 1 ;
@@ -510,6 +517,11 @@ int main(const int argc, char *const argv[], char *const *const envp)if (populate_ruleset_fs (ENV_FS_RW_NAME , ruleset_fd, access_fs_rw)) { goto err_close_ruleset; } +if (getenv (ENV_UNIX_CONNECT_NAME ) && +populate_ruleset_fs (ENV_UNIX_CONNECT_NAME , ruleset_fd, +LANDLOCK_ACCESS_FS_CONNECT_UNIX )) { + goto err_close_ruleset; + }if (populate_ruleset_net (ENV_TCP_BIND_NAME , ruleset_fd,LANDLOCK_ACCESS_NET_BIND_TCP )) {
Signature · 1 line
2.51.0
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 49 lines · Justin Suess
Allow users to separately specify unix socket rights, document the variable, and make the right optional.
Signed-off-by Justin Suess <[email protected]>Cc Günther Noack <[email protected]>---
Notes:
Small fixup suggestion patch to this RFC series.
Handling the unix connect rights separate from other rights makes more sense, and makes the sandboxer much easier to use. Also connect doesn't really neatly correspond to "roughly write" in my opinion, so this puts it in a separate variable documented in the help printout.
This also makes it possible to specify rights on the socket itself, which wasn't possible.
before:
~ # LL_FS_RO=/ LL_FS_RW=/tmp/test.sock landlock-sandboxer sh -c 'echo "hello" | socat - UNIX-CONNECT:/tmp/test.sock'
Executing the sandboxed command...
2026/01/01 19:14:33 socat[78] Econnect(, AF=1 "/tmp/test.sock", 16): Permission deniedafter:
~ # LL_FS_RO=/ LL_FS_RW= LL_UNIX_CONNECT=/tmp/test.sock landlock-sandboxer sh -c
'echo "hello" | socat - UNIX-CONNECT:/tmp/test.sock'
Executing the sandboxed command...
hellosamples/landlock/sandboxer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)samples/landlock/sandboxer.c +1
-0@@ -62,6 +62,7 @@ static inline int landlock_restrict_self(const int ruleset_fd,#define ENV_TCP_CONNECT_NAME "LL_TCP_CONNECT"#define ENV_SCOPED_NAME "LL_SCOPED"#define ENV_FORCE_LOG_NAME "LL_FORCE_LOG" +#define ENV_UNIX_CONNECT_NAME "LL_UNIX_CONNECT"#define ENV_DELIMITER ":"static int str2num (const char *numstr,__u64 *num_dst)@@ -163,8 +164,14 @@ static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd, goto out_free_name;
samples/landlock/sandboxer.c static int populate_ruleset_fs(const char *const env_var, const int ruleset_fd, · line 173
Quoted 10 lines
samples/landlock/sandboxer.c +6
-1} path_beneath.allowed_access = allowed_access; -if (!S_ISDIR (statbuf.st_mode)) +if (!S_ISDIR (statbuf.st_mode)) { path_beneath.allowed_access &=ACCESS_FILE ; +/* Keep CONNECT_UNIX for socket files. */ +if (S_ISSOCK (statbuf.st_mode)) + path_beneath.allowed_access |= + allowed_access & +LANDLOCK_ACCESS_FS_CONNECT_UNIX ;
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add LANDLOCK_ACCESS_FS_CONNECT_UNIX on socket files (S_ISSOCK(d_backing_inode)) too in landlock_append_fs_rule?
Also, for the sandboxer logic, maybe a better way would be having LANDLOCK_ACCESS_FS_CONNECT_UNIX in ACCESS_FILE (matching the kernel code), then another if(!S_ISSOCK) below this that will clear out LANDLOCK_ACCESS_FS_CONNECT_UNIX if not socket.
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for LANDLOCK_ACCESS_FS_CONNECT_UNIX access to a directory to allow LANDLOCK_ACCESS_FS_CONNECT_UNIX to any socket under that directory. This matches the flexibility mount namespaces can achieve.
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 13 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.
Quoted 5 lines
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.
Right, I forgot about the fact that we also need it on dirs, apologies.
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 20 lines · Tingmao Wang
Quoted 13 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.Quoted 5 lines
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.
Quoted 6 lines
Right, I forgot about the fact that we also need it on dirs, apologies.
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
I agree with this.
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
In reply to Tingmao WangQuoted 18 lines · Tingmao Wang
Quoted 12 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.Quoted 5 lines
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.
Quoted 6 lines
Right, I forgot about the fact that we also need it on dirs, apologies.
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
How do we handle IOCTL access on regular files? I think that landlock will let you put IOCTL rights on regular files even they are not valid for that operation.
Sockets seem like a similar case where the operation is only valid for a subset of file types.
I think we should mirror the existing behavior is for consistency.
Besides, restricting which file types can have that right also makes it harder for applications that may not care about the specific file type, but now would have to check the filetype before making a policy on them (also opening them to TOCTOU).
Justin
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 19 lines · Justin Suess
Quoted 18 lines · Tingmao Wang
Quoted 17 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.
Quoted 7 lines
Quoted 6 lines
Right, I forgot about the fact that we also need it on dirs, apologies.
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
How do we handle IOCTL access on regular files? I think that landlock will let you put IOCTL rights on regular files even they are not valid for that operation.
Regular files definitely support ioctls.
Quoted 5 lines
Sockets seem like a similar case where the operation is only valid for a subset of file types.
I think we should mirror the existing behavior is for consistency.
Besides, restricting which file types can have that right also makes it harder for applications that may not care about the specific file type, but now would have to check the filetype before making a policy on them (also opening them to TOCTOU).
I agree.
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 22 lines · Demi Marie Obenour
Quoted 21 lines · Justin Suess
Quoted 20 lines · Tingmao Wang
Quoted 12 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.Quoted 5 lines
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.Right, I forgot about the fact that we also need it on dirs, apologies.
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
How do we handle IOCTL access on regular files? I think that landlock will let you put IOCTL rights on regular files even they are not valid for that operation.
Regular files definitely support ioctls.
The LANDLOCK_ACCESS_FS_IOCTL_DEV right only applies to ioctl(2) invocations on device files.
Quoted 7 lines
Quoted 5 lines
Sockets seem like a similar case where the operation is only valid for a subset of file types.
I think we should mirror the existing behavior is for consistency.
Besides, restricting which file types can have that right also makes it harder for applications that may not care about the specific file type, but now would have to check the filetype before making a policy on them (also opening them to TOCTOU).
I agree.
I also agree with your interpretation, Justin.
For the record, Landlock's kernel implementation currently groups FS access rights into two groups:
- file access rights
- directory-only rights
When adding a rule, the directory access rights can only be granted on a directory inode. The file access rights can be granted on both a directory inode and a regular file inode.
It is pointless to grant the CONNECT_UNIX (or IOCTL_DEV) right on a file which is not a Unix socket (or device file). But it complicates the userspace API if we introduce more special rules there. - Users of Landlock would have to keep track of all these special cases and mirror the logic, which is error prone. IMHO is is granular enough if we differentiate between files and directories as we currently do.
For reference, this is documented at
https://docs.kernel.org/userspace-api/landlock.html#filesystem-flags
and the logic is implemented in landlock_append_fs_rule() in fs.c.
(Actually, in the implementation, the IOCTL_DEV right is treated the same as one of the ACCESS_FILE rights - I should probably revise that
documentation: That right does not *directly* apply to a directory inode, as directories are not device files. It only inherits down in the file system hierarchy. Looking back at earlier versions of the IOCTL_DEV patch set, it was different there. I think I missed to keep the documentation in-line.)
–Günther
Mickaël Salaün
maintainerRe: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
Quoted 55 lines · Günther Noack
Quoted 22 lines · Demi Marie Obenour
Quoted 21 lines · Justin Suess
Quoted 20 lines · Tingmao Wang
Quoted 12 lines · Demi Marie Obenour
On 1/1/26 17:07, Tingmao Wang wrote:
(snip)
Quoted 8 lines
Looking at this I guess it might also make sense for the kernel side to enforce only being able to add
LANDLOCK_ACCESS_FS_CONNECT_UNIXon socket files (S_ISSOCK(d_backing_inode)) too inlandlock_append_fs_rule?Also, for the sandboxer logic, maybe a better way would be having
LANDLOCK_ACCESS_FS_CONNECT_UNIXinACCESS_FILE(matching the kernel code), then anotherif(!S_ISSOCK)below this that will clear outLANDLOCK_ACCESS_FS_CONNECT_UNIXif not socket.Quoted 5 lines
A process might legitimately need to connect to a socket that doesn't exist at the time it sandboxes itself. Therefore, I think it makes sense to for
LANDLOCK_ACCESS_FS_CONNECT_UNIXaccess to a directory to allowLANDLOCK_ACCESS_FS_CONNECT_UNIXto any socket under that directory. This matches the flexibility mount namespaces can achieve.Right, I forgot about the fact that we also need it on dirs, apologies.
Quoted 7 lines
Quoted 5 lines
Quoted 4 lines
(But maybe it might still make sense to not allow this on files which are neither a socket or a dir? (If the file later gets removed and recreated as a socket, the rule would not apply retroactively anyway due to being tied to the inode.))
How do we handle IOCTL access on regular files? I think that landlock will let you put IOCTL rights on regular files even they are not valid for that operation.
Regular files definitely support ioctls.
The
LANDLOCK_ACCESS_FS_IOCTL_DEVright only applies to ioctl(2) invocations on device files.Quoted 7 lines
Quoted 5 lines
Sockets seem like a similar case where the operation is only valid for a subset of file types.
I think we should mirror the existing behavior is for consistency.
Besides, restricting which file types can have that right also makes it harder for applications that may not care about the specific file type, but now would have to check the filetype before making a policy on them (also opening them to TOCTOU).
I agree.
I also agree with your interpretation, Justin.
For the record, Landlock's kernel implementation currently groups FS access rights into two groups:
- file access rights
- directory-only rightsWhen adding a rule, the directory access rights can only be granted on a directory inode. The file access rights can be granted on both a directory inode and a regular file inode.
Quoted 6 lines
It is pointless to grant the
CONNECT_UNIX(orIOCTL_DEV) right on a file which is not a Unix socket (or device file). But it complicates the userspace API if we introduce more special rules there. - Users of Landlock would have to keep track of all these special cases and mirror the logic, which is error prone. IMHO is is granular enough if we differentiate between files and directories as we currently do.
Agreed. We discussed about making it more granular (see the IOCTL patch series), but it is not worth it. Even the directory/file differentiation is questionable, but I initially made this decision to incentivise user space to know if they are dealing with directories or files because access right inheritance should be carefully managed. In most cases, when programs sandbox themselves, they should not need to stat the file because they should already know if it's a file or a directory; only sandboxers need too check the file type.
Quoted 5 lines
For reference, this is documented at
https://docs.kernel.org/userspace-api/landlock.html#filesystem-flags
and the logic is implemented inlandlock_append_fs_rule()infs.c.
Quoted 7 lines
(Actually, in the implementation, the
IOCTL_DEVright is treated the same as one of theACCESS_FILErights - I should probably revise that
documentation: That right does not *directly* apply to a directory inode, as directories are not device files. It only inherits down in the file system hierarchy. Looking back at earlier versions of theIOCTL_DEVpatch set, it was different there. I think I missed to keep the documentation in-line.)
Indeed
Re: [RFC PATCH 3/5] samples/landlock: Add support for LANDLOCK_ACCESS_FS_CONNECT_UNIX
In reply to Justin SuessHello!
Quoted 5 lines · Justin Suess
Allow users to separately specify unix socket rights, document the variable, and make the right optional.
Signed-off-by Justin Suess <[email protected]>Cc Günther Noack <[email protected]>
FYI, I ended up not applying this on V2.
I am unconvinced whether further separating the groups of access rights is a good idea for the sandboxer. This is just sample code to be used as reference, so it is good to keep it simple. I feel that giving it more granular control over access rights does not help readers to understand it much further?
It is true though that it would make sense to have this feature in more production-grade tools. 👍
–Günther
RFC PATCH 4/5 landlock/selftests: test LANDLOCK_ACCESS_FS_CONNECT_UNIX
In reply to Günther Noack* Exercise the LANDLOCK_ACCESS_FS_CONNECT_UNIX access right.
* Extract common helpers from an existing IOCTL test that also uses pathname unix(7) sockets.
--- tools/testing/selftests/landlock/fs_test.c | 88 +++++++++++++++++----- 1 file changed, 71 insertions(+), 17 deletions(-)
tools/testing/selftests/landlock/fs_test.c +71 -17
@@ -4358,30 +4358,58 @@ TEST_F_FORK(layout1, named_pipe_ioctl)ASSERT_EQ (child_pid,waitpid (child_pid,NULL ,0 )); } +/* +* set_up_named_unix_server - Create a pathname unix socket and listen +* +* Return: The listening FD - it is the caller responsibility to close it. +*/ +static int set_up_named_unix_server (struct __test_metadata *const _metadata, +const char *const path) +{ +int fd; +struct sockaddr_un addr = { + .sun_family =AF_UNIX , + }; + +ASSERT_EQ (0 ,unlink (path)); + fd =socket (AF_UNIX ,SOCK_STREAM ,0 ); +ASSERT_LE (0 , fd); + +strncpy (addr.sun_path, path,sizeof (addr.sun_path)); +ASSERT_EQ (0 ,bind (fd, (struct sockaddr *)&addr,sizeof (addr))); + +ASSERT_EQ (0 ,listen (fd,10 /* qlen */ )); +return fd; +} + +/* +* test_connect_named_unix - connect to the given named UNIX socket +* +* Return: The errno from connect(), or 0 +*/ +static int test_connect_named_unix (int fd,const char *const path) +{ +struct sockaddr_un addr = { + .sun_family =AF_UNIX , + }; +strncpy (addr.sun_path, path,sizeof (addr.sun_path)); + +if (connect (fd, (struct sockaddr *)&addr,sizeof (addr)) ==-1 ) +return errno; +return 0 ; +} +/* For named UNIX domain sockets, no IOCTL restrictions apply. */ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) {const char *const path = file1_s1d1;int srv_fd, cli_fd, ruleset_fd; -struct sockaddr_un srv_un = { - .sun_family =AF_UNIX , - }; -struct sockaddr_un cli_un = { - .sun_family =AF_UNIX , - };const struct landlock_ruleset_attr attr = { .handled_access_fs =LANDLOCK_ACCESS_FS_IOCTL_DEV , };/* Sets up a server */ -ASSERT_EQ (0 ,unlink (path)); - srv_fd =socket (AF_UNIX ,SOCK_STREAM ,0 ); -ASSERT_LE (0 , srv_fd); - -strncpy (srv_un.sun_path, path,sizeof (srv_un.sun_path)); -ASSERT_EQ (0 ,bind (srv_fd, (struct sockaddr *)&srv_un,sizeof (srv_un))); - -ASSERT_EQ (0 ,listen (srv_fd,10 /* qlen */ )); + srv_fd =set_up_named_unix_server (_metadata, path);/* Enables Landlock. */ ruleset_fd =landlock_create_ruleset (&attr,sizeof (attr),0 );
@@ -4393,9 +4421,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl) cli_fd =socket (AF_UNIX ,SOCK_STREAM ,0 );ASSERT_LE (0 , cli_fd); -strncpy (cli_un.sun_path, path,sizeof (cli_un.sun_path)); -ASSERT_EQ (0 , -connect (cli_fd, (struct sockaddr *)&cli_un,sizeof (cli_un))); +ASSERT_EQ (0 ,test_connect_named_unix (cli_fd, path));/* FIONREAD and other IOCTLs should not be forbidden. */ EXPECT_EQ (0 ,test_fionread_ioctl (cli_fd));
@@ -4570,6 +4596,34 @@ TEST_F_FORK(ioctl, handle_file_access_file)ASSERT_EQ (0 ,close (file_fd)); } +TEST_F_FORK(layout1, named_unix_domain_socket) +{ +const char *const path = file1_s1d1; +int cli_fd, srv_fd, ruleset_fd; +const struct landlock_ruleset_attr attr = { + .handled_access_fs =LANDLOCK_ACCESS_FS_CONNECT_UNIX , + }; + +/* Sets up a server */ + srv_fd =set_up_named_unix_server (_metadata, path); + +/* Enables Landlock. */ + ruleset_fd =landlock_create_ruleset (&attr,sizeof (attr),0 ); +ASSERT_LE (0 , ruleset_fd); +enforce_ruleset (_metadata, ruleset_fd); +ASSERT_EQ (0 ,close (ruleset_fd)); + +/* Sets up a client connection to it */ + cli_fd =socket (AF_UNIX ,SOCK_STREAM ,0 ); +ASSERT_LE (0 , cli_fd); + +/* Connecting to the Unix socket is denied. */ +EXPECT_EQ (EACCES ,test_connect_named_unix (cli_fd, path)); + +ASSERT_EQ (0 ,close (cli_fd)); +ASSERT_EQ (0 ,close (srv_fd)); +} +/* clang-format off */ FIXTURE (layout1_bind) {};/* clang-format on */
Signature · 1 line
2.52.0
RFC PATCH 5/5 landlock: Document LANDLOCK_ACCESS_FS_UNIX_CONNECT
In reply to Günther Noack--- Documentation/userspace-api/landlock.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
Documentation/userspace-api/landlock.rst +13 -1
@@ -77,7 +77,8 @@ to be explicit about the denied-by-default access rights. LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_TRUNCATE | - LANDLOCK_ACCESS_FS_IOCTL_DEV, + LANDLOCK_ACCESS_FS_IOCTL_DEV | + LANDLOCK_ACCESS_FS_UNIX_CONNECT, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP,
@@ -127,6 +128,10 @@ version, and only use the available subset of access rights: /* Removes LANDLOCK_SCOPE_* for ABI < 6 */ ruleset_attr.scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | LANDLOCK_SCOPE_SIGNAL); + __attribute__((fallthrough)); + case 7: + /* Removes LANDLOCK_ACCESS_FS_UNIX_CONNECT for ABI < 8 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_UNIX_CONNECT; } This enables the creation of an inclusive ruleset that will contain our rules.
@@ -604,6 +609,13 @@ Landlock audit events with the ``LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF``, sys_landlock_restrict_self(). See Documentation/admin-guide/LSM/landlock.rst for more details on audit. +Pathname UNIX sockets (ABI < 8) +------------------------------- + +Starting with the Landlock ABI version 8, it is possible to restrict +connections to a pathname :manpage:`unix(7)` socket using the new +``LANDLOCK_ACCESS_FS_UNIX_CONNECT`` right. + .. _kernel_support: Kernel support
Signature · 1 line
2.52.0
Quoted 4 lines · Günther Noack
Happy New Year!
This patch set introduces a file-system-based Landlock restriction mechanism for connecting to Unix sockets.
(snip)
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.
I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Quoted 6 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.
Quoted 7 lines
I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9
Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
Regarding the un-restrictable operations, Tingmao's pointers are correct. In the warning box in the documentation, the missing operations that I am aware of are (a) the Unix socket connect() operation, and (b) the symlink lookup which happens implicitly during path traversal and which Landlock and other LSMs can not control through LSM hooks at the moment. (A symlink always gets implicitly resolved during path lookup even when you do not have directory read permissions on the directory where the symlink is.)
–Günther
Quoted 8 lines · Günther Noack
Regarding the un-restrictable operations, Tingmao's pointers are correct. In the warning box in the documentation, the missing operations that I am aware of are (a) the Unix socket
connect()operation, and (b) the symlink lookup which happens implicitly during path traversal and which Landlock and other LSMs can not control through LSM hooks at the moment. (A symlink always gets implicitly resolved during path lookup even when you do not have directory read permissions on the directory where the symlink is.)
I forgot to mention - the error codes returned by Landlock make it possible to probe for the presence of files, even when all available FS access rights are denied on a directory. Attempting to open a file for reading will return EEXIST if it is missing, but will return EACCES if it is denied by Landlock.
gnoack:/tmp/xxx$ ls foobar.txt gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat foobar.txt cat: foobar.txt: Permission denied gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat nonexistent.txt cat: nonexistent.txt: No such file or directory gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/ls ls: cannot open directory '.': Permission denied
–Günther
Mickaël Salaün
maintainerQuoted 10 lines · Günther Noack
Quoted 8 lines · Günther Noack
Regarding the un-restrictable operations, Tingmao's pointers are correct. In the warning box in the documentation, the missing operations that I am aware of are (a) the Unix socket
connect()operation, and (b) the symlink lookup which happens implicitly during path traversal and which Landlock and other LSMs can not control through LSM hooks at the moment. (A symlink always gets implicitly resolved during path lookup even when you do not have directory read permissions on the directory where the symlink is.)
Quoted 2 lines
I forgot to mention - the error codes returned by Landlock make it possible to probe for the presence of files, even when all available
It is not specifically the error codes but the inability to restrict path resolution.
Quoted 4 lines
FS access rights are denied on a directory. Attempting to open a file for reading will return EEXIST if it is missing, but will return EACCES if it is denied by Landlock.
Quoted 8 lines
gnoack:/tmp/xxx$ ls foobar.txt gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat foobar.txt cat: foobar.txt: Permission denied gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/cat nonexistent.txt cat: nonexistent.txt: No such file or directory gnoack:/tmp/xxx$ landlock-restrict -rofiles /proc /usr /bin /etc/ -- /bin/ls ls: cannot open directory '.': Permission denied
FYI, there are several ways to infer file presence, and this also work with other LSMs such as AppArmor and Tomoyo. It is a limitation of path-based hooks, see https://github.com/landlock-lsm/linux/issues/52
As Tingmao noted, this is part of Landlock's documentation, but it could be improved.
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Quoted 32 lines · Demi Marie Obenour
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
Quoted 2 lines
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the security_inode_follow_link() hook, which is already happening during path resolution?
I take it back then. :) If there is prior art, implementing this might be more feasible than I thought.
–Günther
Quoted 33 lines · Günther Noack
Quoted 32 lines · Demi Marie Obenour
Quoted 30 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
Quoted 7 lines
Quoted 2 lines
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?
I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
Quoted 2 lines
I take it back then. :) If there is prior art, implementing this might be more feasible than I thought.
I think so too!
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Mickaël Salaün
maintainerQuoted 37 lines · Demi Marie Obenour
Quoted 36 lines · Günther Noack
Quoted 34 lines · Demi Marie Obenour
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Quoted 7 lines
Quoted 4 lines
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
SELinux uses inode-based hooks, which is not (directly) possible for Landlock because it is an unprivileged access control, which means it cannot rely on extended file attributes to define a security policy.
See https://github.com/landlock-lsm/linux/issues/9
Quoted 8 lines
Quoted 3 lines
I take it back then. :) If there is prior art, implementing this might be more feasible than I thought.
I think so too!
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Quoted 43 lines · Mickaël Salaün
Quoted 42 lines · Demi Marie Obenour
Quoted 40 lines · Günther Noack
Quoted 32 lines · Demi Marie Obenour
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
Quoted 2 lines
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?
Quoted 8 lines
Quoted 2 lines
I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
SELinux uses inode-based hooks, which is not (directly) possible for Landlock because it is an unprivileged access control, which means it cannot rely on extended file attributes to define a security policy.
Could Landlock use a side table, with the inode's address in memory as the key?
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Mickaël Salaün
maintainerQuoted 47 lines · Demi Marie Obenour
Quoted 46 lines · Mickaël Salaün
Quoted 44 lines · Demi Marie Obenour
Quoted 33 lines · Günther Noack
Quoted 32 lines · Demi Marie Obenour
Quoted 30 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
Quoted 7 lines
Quoted 2 lines
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
Quoted 8 lines
Quoted 5 lines
SELinux uses inode-based hooks, which is not (directly) possible for Landlock because it is an unprivileged access control, which means it cannot rely on extended file attributes to define a security policy.
Could Landlock use a side table, with the inode's address in memory as the key?
A struct inode is not enough because we need to resolve a file hierarchy, which is only possible with a struct path.
Quoted 52 lines · Mickaël Salaün
Quoted 51 lines · Demi Marie Obenour
Quoted 50 lines · Mickaël Salaün
Quoted 37 lines · Demi Marie Obenour
Quoted 36 lines · Günther Noack
Quoted 34 lines · Demi Marie Obenour
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Quoted 7 lines
Quoted 4 lines
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
SELinux uses inode-based hooks, which is not (directly) possible for Landlock because it is an unprivileged access control, which means it cannot rely on extended file attributes to define a security policy.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
Could Landlock use a side table, with the inode's address in memory as the key?
A struct inode is not enough because we need to resolve a file hierarchy, which is only possible with a struct path.
Could Landlock "piggyback" on the core kernel's own path resolution, updating its state when each hook gets called?
Signature · 2 lines
Sincerely, Demi Marie Obenour (she/her/hers)
Mickaël Salaün
maintainerQuoted 55 lines · Demi Marie Obenour
Quoted 54 lines · Mickaël Salaün
Quoted 53 lines · Demi Marie Obenour
Quoted 51 lines · Mickaël Salaün
Quoted 37 lines · Demi Marie Obenour
Quoted 36 lines · Günther Noack
Quoted 34 lines · Demi Marie Obenour
Quoted 24 lines · Günther Noack
Quoted 10 lines · Demi Marie Obenour
Quoted 9 lines · Tingmao Wang
Quoted 4 lines · Demi Marie Obenour
[...]
Does this leave directory traversal as the only missing Landlock filesystem access control? Ideally Landlock could provide the same isolation from the filesystem that mount namespaces do.I think that level of isolation would require path walk control - see:
https://github.com/landlock-lsm/linux/issues/9Quoted 6 lines
Quoted 4 lines
(Landlock also doesn't currently control some metadata operations - see the warning at the end of the "Filesystem flags" section in [1])
[1]: https://docs.kernel.org/6.18/userspace-api/landlock.html#filesystem-flags
Could this replace all of the existing hooks?
If you do not need to distinguish between the different operations which Landlock offers access rights for, but you only want to limit the visibility of directory hierarchies in the file system, then yes, the path walk control described in issue 9 would be sufficient and a more complete control.
Quoted 6 lines
The path walk control is probably among the more difficult Landlock feature requests. A simple implementation would be easy to implement technically, but it also requires a new LSM hook which will have to get called *during* path lookup, and we'd have to make sure that the performance impact stays in check. Path lookup is after all a very central facility in a OS kernel.
What about instead using the inode-based hooks for directory searching? SELinux can already restrict that.
Quoted 7 lines
Quoted 4 lines
Oh, thanks, good pointer! I was under the impression that this didn't exist yet -- I assume you are referring to the
security_inode_follow_link()hook, which is already happening during path resolution?I'm not familiar with existing LSM hooks, but I do know that SELinux enforces checks on searching and reading directories and symlinks.
SELinux uses inode-based hooks, which is not (directly) possible for Landlock because it is an unprivileged access control, which means it cannot rely on extended file attributes to define a security policy.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Could Landlock use a side table, with the inode's address in memory as the key?
A struct inode is not enough because we need to resolve a file hierarchy, which is only possible with a struct path.
Could Landlock "piggyback" on the core kernel's own path resolution, updating its state when each hook gets called?
Most of the inode-based hooks are called in places where there is no path data (in the current context). We should be very careful with changes to the VFS wrt performance and complexity. If you have an idea of how to do it, I encourage you to test it and send an RFC.
Mickaël Salaün
maintainerQuoted 1 line · Günther Noack
Happy New Year!
Happy New Year!
Quoted 3 lines
This patch set introduces a file-system-based Landlock restriction mechanism for connecting to Unix sockets.
Thanks for this patch series, this is an important feature for sandboxing.
Quoted 10 lines
## Motivation
Currently, landlocked processes can
connect()to named UNIX sockets through the BSD socket API described in unix(7), by invoking socket(2) followed by connect(2) with a suitable structsockname_unholding the socket's filename. This can come as a surprise for users (e.g. in [1]) and it can be used to escape a sandbox when a Unix service offers command execution (some scenarios were listed by Tingmao Wang in [2]).
Quoted 3 lines
These patches are built on Justin Suess's patch which adds the LSM hook:
https://lore.kernel.org/all/[email protected]/
As Kuniyuki pointed out [1], we should handle both connect and send. This would be similar to the scoped restriction from Tingmao. I guess we'll need a similar hook for the send operation. Because there is no need to differenciate between connected and disconnected unix socket in a security policy, we should have one access right for both. Any proposal for its name? Something like TRANSMIT_UNIX or EMIT_UNIX?
[1] https://lore.kernel.org/all/CAAVpQUAd==+Pw02+E6UC-qwaDNm7aFg+Q9YDbWzyniShAkAhFQ@mail.gmail.com/
Quoted 14 lines · Mickaël Salaün
Quoted 9 lines · Günther Noack
## Motivation
Currently, landlocked processes can
connect()to named UNIX sockets through the BSD socket API described in unix(7), by invoking socket(2) followed by connect(2) with a suitable structsockname_unholding the socket's filename. This can come as a surprise for users (e.g. in [1]) and it can be used to escape a sandbox when a Unix service offers command execution (some scenarios were listed by Tingmao Wang in [2]).Quoted 3 lines
These patches are built on Justin Suess's patch which adds the LSM hook:
https://lore.kernel.org/all/[email protected]/
Quoted 8 lines
As Kuniyuki pointed out [1], we should handle both connect and send. This would be similar to the scoped restriction from Tingmao. I guess we'll need a similar hook for the send operation. Because there is no need to differenciate between connected and disconnected unix socket in a security policy, we should have one access right for both. Any proposal for its name? Something like
TRANSMIT_UNIXorEMIT_UNIX?[1] https://lore.kernel.org/all/CAAVpQUAd==+Pw02+E6UC-qwaDNm7aFg+Q9YDbWzyniShAkAhFQ@mail.gmail.com/
Ah, thanks for pointing it out.
The restriction as implemented in this patch set already solves this for all the three cases where a Unix socket file is looked up. I believe that it is happening in all the right times (everytime when the lookup has to happen).
The cases where the restriction applies are the following:
* unix_stream_connect - when calling connect() on a stream socket
* unix_dgram_connect - when calling connect() on a dgram socket
* unix_dgram_sendmsg - when calling sendmsg() on a dgram socket (per-message lookup only)
You can find the code locations by looking for the call to unix_find_other() in af_unix.c. (That function invokes either unix_find_bsd() or the lookup for abstract Unix sockets.)
In the unix_dgram_sendmsg() case, the lookup is only performed if an explicit sockaddr_un was provided together with the arguments to the sendmsg(). (And sendto(2) also uses the same code path as sendmsg(2).)
It is true that the current name for the access right is slightly misleading. How about LANDLOCK_ACCESS_FS_UNIX_SEND? (Like "transmit", but a bit closer to the naming of the sendmsg(2) networking API?)
(I guess the other alternative would be to wire the socket type information through to the unix_find_bsd() function and pass it through. Would require a small change to the af_unix.c implementation, but then we could tell apart LANDLOCK_ACCESS_FS_UNIX_STREAM_CONNECT and LANDLOCK_ACCESS_FS_UNIX_DGRAM_SEND). WDYT?
–Günther
Mickaël Salaün
maintainerQuoted 38 lines · Günther Noack
Quoted 14 lines · Mickaël Salaün
Quoted 9 lines · Günther Noack
## Motivation
Currently, landlocked processes can
connect()to named UNIX sockets through the BSD socket API described in unix(7), by invoking socket(2) followed by connect(2) with a suitable structsockname_unholding the socket's filename. This can come as a surprise for users (e.g. in [1]) and it can be used to escape a sandbox when a Unix service offers command execution (some scenarios were listed by Tingmao Wang in [2]).Quoted 3 lines
These patches are built on Justin Suess's patch which adds the LSM hook:
https://lore.kernel.org/all/[email protected]/Quoted 8 lines
As Kuniyuki pointed out [1], we should handle both connect and send. This would be similar to the scoped restriction from Tingmao. I guess we'll need a similar hook for the send operation. Because there is no need to differenciate between connected and disconnected unix socket in a security policy, we should have one access right for both. Any proposal for its name? Something like
TRANSMIT_UNIXorEMIT_UNIX?[1] https://lore.kernel.org/all/CAAVpQUAd==+Pw02+E6UC-qwaDNm7aFg+Q9YDbWzyniShAkAhFQ@mail.gmail.com/
Ah, thanks for pointing it out.
The restriction as implemented in this patch set already solves this for all the three cases where a Unix socket file is looked up. I believe that it is happening in all the right times (everytime when the lookup has to happen).
The cases where the restriction applies are the following:
*
unix_stream_connect- when callingconnect()on a stream socket
*unix_dgram_connect- when callingconnect()on a dgram socket
*unix_dgram_sendmsg- when callingsendmsg()on a dgram socket (per-message lookup only)
Quoted 8 lines
You can find the code locations by looking for the call to
unix_find_other()inaf_unix.c. (That function invokes eitherunix_find_bsd()or the lookup for abstract Unix sockets.)In the
unix_dgram_sendmsg()case, the lookup is only performed if an explicitsockaddr_unwas provided together with the arguments to thesendmsg(). (And sendto(2) also uses the same code path as sendmsg(2).)
Great
Quoted 5 lines
It is true that the current name for the access right is slightly misleading. How about
LANDLOCK_ACCESS_FS_UNIX_SEND? (Like "transmit", but a bit closer to the naming of the sendmsg(2) networking API?)
We should try to keep the access right naming consistent:
LANDLOCK_ACCESS_FS_<VERB>[_NOUN]
What about USE_UNIX, or FIND_UNIX (closer to the kernel function), or RESOLVE_UNIX? It should be clear with the name that it is not about listening nor receiving from a process outside of the sandbox (which should have its own access right BTW).
Quoted 6 lines
(I guess the other alternative would be to wire the socket type information through to the
unix_find_bsd()function and pass it through. Would require a small change to theaf_unix.cimplementation, but then we could tell apartLANDLOCK_ACCESS_FS_UNIX_STREAM_CONNECTandLANDLOCK_ACCESS_FS_UNIX_DGRAM_SEND). WDYT?
I think the hook should have the same arguments as unix_find_bsd()'s ones. This gives the full context of the call.
Quoted 29 lines · Mickaël Salaün
Quoted 28 lines · Günther Noack
Quoted 8 lines · Mickaël Salaün
As Kuniyuki pointed out [1], we should handle both connect and send. This would be similar to the scoped restriction from Tingmao. I guess we'll need a similar hook for the send operation. Because there is no need to differenciate between connected and disconnected unix socket in a security policy, we should have one access right for both. Any proposal for its name? Something like
TRANSMIT_UNIXorEMIT_UNIX?[1] https://lore.kernel.org/all/CAAVpQUAd==+Pw02+E6UC-qwaDNm7aFg+Q9YDbWzyniShAkAhFQ@mail.gmail.com/
Ah, thanks for pointing it out.
The restriction as implemented in this patch set already solves this for all the three cases where a Unix socket file is looked up. I believe that it is happening in all the right times (everytime when the lookup has to happen).
The cases where the restriction applies are the following:
*
unix_stream_connect- when callingconnect()on a stream socket
*unix_dgram_connect- when callingconnect()on a dgram socket
*unix_dgram_sendmsg- when callingsendmsg()on a dgram socket (per-message lookup only)You can find the code locations by looking for the call to
unix_find_other()inaf_unix.c. (That function invokes eitherunix_find_bsd()or the lookup for abstract Unix sockets.)
Quoted 6 lines
Quoted 4 lines
In the
unix_dgram_sendmsg()case, the lookup is only performed if an explicitsockaddr_unwas provided together with the arguments to thesendmsg(). (And sendto(2) also uses the same code path as sendmsg(2).)Great
FYI, V2 splits the access rights for the three UNIX access types SOCK_STREAM, SOCK_DGRAM and SOCK_SEQPACKET.
FYI, I double checked that the logic extends cleanly to the SOCK_SEQPACKET case as well: SOCK_SEQPACKET is implemented as a thin layer above the existing hooks for SOCK_STREAM and SOCK_DGRAM - it does connect(2) with the SOCK_STREAM implementation, and it does sendmsg(2) with the SOCK_DGRAM implementation, but in the sendmsg(2) case it removes any explicitly passed recipient addresses beforehand. (See "unix_seqpacket_ops" in net/unix/af_unix.c) So as far as the UNIX path lookup hook is concerned, SOCK_SEQPACKET behaves like SOCK_STREAM, and only invokes the hook during connect(2).
Quoted 5 lines
Quoted 4 lines
It is true that the current name for the access right is slightly misleading. How about
LANDLOCK_ACCESS_FS_UNIX_SEND? (Like "transmit", but a bit closer to the naming of the sendmsg(2) networking API?)
Quoted 7 lines
We should try to keep the access right naming consistent:
LANDLOCK_ACCESS_FS_<VERB>[_NOUN]What about
USE_UNIX, orFIND_UNIX(closer to the kernel function), orRESOLVE_UNIX? It should be clear with the name that it is not about listening nor receiving from a process outside of the sandbox (which should have its own access right BTW).
Thanks, changed in V2 to say RESOLVE_UNIX, and also split up the access rights for the three UNIX socket types.
(For reference, the path_resolution(7) man page [1] also uses the verb "resolve". I think both "resolve" and "lookup" are used exchangeably for paths.)
[1] https://man7.org/linux/man-pages/man7/path_resolution.7.html
Quoted 8 lines
Quoted 5 lines
(I guess the other alternative would be to wire the socket type information through to the
unix_find_bsd()function and pass it through. Would require a small change to theaf_unix.cimplementation, but then we could tell apartLANDLOCK_ACCESS_FS_UNIX_STREAM_CONNECTandLANDLOCK_ACCESS_FS_UNIX_DGRAM_SEND). WDYT?I think the hook should have the same arguments as unix_find_bsd()'s ones. This gives the full context of the call.
You are right, I had not recalled that the socket type information already gets passed to unix_find_bsd() - it required not much additional wiring at all, in the end. 👍
–Günther