summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/landlock/tsync.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/security/landlock/tsync.c b/security/landlock/tsync.c
index 1e738ef2cff5..f0e5f8102001 100644
--- a/security/landlock/tsync.c
+++ b/security/landlock/tsync.c
@@ -486,6 +486,16 @@ int landlock_restrict_sibling_threads(const struct cred *old_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 the lock is already held, we gracefully yield by restarting the
+ * syscall. This allows the current thread to process pending
+ * task_works before retrying.
+ */
+ if (!down_write_trylock(&current->signal->exec_update_lock))
+ return restart_syscall();
+
+ /*
* We schedule a pseudo-signal task_work for each of the calling task's
* sibling threads. In the task work, each thread:
*
@@ -594,6 +604,6 @@ int landlock_restrict_sibling_threads(const struct cred *old_cred,
wait_for_completion(&shared_ctx.all_finished);
tsync_works_release(&works);
-
+ up_write(&current->signal->exec_update_lock);
return atomic_read(&shared_ctx.preparation_error);
}