Skip to content

Landlock: Implement scope control for pathname Unix sockets

Tingmao Wang linux-security-module 3 versions – In review

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v3 Latest6 patches 1 replyIn review
  2. v26 patches 34 repliesSuperseded
  3. v16 patches 5 repliesSuperseded

Changes in v2 from the cover letter

Fix grammar in doc, rebased on mic/next, and extracted common code from hook_unix_stream_connect and hook_unix_may_send into a separate function.

Patches in v3 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/6landlock: Add LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET scope bit to uAPIDocumentation/userspace-api/landlock.rst include/uapi/linux/landlock.h security/landlock/limits.h +3 more+41 -120 replies
2/6landlock: Implement LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKETsecurity/landlock/audit.c security/landlock/audit.h security/landlock/task.c+71 -471 reply
3/6samples/landlock: Support LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKETsamples/landlock/sandboxer.c+18 -50 replies
4/6selftests/landlock: Support pathname socket path in set_unix_addresstools/testing/selftests/landlock/common.h tools/testing/selftests/landlock/net_test.c tools/testing/selftests/landlock/scoped_abstract_unix_test.c +1 more+44 -230 replies
5/6selftests/landlock: Repurpose scoped_abstract_unix_test.c for pathname sockets tootools/testing/selftests/landlock/scoped_unix_test.c+217 -520 replies
6/6selftests/landlock: Add pathname socket variants for more teststools/testing/selftests/landlock/scoped_unix_test.c+411 -2060 replies

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v3 yet.

Read the v3 thread

Cover letter [PATCH v3 0/6] Landlock: Implement scope control for pathname Unix sockets

This version contains some minor update based on feedback from Mickaël.

