mbox series

[v5,00/24] Landlock audit support

Message ID 20250131163059.1139617-1-mic@digikod.net (mailing list archive)
Headers show
Series Landlock audit support | expand

Message

Mickaël Salaün Jan. 31, 2025, 4:30 p.m. UTC
Hi,

This patch series adds audit support to Landlock.

Logging denied requests is useful for different use cases:
- sysadmins: to look for users' issues,
- security experts: to detect attack attempts,
- power users: to understand denials,
- developers: to ease sandboxing support and get feedback from users.

Because of its unprivileged nature, Landlock can compose standalone
security policies (i.e. domains).  To make logs useful, they need to
contain the most relevant Landlock domain that denied an action, and the
reason of such denial.  This translates to the latest nested domain and
the related blockers: missing access rights or other kind of
restrictions.

# Changes from previous version

Remove the AUDIT_EXE_LANDLOCK_DENY audit rule and add 2 new
landlock_restrict_self(2) flags to filter Landlock audit events, which
makes 3 flags:
- LANDLOCK_RESTRICT_SELF_QUIET: do not log any denied access because of
  this new domain.
- LANDLOCK_RESTRICT_SELF_QUIET_DESCENDENTS: do not log denied access
  from child domains.
- LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC: log denied access for processes
  resulting from an execve(2), which is not the case by default anymore.

