From: "Mickaël Salaün" <mic@digikod.net>
To: "Günther Noack" <gnoack@google.com>
Cc: linux-security-module@vger.kernel.org,
Jann Horn <jannh@google.com>, Serge Hallyn <sergeh@kernel.org>,
Konstantin Meskhidze <konstantin.meskhidze@huawei.com>,
Tingmao Wang <m@maowtm.org>,
"Andrew G. Morgan" <morgan@kernel.org>,
John Johansen <john.johansen@canonical.com>,
Paul Moore <paul@paul-moore.com>
Subject: Re: [PATCH v3 2/3] landlock: selftests for LANDLOCK_RESTRICT_SELF_TSYNC
Date: Thu, 5 Feb 2026 19:54:23 +0100 [thread overview]
Message-ID: <20260205.yooDuch4phae@digikod.net> (raw)
In-Reply-To: <20251127115136.3064948-3-gnoack@google.com>
These tests are useful but there are two missing parts:
- testing the restriction of each thread;
- testing the domain ID of each thread.
I'll merge this whole series but could you please extend this test file
with a new patch?
On Thu, Nov 27, 2025 at 12:51:35PM +0100, Günther Noack wrote:
> Exercise various scenarios where Landlock domains are enforced across
> all of a processes' threads.
>
> Cc: Andrew G. Morgan <morgan@kernel.org>
> Cc: John Johansen <john.johansen@canonical.com>
> Cc: Mickaël Salaün <mic@digikod.net>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: linux-security-module@vger.kernel.org
> Signed-off-by: Günther Noack <gnoack@google.com>
> ---
> tools/testing/selftests/landlock/base_test.c | 6 +-
> tools/testing/selftests/landlock/tsync_test.c | 161 ++++++++++++++++++
> 2 files changed, 164 insertions(+), 3 deletions(-)
> create mode 100644 tools/testing/selftests/landlock/tsync_test.c
>
> diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c
> index f4b1a275d8d9..0fea236ef4bd 100644
> --- a/tools/testing/selftests/landlock/base_test.c
> +++ b/tools/testing/selftests/landlock/base_test.c
> @@ -288,7 +288,7 @@ TEST(restrict_self_fd)
> EXPECT_EQ(EBADFD, errno);
> }
>
> -TEST(restrict_self_fd_flags)
> +TEST(restrict_self_fd_logging_flags)
> {
> int fd;
>
> @@ -304,9 +304,9 @@ TEST(restrict_self_fd_flags)
> EXPECT_EQ(EBADFD, errno);
> }
>
> -TEST(restrict_self_flags)
> +TEST(restrict_self_logging_flags)
> {
> - const __u32 last_flag = LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF;
> + const __u32 last_flag = LANDLOCK_RESTRICT_SELF_TSYNC;
>
> /* Tests invalid flag combinations. */
>
> diff --git a/tools/testing/selftests/landlock/tsync_test.c b/tools/testing/selftests/landlock/tsync_test.c
> new file mode 100644
> index 000000000000..3971e0f02c49
> --- /dev/null
> +++ b/tools/testing/selftests/landlock/tsync_test.c
> @@ -0,0 +1,161 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Landlock tests - Enforcing the same restrictions across multiple threads
> + *
> + * Copyright © 2025 Günther Noack <gnoack3000@gmail.com>
> + */
> +
> +#define _GNU_SOURCE
> +#include <pthread.h>
> +#include <sys/prctl.h>
> +#include <linux/landlock.h>
> +
> +#include "common.h"
> +
> +/* create_ruleset - Create a simple ruleset FD common to all tests */
> +static int create_ruleset(struct __test_metadata *const _metadata)
> +{
> + struct landlock_ruleset_attr ruleset_attr = {
> + .handled_access_fs = (LANDLOCK_ACCESS_FS_WRITE_FILE |
> + LANDLOCK_ACCESS_FS_TRUNCATE),
> + };
> + const int ruleset_fd =
> + landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
> +
> + ASSERT_LE(0, ruleset_fd)
> + {
> + TH_LOG("landlock_create_ruleset: %s", strerror(errno));
> + }
> + return ruleset_fd;
> +}
> +
> +TEST(single_threaded_success)
> +{
> + const int ruleset_fd = create_ruleset(_metadata);
> +
> + disable_caps(_metadata);
> +
> + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> + ASSERT_EQ(0, landlock_restrict_self(ruleset_fd,
> + LANDLOCK_RESTRICT_SELF_TSYNC));
> +
> + ASSERT_EQ(0, close(ruleset_fd));
> +}
> +
> +void store_no_new_privs(void *data)
I fixed the helpers to make them static.
> +{
> + bool *nnp = data;
> +
> + if (!nnp)
> + return;
> + *nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
> +}
> +
> +void *idle(void *data)
> +{
> + pthread_cleanup_push(store_no_new_privs, data);
> +
> + while (true)
> + sleep(1);
> +
> + pthread_cleanup_pop(1);
> +}
> +
> +TEST(multi_threaded_success)
> +{
> + pthread_t t1, t2;
> + bool no_new_privs1, no_new_privs2;
> + const int ruleset_fd = create_ruleset(_metadata);
> +
> + disable_caps(_metadata);
> +
> + ASSERT_EQ(0, pthread_create(&t1, NULL, idle, &no_new_privs1));
> + ASSERT_EQ(0, pthread_create(&t2, NULL, idle, &no_new_privs2));
> +
> + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> +
> + EXPECT_EQ(0, landlock_restrict_self(ruleset_fd,
> + LANDLOCK_RESTRICT_SELF_TSYNC));
> +
> + ASSERT_EQ(0, pthread_cancel(t1));
> + ASSERT_EQ(0, pthread_cancel(t2));
> + ASSERT_EQ(0, pthread_join(t1, NULL));
> + ASSERT_EQ(0, pthread_join(t2, NULL));
> +
> + /* The no_new_privs flag was implicitly enabled on all threads. */
> + EXPECT_TRUE(no_new_privs1);
> + EXPECT_TRUE(no_new_privs2);
> +
> + ASSERT_EQ(0, close(ruleset_fd));
> +}
> +
> +TEST(multi_threaded_success_despite_diverging_domains)
> +{
> + pthread_t t1, t2;
> + const int ruleset_fd = create_ruleset(_metadata);
> +
> + disable_caps(_metadata);
> +
> + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> +
> + ASSERT_EQ(0, pthread_create(&t1, NULL, idle, NULL));
> + ASSERT_EQ(0, pthread_create(&t2, NULL, idle, NULL));
> +
> + /*
> + * The main thread enforces a ruleset,
> + * thereby bringing the threads' Landlock domains out of sync.
> + */
> + EXPECT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
> +
> + /* Still, TSYNC succeeds, bringing the threads in sync again. */
> + EXPECT_EQ(0, landlock_restrict_self(ruleset_fd,
> + LANDLOCK_RESTRICT_SELF_TSYNC));
> +
> + ASSERT_EQ(0, pthread_cancel(t1));
> + ASSERT_EQ(0, pthread_cancel(t2));
> + ASSERT_EQ(0, pthread_join(t1, NULL));
> + ASSERT_EQ(0, pthread_join(t2, NULL));
> + ASSERT_EQ(0, close(ruleset_fd));
> +}
> +
> +struct thread_restrict_data {
> + pthread_t t;
> + int ruleset_fd;
> + int result;
> +};
> +
> +void *thread_restrict(void *data)
> +{
> + struct thread_restrict_data *d = data;
> +
> + d->result = landlock_restrict_self(d->ruleset_fd,
> + LANDLOCK_RESTRICT_SELF_TSYNC);
> + return NULL;
> +}
> +
> +TEST(competing_enablement)
> +{
> + const int ruleset_fd = create_ruleset(_metadata);
> + struct thread_restrict_data d[] = {
> + { .ruleset_fd = ruleset_fd },
> + { .ruleset_fd = ruleset_fd },
> + };
> +
> + disable_caps(_metadata);
> +
> + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
> + ASSERT_EQ(0, pthread_create(&d[0].t, NULL, thread_restrict, &d[0]));
> + ASSERT_EQ(0, pthread_create(&d[1].t, NULL, thread_restrict, &d[1]));
> +
> + /* Wait for threads to finish. */
> + ASSERT_EQ(0, pthread_join(d[0].t, NULL));
> + ASSERT_EQ(0, pthread_join(d[1].t, NULL));
> +
> + /* Expect that both succeeded. */
> + EXPECT_EQ(0, d[0].result);
> + EXPECT_EQ(0, d[1].result);
> +
> + ASSERT_EQ(0, close(ruleset_fd));
> +}
> +
> +TEST_HARNESS_MAIN
> --
> 2.52.0.177.g9f829587af-goog
>
>
next prev parent reply other threads:[~2026-02-05 18:54 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-27 11:51 [PATCH v3 0/3] Landlock multithreaded enforcement Günther Noack
2025-11-27 11:51 ` [PATCH v3 1/3] landlock: Multithreading support for landlock_restrict_self() Günther Noack
2025-11-27 11:51 ` [PATCH v3 2/3] landlock: selftests for LANDLOCK_RESTRICT_SELF_TSYNC Günther Noack
2026-02-05 18:54 ` Mickaël Salaün [this message]
2025-11-27 11:51 ` [PATCH v3 3/3] landlock: Document LANDLOCK_RESTRICT_SELF_TSYNC Günther Noack
2026-02-05 18:53 ` [PATCH v3 0/3] Landlock multithreaded enforcement Mickaël Salaün
2026-02-11 14:55 ` 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=20260205.yooDuch4phae@digikod.net \
--to=mic@digikod.net \
--cc=gnoack@google.com \
--cc=jannh@google.com \
--cc=john.johansen@canonical.com \
--cc=konstantin.meskhidze@huawei.com \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=morgan@kernel.org \
--cc=paul@paul-moore.com \
--cc=sergeh@kernel.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.