Commit f087b0ba authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'locking-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull futex fixes from Ingo Molnar:

 - Tighten up the sys_futex_requeue() ABI a bit, to disallow dissimilar
   futex flags and potential UaF access (Peter Zijlstra)

 - Fix UaF between futex_key_to_node_opt() and vma_replace_policy()
   (Hao-Yu Yang)

 - Clear stale exiting pointer in futex_lock_pi() retry path, which
   triggered a warning (and potential misbehavior) in stress-testing
   (Davidlohr Bueso)

* tag 'locking-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  futex: Clear stale exiting pointer in futex_lock_pi() retry path
  futex: Fix UaF between futex_key_to_node_opt() and vma_replace_policy()
  futex: Require sys_futex_requeue() to have identical flags
parents 21047b17 210d36d8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ struct mempolicy {
		nodemask_t cpuset_mems_allowed;	/* relative to these nodes */
		nodemask_t user_nodemask;	/* nodemask passed by user */
	} w;
	struct rcu_head rcu;
};

/*
+1 −1
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ static int __futex_key_to_node(struct mm_struct *mm, unsigned long addr)
	if (!vma)
		return FUTEX_NO_NODE;

	mpol = vma_policy(vma);
	mpol = READ_ONCE(vma->vm_policy);
	if (!mpol)
		return FUTEX_NO_NODE;

+2 −1
Original line number Diff line number Diff line
@@ -918,7 +918,7 @@ int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked)
int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock)
{
	struct hrtimer_sleeper timeout, *to;
	struct task_struct *exiting = NULL;
	struct task_struct *exiting;
	struct rt_mutex_waiter rt_waiter;
	struct futex_q q = futex_q_init;
	DEFINE_WAKE_Q(wake_q);
@@ -933,6 +933,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
	to = futex_setup_timer(time, &timeout, flags, 0);

retry:
	exiting = NULL;
	ret = get_futex_key(uaddr, flags, &q.key, FUTEX_WRITE);
	if (unlikely(ret != 0))
		goto out;
+8 −0
Original line number Diff line number Diff line
@@ -459,6 +459,14 @@ SYSCALL_DEFINE4(futex_requeue,
	if (ret)
		return ret;

	/*
	 * For now mandate both flags are identical, like the sys_futex()
	 * interface has. If/when we merge the variable sized futex support,
	 * that patch can modify this test to allow a difference in size.
	 */
	if (futexes[0].w.flags != futexes[1].w.flags)
		return -EINVAL;

	cmpval = futexes[0].w.val;

	return futex_requeue(u64_to_user_ptr(futexes[0].w.uaddr), futexes[0].w.flags,
+8 −2
Original line number Diff line number Diff line
@@ -487,7 +487,13 @@ void __mpol_put(struct mempolicy *pol)
{
	if (!atomic_dec_and_test(&pol->refcnt))
		return;
	kmem_cache_free(policy_cache, pol);
	/*
	 * Required to allow mmap_lock_speculative*() access, see for example
	 * futex_key_to_node_opt(). All accesses are serialized by mmap_lock,
	 * however the speculative lock section unbound by the normal lock
	 * boundaries, requiring RCU freeing.
	 */
	kfree_rcu(pol, rcu);
}
EXPORT_SYMBOL_FOR_MODULES(__mpol_put, "kvm");

@@ -1020,7 +1026,7 @@ static int vma_replace_policy(struct vm_area_struct *vma,
	}

	old = vma->vm_policy;
	vma->vm_policy = new; /* protected by mmap_lock */
	WRITE_ONCE(vma->vm_policy, new); /* protected by mmap_lock */
	mpol_put(old);

	return 0;