From: "Mickaël Salaün" <mic@digikod.net>
To: "Günther Noack" <gnoack@google.com>,
"Steven Rostedt" <rostedt@goodmis.org>
Cc: "Mickaël Salaün" <mic@digikod.net>,
"Christian Brauner" <brauner@kernel.org>,
"Jann Horn" <jannh@google.com>, "Jeff Xu" <jeffxu@google.com>,
"Justin Suess" <utilityemal77@gmail.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-security-module@vger.kernel.org,
linux-trace-kernel@vger.kernel.org
Subject: [PATCH v4 16/19] selftests/landlock: Add network tracepoint tests
Date: Tue, 11 Aug 2026 11:43:30 +0200 [thread overview]
Message-ID: <20260811094338.288094-17-mic@digikod.net> (raw)
In-Reply-To: <20260811094338.288094-1-mic@digikod.net>
Add network-specific trace tests, co-located with the existing audit
fixture so each subsystem's functional, audit, and trace tests live
together.
Parameterized fixtures verify the landlock_deny_access_net event: a bind
or connect denied outside the ruleset emits exactly one event with the
expected sport/dport, an allowed bind or connect emits none, and the
unsandboxed baseline emits none. A separate fixture verifies the
landlock_check_rule_net event on an allowed bind, anchoring its domain,
access_request, port, and grants to exact values; only check_rule_fs had
a dedicated field test before.
Port fields are read in host endianness, matching the
landlock_net_port_attr.port UAPI convention, so the decimal comparisons
also catch byte-order regressions in the tracepoint plumbing. IPv6
trace tests are intentionally elided: IPv6 hook dispatch shares the
current_check_access_socket() path with IPv4 (covered by the audit
tests), and the trace fields do not depend on address family.
Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Signed-off-by: Mickaël Salaün <mic@digikod.net>
---
Changes since v3:
https://patch.msgid.link/20260722171159.2776765-18-mic@digikod.net
- Collapse the three trace_net_connect deny_access_net field tests
(connect_denied, bind_fields, connect_after_bind) into one
parametrized deny_access_net test with a FIXTURE_VARIANT selecting
the handled access, an optional allowed-port bind, and the denied
operation (connect vs bind); same three cases and sport/dport
assertions. check_rule_net_fields stays separate.
Changes since v2:
https://patch.msgid.link/20260406143717.1815792-16-mic@digikod.net
- Anchor the shared denial fields (non-zero domain, same_exec, logged,
non-empty blockers) in the deny_access_net field tests via a common
helper, so they prove the whole event stays populated rather than
only checking sport/dport.
- Add setup_loopback() to the trace_net and trace_net_connect fixtures
(network-namespace isolation matching the rest of net_test.c) so a
bound loopback port cannot collide with a concurrent test.
- Tighten the denied-event count assertions from EXPECT_LE to EXPECT_EQ
(a single denied operation on a single-layer domain emits exactly one
event), matching the scope and ptrace trace tests.
- Add a check_rule_net field test (check_rule_net_fields): an allowed
bind matching a net-port rule emits one landlock_check_rule_net event
with domain, access_request, port, and grants pinned to exact values;
only check_rule_fs had a dedicated field test before.
Changes since v1:
- New patch.
---
tools/testing/selftests/landlock/net_test.c | 590 +++++++++++++++++++-
1 file changed, 589 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/landlock/net_test.c b/tools/testing/selftests/landlock/net_test.c
index be2eb88092fb..a18761e0fd82 100644
--- a/tools/testing/selftests/landlock/net_test.c
+++ b/tools/testing/selftests/landlock/net_test.c
@@ -10,11 +10,12 @@
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
-#include <linux/landlock.h>
#include <linux/in.h>
+#include <linux/landlock.h>
#include <sched.h>
#include <stdint.h>
#include <string.h>
+#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
@@ -22,6 +23,9 @@
#include "audit.h"
#include "common.h"
+#include "trace.h"
+
+#define TRACE_TASK "net_test"
const short sock_port_start = (1 << 10);
@@ -3285,4 +3289,588 @@ TEST_F(audit, sendmsg)
EXPECT_EQ(0, close(sock_fd));
}
+/* Trace tests */
+
+/* clang-format off */
+FIXTURE(trace_net) {
+ /* clang-format on */
+ int tracefs_ok;
+};
+
+FIXTURE_SETUP(trace_net)
+{
+ int ret;
+
+ /* Isolate the network namespace so the bound port cannot collide. */
+ setup_loopback(_metadata);
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ ASSERT_EQ(0, unshare(CLONE_NEWNS));
+ ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
+
+ ret = tracefs_fixture_setup();
+ if (ret) {
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+ self->tracefs_ok = 0;
+ SKIP(return, "tracefs not available");
+ }
+ self->tracefs_ok = 1;
+
+ ASSERT_EQ(0,
+ tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, true));
+ ASSERT_EQ(0, tracefs_clear());
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+FIXTURE_TEARDOWN(trace_net)
+{
+ if (!self->tracefs_ok)
+ return;
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, false);
+ tracefs_fixture_teardown();
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+/*
+ * Baseline: verifies that without Landlock, the bind succeeds and no
+ * deny_access_net trace event fires.
+ */
+/* clang-format off */
+FIXTURE_VARIANT(trace_net)
+{
+ /* clang-format on */
+ bool sandbox;
+ int bind_port_offset; /* 0 = allowed port, 1 = denied port */
+ int expect_denied;
+};
+
+/* Unsandboxed: no Landlock, bind should succeed with no events. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(trace_net, unsandboxed) {
+ /* clang-format on */
+ .sandbox = false,
+ .bind_port_offset = 0,
+ .expect_denied = 0,
+};
+
+/* Denied: sandboxed, bind to port not in ruleset. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(trace_net, bind_denied) {
+ /* clang-format on */
+ .sandbox = true,
+ .bind_port_offset = 1,
+ .expect_denied = 1,
+};
+
+/* Allowed: sandboxed, bind to port in ruleset. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(trace_net, bind_allowed) {
+ /* clang-format on */
+ .sandbox = true,
+ .bind_port_offset = 0,
+ .expect_denied = 0,
+};
+
+TEST_F(trace_net, deny_access_net_bind)
+{
+ char *buf;
+ int count, status;
+ pid_t child;
+
+ if (!self->tracefs_ok)
+ SKIP(return, "tracefs not available");
+
+ ASSERT_EQ(0, tracefs_clear_buf());
+
+ child = fork();
+ ASSERT_LE(0, child);
+
+ if (child == 0) {
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+ int sock_fd;
+
+ if (variant->sandbox) {
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_net =
+ LANDLOCK_ACCESS_NET_BIND_TCP,
+ };
+ struct landlock_net_port_attr port_attr = {
+ .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
+ .port = sock_port_start,
+ };
+ int ruleset_fd;
+
+ ruleset_fd = landlock_create_ruleset(
+ &ruleset_attr, sizeof(ruleset_attr), 0);
+ if (ruleset_fd < 0)
+ _exit(1);
+
+ if (landlock_add_rule(ruleset_fd,
+ LANDLOCK_RULE_NET_PORT,
+ &port_attr, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+
+ prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+ if (landlock_restrict_self(ruleset_fd, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+ close(ruleset_fd);
+ }
+
+ sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sock_fd < 0)
+ _exit(1);
+
+ addr.sin_port =
+ htons(sock_port_start + variant->bind_port_offset);
+ if (variant->expect_denied) {
+ /* Bind should be denied. */
+ if (bind(sock_fd, (struct sockaddr *)&addr,
+ sizeof(addr)) == 0) {
+ close(sock_fd);
+ _exit(2);
+ }
+ if (errno != EACCES) {
+ close(sock_fd);
+ _exit(3);
+ }
+ } else {
+ /* Bind should succeed. */
+ if (bind(sock_fd, (struct sockaddr *)&addr,
+ sizeof(addr))) {
+ close(sock_fd);
+ _exit(2);
+ }
+ }
+ close(sock_fd);
+ _exit(0);
+ }
+
+ ASSERT_EQ(child, waitpid(child, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ EXPECT_EQ(0, WEXITSTATUS(status));
+
+ buf = tracefs_read_buf();
+ ASSERT_NE(NULL, buf);
+
+ count = tracefs_count_matches(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK));
+ if (variant->expect_denied) {
+ EXPECT_EQ(variant->expect_denied, count)
+ {
+ TH_LOG("Expected deny_access_net event, got %d\n%s",
+ count, buf);
+ }
+ } else {
+ EXPECT_EQ(0, count)
+ {
+ TH_LOG("Expected 0 deny_access_net events, "
+ "got %d\n%s",
+ count, buf);
+ }
+ }
+
+ free(buf);
+}
+
+/*
+ * Anchors the denial fields shared by every deny_access_net event so a field
+ * test proves more than sport/dport: the denying domain, the same-exec bit, the
+ * audit-logging verdict, and the blocked access all stay populated.
+ */
+static void
+expect_net_deny_common_fields(struct __test_metadata *const _metadata,
+ const char *const buf)
+{
+ char field[64];
+
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "domain", field, sizeof(field)));
+ EXPECT_STRNE("0", field);
+
+ /* Same exec that restricted itself, no exec in between. */
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "same_exec", field, sizeof(field)));
+ EXPECT_STREQ("1", field);
+
+ /* Default flags, same exec: audit would log this denial. */
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "logged", field, sizeof(field)));
+ EXPECT_STREQ("1", field);
+
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "blockers", field, sizeof(field)));
+ EXPECT_STRNE("", field);
+}
+
+/* Connect and field-check tests use a separate fixture without variants. */
+
+/* clang-format off */
+FIXTURE(trace_net_connect) {
+ /* clang-format on */
+ int tracefs_ok;
+};
+
+FIXTURE_SETUP(trace_net_connect)
+{
+ int ret;
+
+ /* Isolate the network namespace so the bound port cannot collide. */
+ setup_loopback(_metadata);
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ ASSERT_EQ(0, unshare(CLONE_NEWNS));
+ ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
+
+ ret = tracefs_fixture_setup();
+ if (ret) {
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+ self->tracefs_ok = 0;
+ SKIP(return, "tracefs not available");
+ }
+ self->tracefs_ok = 1;
+
+ ASSERT_EQ(0,
+ tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, true));
+ ASSERT_EQ(0, tracefs_clear());
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+FIXTURE_TEARDOWN(trace_net_connect)
+{
+ if (!self->tracefs_ok)
+ return;
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ tracefs_enable_event(TRACEFS_DENY_ACCESS_NET_ENABLE, false);
+ tracefs_fixture_teardown();
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+/* clang-format off */
+FIXTURE_VARIANT(trace_net_connect) {
+ /* clang-format on */
+ /* handled_access_net, also the access allowed on the base port. */
+ __u64 handled;
+ /* Bind the allowed base port before the denied operation. */
+ bool bind_base_first;
+ /* Denied operation on the next port: connect (true) or bind (false). */
+ bool deny_connect;
+};
+
+/* clang-format off */
+
+/* Denied connect(): sport=0, dport=<denied port>. */
+FIXTURE_VARIANT_ADD(trace_net_connect, connect_denied) {
+ .handled = LANDLOCK_ACCESS_NET_CONNECT_TCP,
+ .bind_base_first = false,
+ .deny_connect = true,
+};
+
+/* Denied bind(): sport=<denied port>, dport=0. */
+FIXTURE_VARIANT_ADD(trace_net_connect, bind_fields) {
+ .handled = LANDLOCK_ACCESS_NET_BIND_TCP,
+ .bind_base_first = false,
+ .deny_connect = false,
+};
+
+/* Denied connect() after an allowed bind(): the connect fields (sport=0). */
+FIXTURE_VARIANT_ADD(trace_net_connect, connect_after_bind) {
+ .handled = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP,
+ .bind_base_first = true,
+ .deny_connect = true,
+};
+
+/* clang-format on */
+
+/*
+ * A denied TCP bind(2) or connect(2) emits one deny_access_net event. The port
+ * is reported in the field matching the denied operation, in host endianness
+ * (the UAPI landlock_net_port_attr.port convention): a connect denial reports
+ * sport=0 dport=<port>, a bind denial reports sport=<port> dport=0, so a
+ * byte-order or field-swap bug is caught. A prior allowed bind
+ * (connect_after_bind) does not change the connect denial's fields.
+ */
+TEST_F(trace_net_connect, deny_access_net)
+{
+ pid_t child;
+ int status;
+ char *buf;
+ char field[64], expected[16];
+
+ if (!self->tracefs_ok)
+ SKIP(return, "tracefs not available");
+
+ child = fork();
+ ASSERT_LE(0, child);
+
+ if (child == 0) {
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_net = variant->handled,
+ };
+ struct landlock_net_port_attr port_attr = {
+ .allowed_access = variant->handled,
+ .port = sock_port_start,
+ };
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+ int ruleset_fd, sock_fd, optval = 1, ret;
+
+ ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+ sizeof(ruleset_attr), 0);
+ if (ruleset_fd < 0)
+ _exit(1);
+ if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
+ &port_attr, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+ prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+ if (landlock_restrict_self(ruleset_fd, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+ close(ruleset_fd);
+
+ sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sock_fd < 0)
+ _exit(1);
+
+ /* Bind the allowed base port first (succeeds, no event). */
+ if (variant->bind_base_first) {
+ setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(optval));
+ addr.sin_port = htons(sock_port_start);
+ if (bind(sock_fd, (struct sockaddr *)&addr,
+ sizeof(addr))) {
+ close(sock_fd);
+ _exit(1);
+ }
+ }
+
+ /* Denied operation on the next port. */
+ addr.sin_port = htons(sock_port_start + 1);
+ if (variant->deny_connect)
+ ret = connect(sock_fd, (struct sockaddr *)&addr,
+ sizeof(addr));
+ else
+ ret = bind(sock_fd, (struct sockaddr *)&addr,
+ sizeof(addr));
+ if (ret == 0) {
+ close(sock_fd);
+ _exit(2);
+ }
+ if (errno != EACCES) {
+ close(sock_fd);
+ _exit(3);
+ }
+ close(sock_fd);
+ _exit(0);
+ }
+
+ ASSERT_EQ(child, waitpid(child, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ EXPECT_EQ(0, WEXITSTATUS(status));
+
+ buf = tracefs_read_buf();
+ ASSERT_NE(NULL, buf);
+
+ EXPECT_EQ(1, tracefs_count_matches(buf,
+ REGEX_DENY_ACCESS_NET(TRACE_TASK)));
+
+ expect_net_deny_common_fields(_metadata, buf);
+
+ /*
+ * The denied operation's port field carries the port; the other is 0.
+ */
+ snprintf(expected, sizeof(expected), "%llu",
+ (unsigned long long)(sock_port_start + 1));
+
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "sport", field, sizeof(field)));
+ EXPECT_STREQ(variant->deny_connect ? "0" : expected, field);
+
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_DENY_ACCESS_NET(TRACE_TASK),
+ "dport", field, sizeof(field)));
+ EXPECT_STREQ(variant->deny_connect ? expected : "0", field);
+
+ free(buf);
+}
+
+/* Field verification for the check_rule_net event on an allowed access. */
+
+/* clang-format off */
+FIXTURE(trace_net_check_rule) {
+ /* clang-format on */
+ int tracefs_ok;
+};
+
+FIXTURE_SETUP(trace_net_check_rule)
+{
+ int ret;
+
+ /* Isolate the network namespace so the bound port cannot collide. */
+ setup_loopback(_metadata);
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ ASSERT_EQ(0, unshare(CLONE_NEWNS));
+ ASSERT_EQ(0, mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL));
+
+ ret = tracefs_fixture_setup();
+ if (ret) {
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+ self->tracefs_ok = 0;
+ SKIP(return, "tracefs not available");
+ }
+ self->tracefs_ok = 1;
+
+ ASSERT_EQ(0, tracefs_enable_event(TRACEFS_CHECK_RULE_NET_ENABLE, true));
+ ASSERT_EQ(0, tracefs_clear());
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+FIXTURE_TEARDOWN(trace_net_check_rule)
+{
+ if (!self->tracefs_ok)
+ return;
+
+ set_cap(_metadata, CAP_SYS_ADMIN);
+ tracefs_enable_event(TRACEFS_CHECK_RULE_NET_ENABLE, false);
+ tracefs_fixture_teardown();
+ clear_cap(_metadata, CAP_SYS_ADMIN);
+}
+
+/*
+ * Verifies that an allowed bind matching a net-port rule emits exactly one
+ * landlock_check_rule_net event with the enforcing domain, the requested
+ * access, the checked port (host endianness), and the per-layer grants. The
+ * whole event is anchored to exact values so a revert of the check_rule_net
+ * emit (or a byte-order or field-plumbing regression) fails the test.
+ */
+TEST_F(trace_net_check_rule, check_rule_net_fields)
+{
+ pid_t child;
+ int status;
+ char *buf;
+ char field[64], expected[16];
+
+ if (!self->tracefs_ok)
+ SKIP(return, "tracefs not available");
+
+ child = fork();
+ ASSERT_LE(0, child);
+
+ if (child == 0) {
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
+ };
+ struct landlock_net_port_attr port_attr = {
+ .allowed_access = LANDLOCK_ACCESS_NET_BIND_TCP,
+ .port = sock_port_start,
+ };
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
+ int ruleset_fd, sock_fd;
+
+ ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+ sizeof(ruleset_attr), 0);
+ if (ruleset_fd < 0)
+ _exit(1);
+
+ if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
+ &port_attr, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+
+ prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+ if (landlock_restrict_self(ruleset_fd, 0)) {
+ close(ruleset_fd);
+ _exit(1);
+ }
+ close(ruleset_fd);
+
+ /* Bind to the allowed port: succeeds and matches the rule. */
+ sock_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (sock_fd < 0)
+ _exit(1);
+
+ addr.sin_port = htons(sock_port_start);
+ if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) {
+ close(sock_fd);
+ _exit(2);
+ }
+ close(sock_fd);
+ _exit(0);
+ }
+
+ ASSERT_EQ(child, waitpid(child, &status, 0));
+ ASSERT_TRUE(WIFEXITED(status));
+ EXPECT_EQ(0, WEXITSTATUS(status));
+
+ buf = tracefs_read_buf();
+ ASSERT_NE(NULL, buf);
+
+ /* A single-layer domain matching one port rule emits one event. */
+ EXPECT_EQ(1,
+ tracefs_count_matches(buf, REGEX_CHECK_RULE_NET(TRACE_TASK)))
+ {
+ TH_LOG("Expected 1 check_rule_net event\n%s", buf);
+ }
+
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
+ "domain", field, sizeof(field)));
+ EXPECT_STRNE("0", field);
+
+ ASSERT_EQ(0, tracefs_extract_field(
+ buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
+ "access_request", field, sizeof(field)));
+ EXPECT_STREQ("bind_tcp", field);
+
+ /*
+ * The port is reported in host endianness (UAPI convention), so on
+ * little-endian htons(sock_port_start) would print a different value:
+ * the exact match also catches byte-order regressions.
+ */
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
+ "port", field, sizeof(field)));
+ snprintf(expected, sizeof(expected), "%llu",
+ (unsigned long long)sock_port_start);
+ EXPECT_STREQ(expected, field);
+
+ /* One layer that fully grants the request: grants={bind_tcp}. */
+ ASSERT_EQ(0,
+ tracefs_extract_field(buf, REGEX_CHECK_RULE_NET(TRACE_TASK),
+ "grants", field, sizeof(field)));
+ EXPECT_STREQ("{bind_tcp}", field);
+
+ free(buf);
+}
+
+/*
+ * IPv6 network trace tests are intentionally elided. IPv6 hook dispatch uses
+ * the same current_check_access_socket() code path as IPv4, validated by the
+ * audit tests in this file. The trace events use the same blockers/sport/dport
+ * fields regardless of address family.
+ */
+
TEST_HARNESS_MAIN
--
2.54.0
next prev parent reply other threads:[~2026-08-11 9:44 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 9:43 [PATCH v4 00/19] Landlock tracepoints Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 01/19] landlock: Prepare ruleset and domain type split Mickaël Salaün
2026-08-16 17:56 ` Tingmao Wang
2026-08-11 9:43 ` [PATCH v4 02/19] landlock: Move domain query functions to domain.c Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 03/19] landlock: Split struct landlock_domain from struct landlock_ruleset Mickaël Salaün
2026-08-20 10:45 ` Günther Noack
2026-08-11 9:43 ` [PATCH v4 04/19] landlock: Split denial logging from audit into common framework Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 05/19] landlock: Decouple the per-denial logging decision from CONFIG_AUDIT Mickaël Salaün
2026-08-16 22:39 ` Tingmao Wang
2026-08-11 9:43 ` [PATCH v4 06/19] landlock: Consolidate access-right and scope names in a shared header Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 07/19] landlock: Add create_ruleset and free_ruleset tracepoints Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 08/19] landlock: Add landlock_add_rule_fs and landlock_add_rule_net tracepoints Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 09/19] landlock: Add create_domain and free_domain tracepoints Mickaël Salaün
2026-08-20 10:36 ` Günther Noack
2026-08-11 9:43 ` [PATCH v4 10/19] landlock: Add landlock_enforce_domain tracepoint Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 11/19] landlock: Add tracepoints for rule checking Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 12/19] landlock: Add landlock_deny_access_fs and landlock_deny_access_net Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 13/19] landlock: Add tracepoints for ptrace and scope denials Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 14/19] selftests/landlock: Add trace event test infrastructure and tests Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 15/19] selftests/landlock: Add filesystem tracepoint tests Mickaël Salaün
2026-08-11 9:43 ` Mickaël Salaün [this message]
2026-08-11 9:43 ` [PATCH v4 17/19] selftests/landlock: Add scope and ptrace " Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 18/19] selftests/landlock: Add landlock_enforce_domain trace tests Mickaël Salaün
2026-08-11 9:43 ` [PATCH v4 19/19] landlock: Document tracepoints Mickaël Salaün
2026-08-11 13:51 ` [PATCH v4 00/19] Landlock tracepoints Steven Rostedt
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=20260811094338.288094-17-mic@digikod.net \
--to=mic@digikod.net \
--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-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=rostedt@goodmis.org \
--cc=utilityemal77@gmail.com \
/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.