On 5/23/25 17:57, Mickaël Salaün wrote:
Hi,

This series adds two tracepoints to Landlock, one tied to rule addition,
and another to rule checking.  With these new tracepoints, we can see
all steps leading to an access decision.  They can be directly used with
/sys/kernel/tracing/events/landlock/* or attached by eBPF programs to
get a more complete view of Landlock internals.

This new feature is useful to trouble shoot policy issues, and it should
also limit the need for custom debugging kernel code when developing new
Landlock features.

Landlock already has audit support, which enables us to log denied
access requests.  Audit is useful to identify security issues or sandbox
misconfiguration.  However, it might not be enough to debug Landlock
policies.  The main differences with audit events is that traces are
disabled by default, can be very verbose, and can be filtered according
to process and Landlock properties (e.g. domain ID).

As for audit, this tracing feature may expose sensitive information and
must then only be accessible to the system administrator.

This RFC only fully supports filesystem rules but the next series will
also support network rules.  Tests are also missing for now.

Regards,

Mickaël Salaün (5):
   landlock: Rename landlock_id to landlock_rule_ref
   landlock: Merge landlock_find_rule() into landlock_unmask_layers()
   tracing: Add __print_untrusted_str()
   landlock: Add landlock_add_rule_fs tracepoint
   landlock: Add landlock_check_rule tracepoint

  MAINTAINERS                                |   1 +
  include/linux/trace_events.h               |   3 +
  include/trace/events/landlock.h            | 124 ++++++++++++++
  include/trace/stages/stage3_trace_output.h |   4 +
  include/trace/stages/stage7_class_define.h |   1 +
  kernel/trace/trace_output.c                |  40 +++++
  security/landlock/Makefile                 |  11 +-
  security/landlock/fs.c                     | 178 +++++++++++++--------
  security/landlock/fs.h                     |   3 +
  security/landlock/net.c                    |  18 +--
  security/landlock/ruleset.c                |  65 ++++----
  security/landlock/ruleset.h                |  15 +-
  security/landlock/trace.c                  |  15 ++
  13 files changed, 365 insertions(+), 113 deletions(-)
  create mode 100644 include/trace/events/landlock.h
  create mode 100644 security/landlock/trace.c


base-commit: a5806cd506af5a7c19bcd596e4708b5c464bfd21

Tested-by: Tingmao Wang <m...@maowtm.org>

Here is an example output I got with `trace-cmd record -e landlock`:

landlock-add-ru-776 [001] 75134.554776: landlock_add_rule_fs: [FAILED TO PARSE] ruleset=0xffff88811a459200 ref_key=18446612686420679296 allowed=57343 dev=21 ino=53 pathname=/tmp/test landlock-add-ru-776 [001] 75134.555336: landlock_check_rule: [FAILED TO PARSE] domain_id=7838764077 access_request=4 ref_type=1 ref_key=18446612686420679296 layers=ARRAY[ff, df] I suggest adding some more events which I think shouldn't be too difficult to implement and I can see them helping a lot with tracing / debugging especially by BPF programs or someone new to landlock:

- landlock_restrict_self: Currently we trace out the ruleset pointer in add rule, and the domain ID in check rule. However there is no way for someone just looking at this trace (or a BPF program for landlock) to relate which rulesets are applied to which domains. I think a simple event we could add that will help with this is, on landlock_restrict_self, prints out the ruleset passed in as well as the domain ID newly created. Maybe also num_rules and num_layers on the new ruleset since it's trivial to do so, and could be informative to someone analyzing a Landlock thing.

- landlock_check_fs: Distinct from landlock_check_rule, this will happen once the outcome of the access check is determined (maybe at the end of is_access_to_paths_allowed and collect_domain_accesses?). It would include the pathname of the target file (only allocated if this event is enabled of course), so something like:

landlock_check_fs: domain_id=7838764077 access_request=4 pathname=/tmp/test allowed=true landlock_check_fs: domain_id=7838764077 access_request=4 pathname=/tmp/test2 allowed=false

We already produces audit logs for denied requests so it is a little bit duplicating that, but I think this trace event shouldn't be too costly to include. It has the benefit that

1. If an access is denied because no rules matched, we don't get any landlock_check_rule traces, and so there's no way for someone looking at the trace log to find out landlock denied something.

2. Having an event that represents an access check makes it possible for BPF programs to find out about all landlock access checks (most interestingly denied ones but we could expose the allowed ones too), and potentially relate the various `landlock_check_rule` events to an access check.

Actually, maybe it's worth having a "landlock_check_fs_enter", emitted at the beginning of is_access_to_paths_allowed and collect_domain_accesses? This could be useful for performance measurements, and also makes it more explicit which landlock_check_rule resulted from which access check. Maybe the pathname and domain_id could be printed on the enter event, and the exit event would just have the outcome? (Just an idea, I feel less certain about this. "Enter"/"exit" naming taken from sys_enter_*/sys_exit_* but start/end also works)

Reply via email to