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
> > [...]
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.