All of lore.kernel.org
 help / color / mirror / Atom feed
From: Justin Suess <utilityemal77@gmail.com>
To: Yihan Ding <dingyihan@uniontech.com>
Cc: "Mickaël Salaün" <mic@digikod.net>,
	"Günther Noack" <gnoack3000@gmail.com>,
	"Paul Moore" <paul@paul-moore.com>,
	"Jann Horn" <jannh@google.com>,
	linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	syzbot+7ea2f5e9dfd468201817@syzkaller.appspotmail.com
Subject: Re: [PATCH v3 1/2] landlock: Serialize TSYNC thread restriction
Date: Tue, 3 Mar 2026 11:20:10 -0500	[thread overview]
Message-ID: <aacKOr1wywSSOAVv@suesslenovo> (raw)
In-Reply-To: <20260226015903.3158620-2-dingyihan@uniontech.com>

On Thu, Feb 26, 2026 at 09:59:02AM +0800, Yihan Ding wrote:
> syzbot found a deadlock in landlock_restrict_sibling_threads().
> When multiple threads concurrently call landlock_restrict_self() with
> sibling thread restriction enabled, they can deadlock by mutually
> queueing task_works on each other and then blocking in kernel space
> (waiting for the other to finish).
> 
> Fix this by serializing the TSYNC operations within the same process
> using the exec_update_lock. This prevents concurrent invocations
> from deadlocking. 
> 
> We use down_write_trylock() and return -ERESTARTNOINTR if the lock
> cannot be acquired immediately. This ensures that if a thread fails
> to get the lock, it will return to userspace, allowing it to process
> any pending TSYNC task_works from the lock holder, and then
> transparently restart the syscall.
> 
> Fixes: 42fc7e6543f6 ("landlock: Multithreading support for landlock_restrict_self()")
> Reported-by: syzbot+7ea2f5e9dfd468201817@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=7ea2f5e9dfd468201817
> Suggested-by: Günther Noack <gnoack3000@gmail.com>
> Signed-off-by: Yihan Ding <dingyihan@uniontech.com>
> ---
> Changes in v3:
> - Replaced down_write_killable() with down_write_trylock() and 
>   returned -ERESTARTNOINTR to avoid a secondary deadlock caused by 
>   blocking the execution of task_works. (Caught by Günther Noack).
> 
> Changes in v2:
> - Use down_write_killable() instead of down_write().
> - Split the interrupt path cleanup into a separate patch.
> ---
>  security/landlock/tsync.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/security/landlock/tsync.c b/security/landlock/tsync.c
> index de01aa899751..xxxxxxxxxxxx 100644
> --- a/security/landlock/tsync.c
> +++ b/security/landlock/tsync.c
> @@ -447,6 +447,13 @@ int landlock_restrict_sibling_threads(const struct cred *old_cred,
>  	shared_ctx.new_cred = new_cred;
>  	shared_ctx.set_no_new_privs = task_no_new_privs(current);
>  
> +	/*
> +	 * Serialize concurrent TSYNC operations to prevent deadlocks
> +	 * when multiple threads call landlock_restrict_self() simultaneously.
> +	 */
> +	if (!down_write_trylock(&current->signal->exec_update_lock))
> +		return -ERESTARTNOINTR;
These two lines above introduced a test failure in tsync_test
completing_enablement.

The commit that introduced the bug is 3d6327c306b3e1356ab868bf27a0854669295a4f
(this patch) and is currently in the mic/next branch.

I noticed the test failure while testing an unrelated patch.

The bug is because this code never actually yields or restarts the syscall.

This is the test output I observed:

  [+] Running tsync_test:
  TAP version 13
  1..4
  # Starting 4 tests from 1 test cases.
  #  RUN           global.single_threaded_success ...
  #            OK  global.single_threaded_success
  ok 1 global.single_threaded_success
  #  RUN           global.multi_threaded_success ...
  #            OK  global.multi_threaded_success
  ok 2 global.multi_threaded_success
  #  RUN           global.multi_threaded_success_despite_diverging_domains ...
  #            OK  global.multi_threaded_success_despite_diverging_domains
  ok 3 global.multi_threaded_success_despite_diverging_domains
  #  RUN           global.competing_enablement ...
  # tsync_test.c:156:competing_enablement:Expected 0 (0) == d[1].result (-1)
  # competing_enablement: Test failed
  #          FAIL  global.competing_enablement
  not ok 4 global.competing_enablement
  # FAILED: 3 / 4 tests passed.


Brief investigation and the additions of these pr_warn lines:


diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 0d66a68677b7..84909232b220 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -574,6 +574,9 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
 		const int err = landlock_restrict_sibling_threads(
 			current_cred(), new_cred);
 		if (err) {
+			pr_warn("landlock: restrict_self tsync err pid=%d tgid=%d err=%d flags=0x%x ruleset_fd=%d\n",
+				task_pid_nr(current), task_tgid_nr(current), err,
+				flags, ruleset_fd);
 			abort_creds(new_cred);
 			return err;
 		}
diff --git a/security/landlock/tsync.c b/security/landlock/tsync.c
index 5afc5d639b8f..deb0f0b1f081 100644
--- a/security/landlock/tsync.c
+++ b/security/landlock/tsync.c
@@ -489,8 +489,11 @@ int landlock_restrict_sibling_threads(const struct cred *old_cred,
 	 * Serialize concurrent TSYNC operations to prevent deadlocks when multiple
 	 * threads call landlock_restrict_self() simultaneously.
 	 */
-	if (!down_write_trylock(&current->signal->exec_update_lock))
+	if (!down_write_trylock(&current->signal->exec_update_lock)) {
+		pr_warn("landlock: tsync trylock busy pid=%d tgid=%d\n",
+			task_pid_nr(current), task_tgid_nr(current));
 		return -ERESTARTNOINTR;
+	}
 
 	/*
 	 * We schedule a pseudo-signal task_work for each of the calling task's
@@ -602,6 +605,10 @@ int landlock_restrict_sibling_threads(const struct cred *old_cred,
 
 	tsync_works_release(&works);
 	up_write(&current->signal->exec_update_lock);
+	if (atomic_read(&shared_ctx.preparation_error))
+		pr_warn("landlock: tsync preparation_error pid=%d tgid=%d err=%d\n",
+			task_pid_nr(current), task_tgid_nr(current),
+			atomic_read(&shared_ctx.preparation_error));
 
 	return atomic_read(&shared_ctx.preparation_error);
 }

Resulted in the following output:

  landlock: tsync trylock busy pid=1263 tgid=1261
  landlock: landlock: restrict_self tsync err pid=1263 tgid=1261 err=-513 flags=0x8 ruleset_fd=6
  # tsync_test.c:156:competing_enablement:Expected 0 (0) == d[1].result (-1)
  # competing_enablement: Test failed
  #          FAIL  global.competing_enablement
  not ok 4 global.competing_enablement

I have a fix that I will send as a patch.

Kind Regards,
Justin Suess

  parent reply	other threads:[~2026-03-03 16:20 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-26  1:59 [PATCH v3 0/2] landlock: Fix TSYNC deadlock and clean up error path Yihan Ding
2026-02-26  1:59 ` [PATCH v3 1/2] landlock: Serialize TSYNC thread restriction Yihan Ding
2026-02-26  7:23   ` Günther Noack
2026-03-03 16:20   ` Justin Suess [this message]
2026-03-03 17:47     ` Mickaël Salaün
2026-03-03 18:13       ` Justin Suess
2026-03-03 19:50     ` Günther Noack
2026-03-03 20:38       ` Tingmao Wang
2026-03-03 21:19         ` Günther Noack
2026-03-04  2:46           ` Ding Yihan
2026-03-04  7:44             ` Günther Noack
2026-03-04 14:08             ` Justin Suess
2026-03-03 21:08       ` Justin Suess
2026-03-03 17:51   ` Mickaël Salaün
2026-02-26  1:59 ` [PATCH v3 2/2] landlock: Clean up interrupted thread logic in TSYNC Yihan Ding
2026-02-26  7:23   ` Günther Noack
2026-03-03 17:31 ` [PATCH v3 0/2] landlock: Fix TSYNC deadlock and clean up error path 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=aacKOr1wywSSOAVv@suesslenovo \
    --to=utilityemal77@gmail.com \
    --cc=dingyihan@uniontech.com \
    --cc=gnoack3000@gmail.com \
    --cc=jannh@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=mic@digikod.net \
    --cc=paul@paul-moore.com \
    --cc=syzbot+7ea2f5e9dfd468201817@syzkaller.appspotmail.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.