One patch was merged in mainline: 7ccbe076d987 ("lsm: Only build
lsm_audit.c if CONFIG_SECURITY and CONFIG_AUDIT are set").

# Design

Log records are created for any denied actions caused by a Landlock
policy, which means that a well-sandboxed applications should not log
anything except for unattended access requests that might be the result
of attacks or bugs.

However, sandbox tools creating restricted environments could lead to
abundant log entries because the sandboxed processes may not be aware of
the related restrictions.  To avoid log spam, the
landlock_restrict_self(2) syscall gets a new
LANDLOCK_RESTRICT_SELF_QUIET flag to not log denials related to this
specific domain.  Except for well-understood exceptions, this flag
should not be set.  Indeed, applications sandboxing themselves should
only try to bypass their own sandbox if they are compromised, which
should ring a bell thanks to log events.

When an action is denied, the related Landlock domain ID is specified.
If this domain was not previously described in a log record, one is
created.  This record contains the domain ID, its creation time, and
informations about the process that enforced the restriction (at the
time of the call to landlock_restrict_self): PID, UID, executable path,
and name (comm).

This new approach also brings building blocks for an upcoming
unprivileged introspection interface.  The unique Landlock IDs will be
useful to tie audit log entries to running processes, and to get
properties of the related Landlock domains.  This will replace the
previously logged ruleset properties.

# Samples

Here are two examples of log events (see serial numbers):

$ LL_FS_RO=/ LL_FS_RW=/ LL_SCOPED=s LL_FORCE_LOG=1 ./sandboxer kill 1

  type=LANDLOCK_ACCESS msg=audit(1729738800.268:30): domain=1a6fdc66f blockers=scope.signal opid=1 ocomm="systemd"
  type=LANDLOCK_DOMAIN msg=audit(1729738800.268:30): domain=1a6fdc66f status=allocated mode=enforcing pid=286 uid=0 exe="/root/sandboxer" comm="sandboxer"
  type=SYSCALL msg=audit(1729738800.268:30): arch=c000003e syscall=62 success=no exit=-1 [..] ppid=272 pid=286 auid=0 uid=0 gid=0 [...] comm="kill" [...]
  type=PROCTITLE msg=audit(1729738800.268:30): proctitle=6B696C6C0031
  type=LANDLOCK_DOMAIN msg=audit(1729738800.324:31): domain=1a6fdc66f status=deallocated denials=1

$ LL_FS_RO=/ LL_FS_RW=/tmp LL_FORCE_LOG=1 ./sandboxer sh -c "echo > /etc/passwd"

  type=LANDLOCK_ACCESS msg=audit(1729738800.221:33): domain=1a6fdc679 blockers=fs.write_file path="/dev/tty" dev="devtmpfs" ino=9
  type=LANDLOCK_DOMAIN msg=audit(1729738800.221:33): domain=1a6fdc679 status=allocated mode=enforcing pid=289 uid=0 exe="/root/sandboxer" comm="sandboxer"
  type=SYSCALL msg=audit(1729738800.221:33): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
  type=PROCTITLE msg=audit(1729738800.221:33): proctitle=7368002D63006563686F203E202F6574632F706173737764
  type=LANDLOCK_ACCESS msg=audit(1729738800.221:34): domain=1a6fdc679 blockers=fs.write_file path="/etc/passwd" dev="vda2" ino=143821
  type=SYSCALL msg=audit(1729738800.221:34): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
  type=PROCTITLE msg=audit(1729738800.221:34): proctitle=7368002D63006563686F203E202F6574632F706173737764
  type=LANDLOCK_DOMAIN msg=audit(1729738800.261:35): domain=1a6fdc679 status=deallocated denials=2

# Future changes

I'll add more tests to check each kind of denied access.

# Previous versions

v4: https://lore.kernel.org/r/20250108154338.1129069-1-mic@digikod.net
v3: https://lore.kernel.org/r/20241122143353.59367-1-mic@digikod.net
v2: https://lore.kernel.org/r/20241022161009.982584-1-mic@digikod.net
v1: https://lore.kernel.org/r/20230921061641.273654-1-mic@digikod.net

Regards,

Mickaël Salaün (24):
  lsm: Add audit_log_lsm_data() helper
  landlock: Add unique ID generator
  landlock: Move domain hierarchy management
  landlock: Prepare to use credential instead of domain for filesystem
  landlock: Prepare to use credential instead of domain for network
  landlock: Prepare to use credential instead of domain for scope
  landlock: Prepare to use credential instead of domain for fowner
  landlock: Identify domain execution crossing
  landlock: Add AUDIT_LANDLOCK_ACCESS and log ptrace denials
  landlock: Add AUDIT_LANDLOCK_DOMAIN and log domain status
  landlock: Log mount-related denials
  landlock: Log file-related denials
  landlock: Log truncate and IOCTL denials
  landlock: Log TCP bind and connect denials
  landlock: Log scoped denials
  landlock: Add LANDLOCK_RESTRICT_SELF_QUIET
  landlock: Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
  landlock: Add LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC
  samples/landlock: Enable users to log sandbox denials
  selftests/landlock: Extend tests for landlock_restrict_self()'s flags
  selftests/landlock: Add tests for audit and
    LANDLOCK_RESTRICT_SELF_QUIET
  selftests/landlock: Test audit with restrict flags
  selftests/landlock: Add audit tests for ptrace
  landlock: Add audit documentation

 Documentation/admin-guide/LSM/index.rst       |   1 +
 Documentation/admin-guide/LSM/landlock.rst    | 157 ++++++
 Documentation/security/landlock.rst           |   7 +
 Documentation/userspace-api/landlock.rst      |   9 +-
 MAINTAINERS                                   |   1 +
 include/linux/lsm_audit.h                     |   8 +
 include/uapi/linux/audit.h                    |   4 +-
 include/uapi/linux/landlock.h                 |  31 ++
 samples/landlock/sandboxer.c                  |  37 +-
 security/landlock/.kunitconfig                |   2 +
 security/landlock/Makefile                    |   5 +
 security/landlock/access.h                    |  23 +
 security/landlock/audit.c                     | 513 ++++++++++++++++++
 security/landlock/audit.h                     |  77 +++
 security/landlock/cred.c                      |  26 +-
 security/landlock/cred.h                      |  65 +++
 security/landlock/domain.c                    | 264 +++++++++
 security/landlock/domain.h                    | 158 ++++++
 security/landlock/fs.c                        | 279 ++++++++--
 security/landlock/fs.h                        |  21 +-
 security/landlock/id.c                        | 249 +++++++++
 security/landlock/id.h                        |  25 +
 security/landlock/limits.h                    |   4 +
 security/landlock/net.c                       |  74 ++-
 security/landlock/ruleset.c                   |  33 +-
 security/landlock/ruleset.h                   |  47 +-
 security/landlock/setup.c                     |   2 +
 security/landlock/syscalls.c                  |  50 +-
 security/landlock/task.c                      | 232 ++++++--
 security/lsm_audit.c                          |  27 +-
 tools/testing/kunit/configs/all_tests.config  |   2 +
 tools/testing/selftests/landlock/Makefile     |   6 +-
 tools/testing/selftests/landlock/audit.h      | 358 ++++++++++++
 tools/testing/selftests/landlock/audit_test.c | 425 +++++++++++++++
 tools/testing/selftests/landlock/base_test.c  |  43 +-
 tools/testing/selftests/landlock/common.h     |   3 +
 tools/testing/selftests/landlock/config       |   1 +
 .../testing/selftests/landlock/ptrace_test.c  |  67 ++-
 .../selftests/landlock/wait-pipe-sandbox.c    | 131 +++++
 39 files changed, 3244 insertions(+), 223 deletions(-)
 create mode 100644 Documentation/admin-guide/LSM/landlock.rst
 create mode 100644 security/landlock/audit.c
 create mode 100644 security/landlock/audit.h
 create mode 100644 security/landlock/domain.c
 create mode 100644 security/landlock/domain.h
 create mode 100644 security/landlock/id.c
 create mode 100644 security/landlock/id.h
 create mode 100644 tools/testing/selftests/landlock/audit.h
 create mode 100644 tools/testing/selftests/landlock/audit_test.c
 create mode 100644 tools/testing/selftests/landlock/wait-pipe-sandbox.c


base-commit: 69e858e0b8b2ea07759e995aa383e8780d9d140c

Comments

Günther Noack Feb. 22, 2025, 7:47 p.m. UTC | #1
On Fri, Jan 31, 2025 at 05:30:35PM +0100, Mickaël Salaün wrote:
> Hi,
> 
> This patch series adds audit support to Landlock.
> 
> Logging denied requests is useful for different use cases:
> - sysadmins: to look for users' issues,
> - security experts: to detect attack attempts,
> - power users: to understand denials,
> - developers: to ease sandboxing support and get feedback from users.
> 
> Because of its unprivileged nature, Landlock can compose standalone
> security policies (i.e. domains).  To make logs useful, they need to
> contain the most relevant Landlock domain that denied an action, and the
> reason of such denial.  This translates to the latest nested domain and
> the related blockers: missing access rights or other kind of
> restrictions.
> 
> # Changes from previous version
> 
> Remove the AUDIT_EXE_LANDLOCK_DENY audit rule and add 2 new
> landlock_restrict_self(2) flags to filter Landlock audit events, which
> makes 3 flags:
> - LANDLOCK_RESTRICT_SELF_QUIET: do not log any denied access because of
>   this new domain.
> - LANDLOCK_RESTRICT_SELF_QUIET_DESCENDENTS: do not log denied access
>   from child domains.
> - LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC: log denied access for processes
>   resulting from an execve(2), which is not the case by default anymore.
> 
> One patch was merged in mainline: 7ccbe076d987 ("lsm: Only build
> lsm_audit.c if CONFIG_SECURITY and CONFIG_AUDIT are set").
> 
> # Design
> 
> Log records are created for any denied actions caused by a Landlock
> policy, which means that a well-sandboxed applications should not log
> anything except for unattended access requests that might be the result
> of attacks or bugs.
> 
> However, sandbox tools creating restricted environments could lead to
> abundant log entries because the sandboxed processes may not be aware of
> the related restrictions.  To avoid log spam, the
> landlock_restrict_self(2) syscall gets a new
> LANDLOCK_RESTRICT_SELF_QUIET flag to not log denials related to this
> specific domain.  Except for well-understood exceptions, this flag
> should not be set.  Indeed, applications sandboxing themselves should
> only try to bypass their own sandbox if they are compromised, which
> should ring a bell thanks to log events.
> 
> When an action is denied, the related Landlock domain ID is specified.
> If this domain was not previously described in a log record, one is
> created.  This record contains the domain ID, its creation time, and
> informations about the process that enforced the restriction (at the
> time of the call to landlock_restrict_self): PID, UID, executable path,
> and name (comm).
> 
> This new approach also brings building blocks for an upcoming
> unprivileged introspection interface.  The unique Landlock IDs will be
> useful to tie audit log entries to running processes, and to get
> properties of the related Landlock domains.  This will replace the
> previously logged ruleset properties.

What implications does this patch set have for Landlock's performance?

For some aspects of Landlock domains, when domains get merged, their
rules can potentially get merged into simpler "flattened"
representations at the cost of losing track about the original domain
for individual denials.

For instance, when a process enforces the following two rulesets
nested in each other:

 * RS1 allowed to only connect to TCP ports {1, 2, 3}
 * RS2 allowed to only connect to TCP ports {2, 3, 4}

Then the resulting merged domain could build the intersection of these
two sets {2, 3}, and store a smaller set of port numbers than the two
rulesets individually.  Similar tricks would likely also be possible
for the rules for socket type restriction, as well as for
IOCTL-per-command allow-lists, if we had done that at that level of
granularity.

I realize that we are not doing this right now for ports, so it is
slightly speculative, but it would be an option in the future.
However, when we want to attribute each denial to the original domain
which caused it, that kind of optimization does not work any more.

In performance-sensitive environments that don't need Landlock
auditing, to what extent would users of such environments have to pay
a "hidden cost" of auditing because we can't do such "data structure
flattening" optimizations any more?

Do you have thoughts on how you want to strike the balance between
Landlock performance and logging accuracy?

–Günther

> # Samples
> 
> Here are two examples of log events (see serial numbers):
> 
> $ LL_FS_RO=/ LL_FS_RW=/ LL_SCOPED=s LL_FORCE_LOG=1 ./sandboxer kill 1
> 
>   type=LANDLOCK_ACCESS msg=audit(1729738800.268:30): domain=1a6fdc66f blockers=scope.signal opid=1 ocomm="systemd"
>   type=LANDLOCK_DOMAIN msg=audit(1729738800.268:30): domain=1a6fdc66f status=allocated mode=enforcing pid=286 uid=0 exe="/root/sandboxer" comm="sandboxer"
>   type=SYSCALL msg=audit(1729738800.268:30): arch=c000003e syscall=62 success=no exit=-1 [..] ppid=272 pid=286 auid=0 uid=0 gid=0 [...] comm="kill" [...]
>   type=PROCTITLE msg=audit(1729738800.268:30): proctitle=6B696C6C0031
>   type=LANDLOCK_DOMAIN msg=audit(1729738800.324:31): domain=1a6fdc66f status=deallocated denials=1
> 
> $ LL_FS_RO=/ LL_FS_RW=/tmp LL_FORCE_LOG=1 ./sandboxer sh -c "echo > /etc/passwd"
> 
>   type=LANDLOCK_ACCESS msg=audit(1729738800.221:33): domain=1a6fdc679 blockers=fs.write_file path="/dev/tty" dev="devtmpfs" ino=9
>   type=LANDLOCK_DOMAIN msg=audit(1729738800.221:33): domain=1a6fdc679 status=allocated mode=enforcing pid=289 uid=0 exe="/root/sandboxer" comm="sandboxer"
>   type=SYSCALL msg=audit(1729738800.221:33): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
>   type=PROCTITLE msg=audit(1729738800.221:33): proctitle=7368002D63006563686F203E202F6574632F706173737764
>   type=LANDLOCK_ACCESS msg=audit(1729738800.221:34): domain=1a6fdc679 blockers=fs.write_file path="/etc/passwd" dev="vda2" ino=143821
>   type=SYSCALL msg=audit(1729738800.221:34): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
>   type=PROCTITLE msg=audit(1729738800.221:34): proctitle=7368002D63006563686F203E202F6574632F706173737764
>   type=LANDLOCK_DOMAIN msg=audit(1729738800.261:35): domain=1a6fdc679 status=deallocated denials=2
> 
> # Future changes
> 
> I'll add more tests to check each kind of denied access.
> 
> # Previous versions
> 
> v4: https://lore.kernel.org/r/20250108154338.1129069-1-mic@digikod.net
> v3: https://lore.kernel.org/r/20241122143353.59367-1-mic@digikod.net
> v2: https://lore.kernel.org/r/20241022161009.982584-1-mic@digikod.net
> v1: https://lore.kernel.org/r/20230921061641.273654-1-mic@digikod.net
> 
> Regards,
> 
> Mickaël Salaün (24):
>   lsm: Add audit_log_lsm_data() helper
>   landlock: Add unique ID generator
>   landlock: Move domain hierarchy management
>   landlock: Prepare to use credential instead of domain for filesystem
>   landlock: Prepare to use credential instead of domain for network
>   landlock: Prepare to use credential instead of domain for scope
>   landlock: Prepare to use credential instead of domain for fowner
>   landlock: Identify domain execution crossing
>   landlock: Add AUDIT_LANDLOCK_ACCESS and log ptrace denials
>   landlock: Add AUDIT_LANDLOCK_DOMAIN and log domain status
>   landlock: Log mount-related denials
>   landlock: Log file-related denials
>   landlock: Log truncate and IOCTL denials
>   landlock: Log TCP bind and connect denials
>   landlock: Log scoped denials
>   landlock: Add LANDLOCK_RESTRICT_SELF_QUIET
>   landlock: Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
>   landlock: Add LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC
>   samples/landlock: Enable users to log sandbox denials
>   selftests/landlock: Extend tests for landlock_restrict_self()'s flags
>   selftests/landlock: Add tests for audit and
>     LANDLOCK_RESTRICT_SELF_QUIET
>   selftests/landlock: Test audit with restrict flags
>   selftests/landlock: Add audit tests for ptrace
>   landlock: Add audit documentation
> 
>  Documentation/admin-guide/LSM/index.rst       |   1 +
>  Documentation/admin-guide/LSM/landlock.rst    | 157 ++++++
>  Documentation/security/landlock.rst           |   7 +
>  Documentation/userspace-api/landlock.rst      |   9 +-
>  MAINTAINERS                                   |   1 +
>  include/linux/lsm_audit.h                     |   8 +
>  include/uapi/linux/audit.h                    |   4 +-
>  include/uapi/linux/landlock.h                 |  31 ++
>  samples/landlock/sandboxer.c                  |  37 +-
>  security/landlock/.kunitconfig                |   2 +
>  security/landlock/Makefile                    |   5 +
>  security/landlock/access.h                    |  23 +
>  security/landlock/audit.c                     | 513 ++++++++++++++++++
>  security/landlock/audit.h                     |  77 +++
>  security/landlock/cred.c                      |  26 +-
>  security/landlock/cred.h                      |  65 +++
>  security/landlock/domain.c                    | 264 +++++++++
>  security/landlock/domain.h                    | 158 ++++++
>  security/landlock/fs.c                        | 279 ++++++++--
>  security/landlock/fs.h                        |  21 +-
>  security/landlock/id.c                        | 249 +++++++++
>  security/landlock/id.h                        |  25 +
>  security/landlock/limits.h                    |   4 +
>  security/landlock/net.c                       |  74 ++-
>  security/landlock/ruleset.c                   |  33 +-
>  security/landlock/ruleset.h                   |  47 +-
>  security/landlock/setup.c                     |   2 +
>  security/landlock/syscalls.c                  |  50 +-
>  security/landlock/task.c                      | 232 ++++++--
>  security/lsm_audit.c                          |  27 +-
>  tools/testing/kunit/configs/all_tests.config  |   2 +
>  tools/testing/selftests/landlock/Makefile     |   6 +-
>  tools/testing/selftests/landlock/audit.h      | 358 ++++++++++++
>  tools/testing/selftests/landlock/audit_test.c | 425 +++++++++++++++
>  tools/testing/selftests/landlock/base_test.c  |  43 +-
>  tools/testing/selftests/landlock/common.h     |   3 +
>  tools/testing/selftests/landlock/config       |   1 +
>  .../testing/selftests/landlock/ptrace_test.c  |  67 ++-
>  .../selftests/landlock/wait-pipe-sandbox.c    | 131 +++++
>  39 files changed, 3244 insertions(+), 223 deletions(-)
>  create mode 100644 Documentation/admin-guide/LSM/landlock.rst
>  create mode 100644 security/landlock/audit.c
>  create mode 100644 security/landlock/audit.h
>  create mode 100644 security/landlock/domain.c
>  create mode 100644 security/landlock/domain.h
>  create mode 100644 security/landlock/id.c
>  create mode 100644 security/landlock/id.h
>  create mode 100644 tools/testing/selftests/landlock/audit.h
>  create mode 100644 tools/testing/selftests/landlock/audit_test.c
>  create mode 100644 tools/testing/selftests/landlock/wait-pipe-sandbox.c
> 
> 
> base-commit: 69e858e0b8b2ea07759e995aa383e8780d9d140c
> -- 
> 2.48.1
>
Mickaël Salaün Feb. 25, 2025, 7:51 p.m. UTC | #2
On Sat, Feb 22, 2025 at 08:47:40PM +0100, Günther Noack wrote:
> On Fri, Jan 31, 2025 at 05:30:35PM +0100, Mickaël Salaün wrote:
> > Hi,
> > 
> > This patch series adds audit support to Landlock.
> > 
> > Logging denied requests is useful for different use cases:
> > - sysadmins: to look for users' issues,
> > - security experts: to detect attack attempts,
> > - power users: to understand denials,
> > - developers: to ease sandboxing support and get feedback from users.
> > 
> > Because of its unprivileged nature, Landlock can compose standalone
> > security policies (i.e. domains).  To make logs useful, they need to
> > contain the most relevant Landlock domain that denied an action, and the
> > reason of such denial.  This translates to the latest nested domain and
> > the related blockers: missing access rights or other kind of
> > restrictions.
> > 
> > # Changes from previous version
> > 
> > Remove the AUDIT_EXE_LANDLOCK_DENY audit rule and add 2 new
> > landlock_restrict_self(2) flags to filter Landlock audit events, which
> > makes 3 flags:
> > - LANDLOCK_RESTRICT_SELF_QUIET: do not log any denied access because of
> >   this new domain.
> > - LANDLOCK_RESTRICT_SELF_QUIET_DESCENDENTS: do not log denied access
> >   from child domains.
> > - LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC: log denied access for processes
> >   resulting from an execve(2), which is not the case by default anymore.
> > 
> > One patch was merged in mainline: 7ccbe076d987 ("lsm: Only build
> > lsm_audit.c if CONFIG_SECURITY and CONFIG_AUDIT are set").
> > 
> > # Design
> > 
> > Log records are created for any denied actions caused by a Landlock
> > policy, which means that a well-sandboxed applications should not log
> > anything except for unattended access requests that might be the result
> > of attacks or bugs.
> > 
> > However, sandbox tools creating restricted environments could lead to
> > abundant log entries because the sandboxed processes may not be aware of
> > the related restrictions.  To avoid log spam, the
> > landlock_restrict_self(2) syscall gets a new
> > LANDLOCK_RESTRICT_SELF_QUIET flag to not log denials related to this
> > specific domain.  Except for well-understood exceptions, this flag
> > should not be set.  Indeed, applications sandboxing themselves should
> > only try to bypass their own sandbox if they are compromised, which
> > should ring a bell thanks to log events.
> > 
> > When an action is denied, the related Landlock domain ID is specified.
> > If this domain was not previously described in a log record, one is
> > created.  This record contains the domain ID, its creation time, and
> > informations about the process that enforced the restriction (at the
> > time of the call to landlock_restrict_self): PID, UID, executable path,
> > and name (comm).
> > 
> > This new approach also brings building blocks for an upcoming
> > unprivileged introspection interface.  The unique Landlock IDs will be
> > useful to tie audit log entries to running processes, and to get
> > properties of the related Landlock domains.  This will replace the
> > previously logged ruleset properties.
> 
> What implications does this patch set have for Landlock's performance?

I did the benchmark for the hook_file_open() (with the changes explained
below) and there is no visible overhead for the worse case: opening /
takes ~8 micro seconds with and without sandboxing, and with and without
this patch series (when the request is allowed).  I'll do the same for
other significant operations, including for denied requests, and include
the result in the next patch series.

> 
> For some aspects of Landlock domains, when domains get merged, their
> rules can potentially get merged into simpler "flattened"
> representations at the cost of losing track about the original domain
> for individual denials.
> 
> For instance, when a process enforces the following two rulesets
> nested in each other:
> 
>  * RS1 allowed to only connect to TCP ports {1, 2, 3}
>  * RS2 allowed to only connect to TCP ports {2, 3, 4}
> 
> Then the resulting merged domain could build the intersection of these
> two sets {2, 3}, and store a smaller set of port numbers than the two
> rulesets individually.  Similar tricks would likely also be possible
> for the rules for socket type restriction, as well as for
> IOCTL-per-command allow-lists, if we had done that at that level of
> granularity.
> 
> I realize that we are not doing this right now for ports, so it is
> slightly speculative, but it would be an option in the future.
> However, when we want to attribute each denial to the original domain
> which caused it, that kind of optimization does not work any more.

Yes, we are not doing this because of the requirement to identify
domains, see
http://lore.kernel.org/r/86db9124-ea11-0fa5-9dff-61744b2f80b4@digikod.net

We really need to be able to identify the cause/source of any denial.
This is a required feature for any decent access control system to
enable users to debug their systems/programs.  I should probably extend
the Landlock guiding principles with this requirement.

This requirement might limit potential future improvements (at the
margin), but it's definitely worth it.

> 
> In performance-sensitive environments that don't need Landlock
> auditing, to what extent would users of such environments have to pay
> a "hidden cost" of auditing because we can't do such "data structure
> flattening" optimizations any more?

In such environments, users can disable audit, and we could have a
dedicated type for this case, but I'm not convinced such optimization
and potential increased complexity would be worth it wrt other "slow"
paths.  Anyway, we should first start optimizing by using a hash table.

> 
> Do you have thoughts on how you want to strike the balance between
> Landlock performance and logging accuracy?

The initial versions of this audit support patch series were much more
verbose.  With the current version I think we found the right balance
between the minimal useful information, verbosity, and complexity.

One important point to keep in mind is that the vast majority of this
new code is only executed for denied access requests.  The approach is
for processes to only pay (a bit) when they request a denied access
(which should be rare).

However, I though the audit-specific variables (e.g. struct
landlock_request) initialization would be moveed near the
landlock_log_denial() calls (i.e. only initialized for denied
requests), but even with compiler optimizations, neither GCC nor clang
do that, so I'll do it manually in the next series.

For now, the two main potential slow paths for Landlock are the backward
path walks for filesystem access [1], and the use of red-black trees for
domains [2].  These slow paths are already difficult to see, so the
impact of audit support is negligible comparatively, especially for
legitimate use cases.

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

> 
> –Günther
> 
> > # Samples
> > 
> > Here are two examples of log events (see serial numbers):
> > 
> > $ LL_FS_RO=/ LL_FS_RW=/ LL_SCOPED=s LL_FORCE_LOG=1 ./sandboxer kill 1
> > 
> >   type=LANDLOCK_ACCESS msg=audit(1729738800.268:30): domain=1a6fdc66f blockers=scope.signal opid=1 ocomm="systemd"
> >   type=LANDLOCK_DOMAIN msg=audit(1729738800.268:30): domain=1a6fdc66f status=allocated mode=enforcing pid=286 uid=0 exe="/root/sandboxer" comm="sandboxer"
> >   type=SYSCALL msg=audit(1729738800.268:30): arch=c000003e syscall=62 success=no exit=-1 [..] ppid=272 pid=286 auid=0 uid=0 gid=0 [...] comm="kill" [...]
> >   type=PROCTITLE msg=audit(1729738800.268:30): proctitle=6B696C6C0031
> >   type=LANDLOCK_DOMAIN msg=audit(1729738800.324:31): domain=1a6fdc66f status=deallocated denials=1
> > 
> > $ LL_FS_RO=/ LL_FS_RW=/tmp LL_FORCE_LOG=1 ./sandboxer sh -c "echo > /etc/passwd"
> > 
> >   type=LANDLOCK_ACCESS msg=audit(1729738800.221:33): domain=1a6fdc679 blockers=fs.write_file path="/dev/tty" dev="devtmpfs" ino=9
> >   type=LANDLOCK_DOMAIN msg=audit(1729738800.221:33): domain=1a6fdc679 status=allocated mode=enforcing pid=289 uid=0 exe="/root/sandboxer" comm="sandboxer"
> >   type=SYSCALL msg=audit(1729738800.221:33): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
> >   type=PROCTITLE msg=audit(1729738800.221:33): proctitle=7368002D63006563686F203E202F6574632F706173737764
> >   type=LANDLOCK_ACCESS msg=audit(1729738800.221:34): domain=1a6fdc679 blockers=fs.write_file path="/etc/passwd" dev="vda2" ino=143821
> >   type=SYSCALL msg=audit(1729738800.221:34): arch=c000003e syscall=257 success=no exit=-13 [...] ppid=272 pid=289 auid=0 uid=0 gid=0 [...] comm="sh" [...]
> >   type=PROCTITLE msg=audit(1729738800.221:34): proctitle=7368002D63006563686F203E202F6574632F706173737764
> >   type=LANDLOCK_DOMAIN msg=audit(1729738800.261:35): domain=1a6fdc679 status=deallocated denials=2
> > 
> > # Future changes
> > 
> > I'll add more tests to check each kind of denied access.
> > 
> > # Previous versions
> > 
> > v4: https://lore.kernel.org/r/20250108154338.1129069-1-mic@digikod.net
> > v3: https://lore.kernel.org/r/20241122143353.59367-1-mic@digikod.net
> > v2: https://lore.kernel.org/r/20241022161009.982584-1-mic@digikod.net
> > v1: https://lore.kernel.org/r/20230921061641.273654-1-mic@digikod.net
> > 
> > Regards,
> > 
> > Mickaël Salaün (24):
> >   lsm: Add audit_log_lsm_data() helper
> >   landlock: Add unique ID generator
> >   landlock: Move domain hierarchy management
> >   landlock: Prepare to use credential instead of domain for filesystem
> >   landlock: Prepare to use credential instead of domain for network
> >   landlock: Prepare to use credential instead of domain for scope
> >   landlock: Prepare to use credential instead of domain for fowner
> >   landlock: Identify domain execution crossing
> >   landlock: Add AUDIT_LANDLOCK_ACCESS and log ptrace denials
> >   landlock: Add AUDIT_LANDLOCK_DOMAIN and log domain status
> >   landlock: Log mount-related denials
> >   landlock: Log file-related denials
> >   landlock: Log truncate and IOCTL denials
> >   landlock: Log TCP bind and connect denials
> >   landlock: Log scoped denials
> >   landlock: Add LANDLOCK_RESTRICT_SELF_QUIET
> >   landlock: Add LANDLOCK_RESTRICT_SELF_QUIET_SUBDOMAINS
> >   landlock: Add LANDLOCK_RESTRICT_SELF_LOG_CROSS_EXEC
> >   samples/landlock: Enable users to log sandbox denials
> >   selftests/landlock: Extend tests for landlock_restrict_self()'s flags
> >   selftests/landlock: Add tests for audit and
> >     LANDLOCK_RESTRICT_SELF_QUIET
> >   selftests/landlock: Test audit with restrict flags
> >   selftests/landlock: Add audit tests for ptrace
> >   landlock: Add audit documentation
> > 
> >  Documentation/admin-guide/LSM/index.rst       |   1 +
> >  Documentation/admin-guide/LSM/landlock.rst    | 157 ++++++
> >  Documentation/security/landlock.rst           |   7 +
> >  Documentation/userspace-api/landlock.rst      |   9 +-
> >  MAINTAINERS                                   |   1 +
> >  include/linux/lsm_audit.h                     |   8 +
> >  include/uapi/linux/audit.h                    |   4 +-
> >  include/uapi/linux/landlock.h                 |  31 ++
> >  samples/landlock/sandboxer.c                  |  37 +-
> >  security/landlock/.kunitconfig                |   2 +
> >  security/landlock/Makefile                    |   5 +
> >  security/landlock/access.h                    |  23 +
> >  security/landlock/audit.c                     | 513 ++++++++++++++++++
> >  security/landlock/audit.h                     |  77 +++
> >  security/landlock/cred.c                      |  26 +-
> >  security/landlock/cred.h                      |  65 +++
> >  security/landlock/domain.c                    | 264 +++++++++
> >  security/landlock/domain.h                    | 158 ++++++
> >  security/landlock/fs.c                        | 279 ++++++++--
> >  security/landlock/fs.h                        |  21 +-
> >  security/landlock/id.c                        | 249 +++++++++
> >  security/landlock/id.h                        |  25 +
> >  security/landlock/limits.h                    |   4 +
> >  security/landlock/net.c                       |  74 ++-
> >  security/landlock/ruleset.c                   |  33 +-
> >  security/landlock/ruleset.h                   |  47 +-
> >  security/landlock/setup.c                     |   2 +
> >  security/landlock/syscalls.c                  |  50 +-
> >  security/landlock/task.c                      | 232 ++++++--
> >  security/lsm_audit.c                          |  27 +-
> >  tools/testing/kunit/configs/all_tests.config  |   2 +
> >  tools/testing/selftests/landlock/Makefile     |   6 +-
> >  tools/testing/selftests/landlock/audit.h      | 358 ++++++++++++
> >  tools/testing/selftests/landlock/audit_test.c | 425 +++++++++++++++
> >  tools/testing/selftests/landlock/base_test.c  |  43 +-
> >  tools/testing/selftests/landlock/common.h     |   3 +
> >  tools/testing/selftests/landlock/config       |   1 +
> >  .../testing/selftests/landlock/ptrace_test.c  |  67 ++-
> >  .../selftests/landlock/wait-pipe-sandbox.c    | 131 +++++
> >  39 files changed, 3244 insertions(+), 223 deletions(-)
> >  create mode 100644 Documentation/admin-guide/LSM/landlock.rst
> >  create mode 100644 security/landlock/audit.c
> >  create mode 100644 security/landlock/audit.h
> >  create mode 100644 security/landlock/domain.c
> >  create mode 100644 security/landlock/domain.h
> >  create mode 100644 security/landlock/id.c
> >  create mode 100644 security/landlock/id.h
> >  create mode 100644 tools/testing/selftests/landlock/audit.h
> >  create mode 100644 tools/testing/selftests/landlock/audit_test.c
> >  create mode 100644 tools/testing/selftests/landlock/wait-pipe-sandbox.c
> > 
> > 
> > base-commit: 69e858e0b8b2ea07759e995aa383e8780d9d140c
> > -- 
> > 2.48.1
> > 
>