(Sending this anyway for completeness despite discussion in
https://lore.kernel.org/all/[email protected]/ )

The rest is the same as the v2 cover letter:

Changes in v2:
Fix grammar in doc, rebased on mic/next, and extracted common code from hook_unix_stream_connect and hook_unix_may_send into a separate function.

The rest is the same as the v1 cover letter:

This patch series extend the existing abstract Unix socket scoping to pathname (i.e. normal file-based) sockets as well, by adding a new scope bit LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET that works the same as LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, except that restricts pathname Unix sockets. This means that a sandboxed process with this scope enabled will not be able to connect to Unix sockets created outside the sandbox via the filesystem.

There is a future plan [1] for allowing specific sockets based on FS hierarchy, but this series is only determining access based on domain parent-child relationship. There is currently no way to allow specific (outside the Landlock domain) Unix sockets, and none of the existing Landlock filesystem controls apply to socket connect().

With this series, we can now properly protect against things like the the following while only relying on Landlock:

    (running under tmux)
    root@6-19-0-rc1-dev-00023-g68f0b276cbeb ~# LL_FS_RO=/ LL_FS_RW= ./sandboxer bash
    Executing the sandboxed command...
    root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# cat /tmp/hi
    cat: /tmp/hi: No such file or directory
    root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# tmux new-window 'echo hi > /tmp/hi'
    root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# cat /tmp/hi
    hi

The above but with Unix socket scoping enabled (both pathname and abstract sockets) - the sandboxed shell can now no longer talk to tmux due to the socket being created from outside the Landlock sandbox:

(running under tmux)
root@6-19-0-rc1-dev-00023-g68f0b276cbeb ~# LL_FS_RO=/ LL_FS_RW= LL_SCOPED=u:a ./sandboxer bash Executing the sandboxed command...
root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# cat /tmp/hi
cat: /tmp/hi: No such file or directory root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# tmux new-window 'echo hi > /tmp/hi' error connecting to /tmp/tmux-0/default (Operation not permitted) root@6-19-0-rc1-dev-00023-g68f0b276cbeb:/# cat /tmp/hi
cat: /tmp/hi: No such file or directory

Tmux is just one example. In a standard systemd session, systemd-run --user can also be used (--user will run the command in the user's session, without requiring any root privileges), and likely a lot more if running in a desktop environment with many popular applications. This change therefore makes it possible to create sandboxes without relying on additional mechanisms like seccomp to protect against such issues.

These kind of issues was originally discussed on here (I took the idea for systemd-run from Demi):
https://spectrum-os.org/lists/archives/spectrum-devel/[email protected]/

Demo with socat + sandboxer:

Outside:
socat unix-listen:/foo.sock,fork -

Sandbox with pathname socket scope bit:

    root@6-19-0-rc1-dev-00023-g0994a10d6512 ~# LL_FS_RW=/ LL_FS_RO= LL_SCOPED=u /sandboxer socat -d2 unix:/foo.sock -
    Executing the sandboxed command...
    2025/12/27 20:28:54 socat[1227] E UNIX-CLIENT: /foo.sock: Operation not permitted
    2025/12/27 20:28:54 socat[1227] N exit(1)

Sandbox without pathname socket scope bit:

    root@6-19-0-rc1-dev-00023-g0994a10d6512 ~# LL_FS_RW=/ LL_FS_RO= LL_SCOPED= /sandboxer socat -d2 unix:/foo.sock -
    Executing the sandboxed command...
    2025/12/27 20:29:22 socat[1250] N successfully connected from local address AF=1 "(7\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xB0\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xAE\xC3\xAE\xAE\xAE\xAE"
    ...

Sandbox with only abstract socket scope bit:

    root@6-19-0-rc1-dev-00023-g0994a10d6512 ~# LL_FS_RW=/ LL_FS_RO= LL_SCOPED=a /sandboxer socat -d2 unix:/foo.sock -
    Executing the sandboxed command...
    2025/12/27 20:29:26 socat[1259] N successfully connected from local address AF=1 "\0\0\0\0\0\0\0\0\0"
    ...

Sendmsg/recvmsg - outside:
socat unix-recvfrom:/datagram.sock -

Sandbox with pathname socket scope bit:

    root@6-19-0-rc1-dev-00023-g0994a10d6512 ~# LL_FS_RW=/ LL_FS_RO= LL_SCOPED=u /sandboxer socat -d2 unix-sendto:/datagram.sock -
    Executing the sandboxed command...
    ...
    2025/12/27 20:33:04 socat[1446] N starting data transfer loop with FDs [5,5] and [0,1]
    123
    2025/12/27 20:33:05 socat[1446] E sendto(5, 0x55d260d8f000, 4, 0, AF=1 "/datagram.sock", 16): Operation not permitted
    2025/12/27 20:33:05 socat[1446] N exit(1)

[1]: https://github.com/landlock-lsm/linux/issues/36

Tingmao Wang (6):
landlock: Add LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET scope bit to uAPI
landlock: Implement LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET samples/landlock: Support LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET selftests/landlock: Support pathname socket path in set_unix_address selftests/landlock: Repurpose scoped_abstract_unix_test.c for pathname
sockets too
selftests/landlock: Add pathname socket variants for more tests

 Documentation/userspace-api/landlock.rst      |  37 +-
 include/uapi/linux/landlock.h                 |   8 +-
 samples/landlock/sandboxer.c                  |  23 +-
 security/landlock/audit.c                     |   4 +
 security/landlock/audit.h                     |   1 +
 security/landlock/limits.h                    |   2 +-
 security/landlock/syscalls.c                  |   2 +-
 security/landlock/task.c                      | 113 ++-
 tools/testing/selftests/landlock/base_test.c  |   2 +-
 tools/testing/selftests/landlock/common.h     |  33 +-
 tools/testing/selftests/landlock/net_test.c   |   2 +-
 .../selftests/landlock/scoped_signal_test.c   |   2 +-
 .../testing/selftests/landlock/scoped_test.c  |   2 +-
 ...bstract_unix_test.c => scoped_unix_test.c} | 886 +++++++++++++-----
 14 files changed, 787 insertions(+), 330 deletions(-)
 rename tools/testing/selftests/landlock/{scoped_abstract_unix_test.c => scoped_unix_test.c} (50%)

base-commit: 24d479d26b25bce5faea3ddd9fa8f3a6c3129ea7
prerequisite-patch-id: 5f3ab4d7ae2173abb98b510534b2eabc575944ed # https://lore.kernel.org/all/[email protected]/
prerequisite-patch-id: 0002366468db0afd2e68f4ee4f6cfb0d8e7ed315

Signature · 1 line
2.52.0