Linux Trace Kernel
 help / color / mirror / Atom feed
From: Justin Suess <utilityemal77@gmail.com>
To: "Mickaël Salaün" <mic@digikod.net>
Cc: "Christian Brauner" <brauner@kernel.org>,
	"Günther Noack" <gnoack@google.com>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Jann Horn" <jannh@google.com>, "Jeff Xu" <jeffxu@google.com>,
	"Kees Cook" <kees@kernel.org>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
	"Matthieu Buffet" <matthieu@buffet.re>,
	"Mikhail Ivanov" <ivanov.mikhail1@huawei-partners.com>,
	"Tingmao Wang" <m@maowtm.org>,
	kernel-team@cloudflare.com, linux-fsdevel@vger.kernel.org,
	linux-security-module@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org
Subject: Re: [PATCH v2 06/17] landlock: Add create_ruleset and free_ruleset tracepoints
Date: Tue, 28 Jul 2026 18:52:19 -0400	[thread overview]
Message-ID: <amkx1TBWk6AieKuw@zenbox> (raw)
In-Reply-To: <20260728.nohNgei7Nei9@digikod.net>

On Tue, Jul 28, 2026 at 10:56:16PM +0200, Mickaël Salaün wrote:
> On Tue, May 26, 2026 at 05:34:59PM -0400, Justin Suess wrote:
> > On Mon, Apr 06, 2026 at 04:37:04PM +0200, Mickaël Salaün wrote:
> > > Add tracepoints for ruleset lifecycle events: landlock_create_ruleset
> > > fires from the landlock_create_ruleset() syscall handler, logging the
> > > ruleset Landlock ID and handled access masks; landlock_free_ruleset
> > > fires in free_ruleset() before the ruleset is freed, so eBPF programs
> > > can access the full ruleset state via BTF.
> > > 
> > > The create_ruleset TP_PROTO takes only the ruleset pointer.  The handled
> > > access masks are read from the ruleset in TP_fast_assign rather than
> > > passed as scalar arguments, so eBPF programs can access the full ruleset
> > > state (rules, access masks) via BTF on a single pointer.  No lock is
> > > needed because the ruleset is not yet shared (the file descriptor has
> > > not been installed).
> > > 
> > > Create the trace header with a DOC comment documenting the consistency
> > > guarantees, locking conventions, TP_PROTO safety, and security
> > > considerations shared by all Landlock tracepoints.  Add
> > > CREATE_TRACE_POINTS in log.c to generate the tracepoint implementations.
> > > 
> > > Add an id field to struct landlock_ruleset, assigned from
> > > landlock_get_id_range() at creation time.  Extend the CONFIG guard on
> > > landlock_get_id_range() from CONFIG_AUDIT to
> > > CONFIG_SECURITY_LANDLOCK_LOG so that IDs are available for tracing even
> > > without audit support.
> > > 
> > > The deallocation events use the "free_" prefix (rather than "drop_")
> > > because they fire when the object is actually freed.  There is no need
> > > for allocated/deallocated symmetry because ruleset creation happens with
> > > the landlock_create_ruleset tracepoint.
> > > 
> > > landlock_create_ruleset tracepoint.
> > > 
> > > Unlike audit records which share a record type and need a "status="
> > > field to distinguish allocation from deallocation, tracepoints provide
> > > one event type per lifecycle transition, each with a type-safe TP_PROTO
> > > matching the specific transition.  This enables type-safe eBPF BTF
> > > access and precise ftrace filtering by event name.
> > > 
> > > Cc: Günther Noack <gnoack@google.com>
> > > Cc: Justin Suess <utilityemal77@gmail.com>
> > > Cc: Masami Hiramatsu <mhiramat@kernel.org>
> > > Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> > > Cc: Steven Rostedt <rostedt@goodmis.org>
> > > Cc: Tingmao Wang <m@maowtm.org>
> > > Signed-off-by: Mickaël Salaün <mic@digikod.net>
> > > ---
> > > 
> > > Changes since v1:
> > > - New patch (split from the v1 add_rule_fs tracepoint patch).
> > > ---
> > >  MAINTAINERS                     |  1 +
> > >  include/trace/events/landlock.h | 94 +++++++++++++++++++++++++++++++++
> > >  security/landlock/id.h          |  6 +--
> > >  security/landlock/log.c         |  5 ++
> > >  security/landlock/ruleset.c     |  8 +++
> > >  security/landlock/ruleset.h     |  9 ++++
> > >  security/landlock/syscalls.c    |  5 ++
> > >  7 files changed, 125 insertions(+), 3 deletions(-)
> > >  create mode 100644 include/trace/events/landlock.h
> > > 
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index c3fe46d7c4bc..51104faa3951 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -14389,6 +14389,7 @@ F:	Documentation/admin-guide/LSM/landlock.rst
> > >  F:	Documentation/security/landlock.rst
> > >  F:	Documentation/userspace-api/landlock.rst
> > >  F:	fs/ioctl.c
> > > +F:	include/trace/events/landlock.h
> > >  F:	include/uapi/linux/landlock.h
> > >  F:	samples/landlock/
> > >  F:	security/landlock/
> > > diff --git a/include/trace/events/landlock.h b/include/trace/events/landlock.h
> > > new file mode 100644
> > > index 000000000000..5e847844fbf7
> > > --- /dev/null
> > > +++ b/include/trace/events/landlock.h
> > > @@ -0,0 +1,94 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/*
> > > + * Copyright © 2025 Microsoft Corporation
> > > + * Copyright © 2026 Cloudflare
> > > + */
> > > +
> > > +#undef TRACE_SYSTEM
> > > +#define TRACE_SYSTEM landlock
> > > +
> > > +#if !defined(_TRACE_LANDLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
> > > +#define _TRACE_LANDLOCK_H
> > > +
> > > +#include <linux/tracepoint.h>
> > > +
> > > +struct landlock_ruleset;
> > > +
> > > +/**
> > > + * DOC: Landlock trace events
> > > + *
> > > + * Consistency guarantee: every trace event corresponds to an operation
> > > + * that has irrevocably succeeded.  Lifecycle events fire only after
> > > + * the point of no return; denial events fire only for denials that
> > > + * actually happen.  This guarantees that eBPF programs observing the
> > > + * trace stream can build a faithful model of Landlock state without
> > > + * reconciliation logic.
> > > + *
> > > + * Mutable object pointers in TP_PROTO (e.g., struct landlock_ruleset
> > > + * for add_rule events) are passed while the caller holds the object's
> > > + * lock, so that TP_fast_assign and eBPF programs reading via BTF see a
> > > + * consistent snapshot.  For objects that are immutable at the emission
> > > + * site (e.g., a domain after creation), no lock is needed.
> > > + *
> > > + * All pointer arguments in TP_PROTO are guaranteed non-NULL by the
> > > + * caller.  eBPF programs can access these pointers via BTF for richer
> > > + * introspection than the TP_STRUCT__entry fields provide.
> > > + *
> > > + * TP_STRUCT__entry fields serve TP_printk display only.  eBPF programs
> > > + * access the raw TP_PROTO arguments directly.
> > > + *
> > > + * Security: as for audit, Landlock trace events may expose sensitive
> > > + * information about all sandboxed processes on the system.  See
> > > + * Documentation/admin-guide/LSM/landlock.rst for security considerations
> > > + * and privilege requirements.
> > > + */
> > > +
> > > +/**
> > > + * landlock_create_ruleset - new ruleset created
> > > + * @ruleset: Newly created ruleset (never NULL); not yet shared via an fd,
> > > + *           so no lock is needed.  eBPF programs can read the full ruleset
> > > + *           state via BTF.
> > > + */
> > > +TRACE_EVENT(
> > > +	landlock_create_ruleset,
> > > +
> > > +	TP_PROTO(const struct landlock_ruleset *ruleset),
> > > +
> > > +	TP_ARGS(ruleset),
> > > +
> > > +	TP_STRUCT__entry(__field(__u64, ruleset_id) __field(access_mask_t,
> > > +							    handled_fs)
> > > +				 __field(access_mask_t, handled_net)
> > > +					 __field(access_mask_t, scoped)),
> > > +
> > > +	TP_fast_assign(__entry->ruleset_id = ruleset->id;
> > > +		       __entry->handled_fs = ruleset->layer.fs;
> > > +		       __entry->handled_net = ruleset->layer.net;
> > > +		       __entry->scoped = ruleset->layer.scope;),
> > > +
> > > +	TP_printk("ruleset=%llx handled_fs=0x%x handled_net=0x%x scoped=0x%x",
> > > +		  __entry->ruleset_id, __entry->handled_fs,
> > > +		  __entry->handled_net, __entry->scoped));
> > > +
> > > +/**
> > > + * landlock_free_ruleset - Ruleset freed
> > > + *
> > > + * Emitted when a ruleset's last reference is dropped (typically when
> > > + * the creating process closes the ruleset file descriptor).
> > > + */
> > > +TRACE_EVENT(landlock_free_ruleset,
> > > +
> > > +	    TP_PROTO(const struct landlock_ruleset *ruleset),
> > > +
> > > +	    TP_ARGS(ruleset),
> > > +
> > > +	    TP_STRUCT__entry(__field(__u64, ruleset_id)),
> > > +
> > > +	    TP_fast_assign(__entry->ruleset_id = ruleset->id;),
> > > +
> > > +	    TP_printk("ruleset=%llx", __entry->ruleset_id));
> > > +
> > > +#endif /* _TRACE_LANDLOCK_H */
> > > +
> > > +/* This part must be outside protection */
> > > +#include <trace/define_trace.h>
> > > diff --git a/security/landlock/id.h b/security/landlock/id.h
> > > index 45dcfb9e9a8b..2a43c2b523a8 100644
> > > --- a/security/landlock/id.h
> > > +++ b/security/landlock/id.h
> > > @@ -8,18 +8,18 @@
> > >  #ifndef _SECURITY_LANDLOCK_ID_H
> > >  #define _SECURITY_LANDLOCK_ID_H
> > >  
> > > -#ifdef CONFIG_AUDIT
> > > +#ifdef CONFIG_SECURITY_LANDLOCK_LOG
> > >  
> > >  void __init landlock_init_id(void);
> > >  
> > >  u64 landlock_get_id_range(size_t number_of_ids);
> > >  
> > > -#else /* CONFIG_AUDIT */
> > > +#else /* CONFIG_SECURITY_LANDLOCK_LOG */
> > >  
> > >  static inline void __init landlock_init_id(void)
> > >  {
> > >  }
> > >  
> > > -#endif /* CONFIG_AUDIT */
> > > +#endif /* CONFIG_SECURITY_LANDLOCK_LOG */
> > >  
> > >  #endif /* _SECURITY_LANDLOCK_ID_H */
> > > diff --git a/security/landlock/log.c b/security/landlock/log.c
> > > index c9b506707af0..ef79e4ed0037 100644
> > > --- a/security/landlock/log.c
> > > +++ b/security/landlock/log.c
> > > @@ -174,6 +174,11 @@ static void audit_denial(const struct landlock_cred_security *const subject,
> > >  
> > >  #endif /* CONFIG_AUDIT */
> > >  
> > > +#ifdef CONFIG_TRACEPOINTS
> > > +#define CREATE_TRACE_POINTS
> > > +#include <trace/events/landlock.h>
> > > +#endif /* CONFIG_TRACEPOINTS */
> > > +
> > >  static struct landlock_hierarchy *
> > >  get_hierarchy(const struct landlock_domain *const domain, const size_t layer)
> > >  {
> > > diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c
> > > index c220e0f9cf5f..0d1e3dadb318 100644
> > > --- a/security/landlock/ruleset.c
> > > +++ b/security/landlock/ruleset.c
> > > @@ -22,10 +22,13 @@
> > >  #include <linux/spinlock.h>
> > >  
> > >  #include "access.h"
> > > +#include "id.h"
> > >  #include "limits.h"
> > >  #include "object.h"
> > >  #include "ruleset.h"
> > >  
> > > +#include <trace/events/landlock.h>
> > > +
> > >  struct landlock_ruleset *
> > >  landlock_create_ruleset(const access_mask_t fs_access_mask,
> > >  			const access_mask_t net_access_mask,
> > > @@ -49,6 +52,10 @@ landlock_create_ruleset(const access_mask_t fs_access_mask,
> > >  	new_ruleset->rules.root_net_port = RB_ROOT;
> > >  #endif /* IS_ENABLED(CONFIG_INET) */
> > >  
> > > +#ifdef CONFIG_SECURITY_LANDLOCK_LOG
> > > +	new_ruleset->id = landlock_get_id_range(1);
> > > +#endif /* CONFIG_SECURITY_LANDLOCK_LOG */
> > The addition of IDs to rulesets for logging makes sense.
> > 
> > But it is limited in usefulness without some form of introspection to be
> > able to correlate it to a specific userspace ruleset.
> 
> The main goal for tracepoints is to correlate the created rule with all
> the related updates with rule addition, and then the domain creation
> from this ruleset.
> 
> > 
> > If a program creates multiple Landlock rulesets, and wishes to trace and
> > correlate which ruleset FD corresponds to the log/tracepoint, it is
> > difficult when no form of introspection exists.
> 
> That's correct, and that's the same thing for the domain IDs, for now...
> 
> These IDs are designed to be available to unprivileged processes, so
> we'll need a proper interface.  Tracepoints is the first interface to
> use ruleset IDs.
>
Makes sense. It need not be a part of this series, just something
to consider later on.

Justin

> > [...]

  reply	other threads:[~2026-07-28 22:52 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-06 14:36 [PATCH v2 00/17] Landlock tracepoints Mickaël Salaün
2026-04-06 14:36 ` [PATCH v2 01/17] landlock: Prepare ruleset and domain type split Mickaël Salaün
2026-04-12 16:29   ` Tingmao Wang
2026-04-06 14:37 ` [PATCH v2 02/17] landlock: Move domain query functions to domain.c Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 03/17] landlock: Split struct landlock_domain from struct landlock_ruleset Mickaël Salaün
2026-04-12 16:27   ` Tingmao Wang
2026-04-06 14:37 ` [PATCH v2 04/17] landlock: Split denial logging from audit into common framework Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 05/17] tracing: Add __print_untrusted_str() Mickaël Salaün
2026-05-18 10:26   ` Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 06/17] landlock: Add create_ruleset and free_ruleset tracepoints Mickaël Salaün
2026-05-26 21:34   ` Justin Suess
2026-07-28 20:56     ` Mickaël Salaün
2026-07-28 22:52       ` Justin Suess [this message]
2026-04-06 14:37 ` [PATCH v2 07/17] landlock: Add landlock_add_rule_fs and landlock_add_rule_net tracepoints Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 08/17] landlock: Add restrict_self and free_domain tracepoints Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 09/17] landlock: Add tracepoints for rule checking Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 10/17] landlock: Set audit_net.sk for socket access checks Mickaël Salaün
2026-05-26 10:42   ` Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 11/17] landlock: Add landlock_deny_access_fs and landlock_deny_access_net Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 12/17] landlock: Add tracepoints for ptrace and scope denials Mickaël Salaün
2026-04-06 15:01   ` Steven Rostedt
2026-04-07 13:00     ` Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 13/17] selftests/landlock: Add trace event test infrastructure and tests Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 14/17] selftests/landlock: Add filesystem tracepoint tests Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 15/17] selftests/landlock: Add network " Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 16/17] selftests/landlock: Add scope and ptrace " Mickaël Salaün
2026-04-06 14:37 ` [PATCH v2 17/17] landlock: Document tracepoints Mickaël Salaün

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=amkx1TBWk6AieKuw@zenbox \
    --to=utilityemal77@gmail.com \
    --cc=brauner@kernel.org \
    --cc=gnoack@google.com \
    --cc=ivanov.mikhail1@huawei-partners.com \
    --cc=jannh@google.com \
    --cc=jeffxu@google.com \
    --cc=kees@kernel.org \
    --cc=kernel-team@cloudflare.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=m@maowtm.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=matthieu@buffet.re \
    --cc=mhiramat@kernel.org \
    --cc=mic@digikod.net \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox