On Thu, Oct 22, 2026 at 3:57 AM Alexei Starovoitov
[off-list ref] wrote:
quoted hunk ↗ jump to hunk
@@ -1713,8 +1713,22 @@ __latent_entropy int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
LIST_HEAD(uf);
VMA_ITERATOR(vmi, mm, 0);
- if (mmap_write_lock_killable(oldmm))
- return -EINTR;
+ /*
+ * Take mmap_lock of oldmm and dup_mmap_sem of uprobes.
+ * Don't sleep on one of them while holding the other.
+ */
+ for (;;) {
+ if (mmap_write_lock_killable(oldmm))
+ return -EINTR;
+ if (uprobe_try_start_dup_mmap())
+ break;
+ mmap_write_unlock(oldmm);
+
+ uprobe_start_dup_mmap();
+ if (mmap_write_trylock(oldmm))
+ break;
+ uprobe_end_dup_mmap();
+ }
I guess in practice that probably works fine, though in theory this
locking pattern could potentially lead to livelock?
Like, if two threads T1/T2 both try to acquire the locks L1 and L2
with this pattern, you could get something like:
Thread 2: lock L1
Thread 2: trylock L2 [fails due to contention by a third thread]
Thread 2: unlock L1
Thread 1: lock L1
Thread 2: lock L2
Thread 1: trylock L2 fails
Thread 2: trylock L1 fails
Thread 1: unlock L1
Thread 2: unlock L2
Thread 1: lock L2
Thread 2: lock L1
Thread 1: trylock L1 fails
Thread 2: trylock L2 fails
Thread 1: unlock L2
Thread 2: unlock L1
... and so on
In practice, it's probably fine as long as SMP cores don't run in
perfect lockstep...