From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BCEDA37DEB7 for ; Wed, 12 Aug 2026 10:57:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.92.199 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786532234; cv=none; b=JaIdiio28tGxSGAWDySDRTcxnNNpKRBu4ukjwJfqDpTIslrA2qp37/5iQ+1sfkjlK5MV0V0MTdEw32PhXe5ZubYGxp4VVi6t24F0qPpuxSYoXJaBX4oaks1lhpySvrg2T0iYrUYma9SHLYVtQ36SHIzpJO0/ACCasPzurV2iCyY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786532234; c=relaxed/simple; bh=F2/9ND3mbwWJDKYFnvux5RxH4EQhQ6GLCHqFavVEBLg=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=ZJKqv8lRyCZZj9MxMa96paCnKjX3Io3mIxWQTtfjsn3+lb2HqWIqB5gvAYuSxxRVsOqNICfLknetfM9+MIzDDvDKgwmPo+MvPHUTc5TiTfUFmWaPHgmjzzyacjaZZq5PCcYCLyBx0/OnTGDhtL6jL7mUZiLhSput3dUh4laq6iQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=pass smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=KSWNgiR4; arc=none smtp.client-ip=90.155.92.199 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="KSWNgiR4" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=ZYmLpBkasMEPz76w4XeFHBwEX5L4RF1BD4eScRT0ngY=; b=KSWNgiR46UesHBpevpt59zu8Ax Bog+lJyOSUJN960t3yKa+d71l0nmZat+pPFNUktWwwhTXDvoqM1dxfqN8uCi9iFXeNFLSKJAImtRc Uk6/nz8SltSNpjwozJCr/Jv2N1KNH6Y8vdiwkiuA+POSFQH/siEH0PVJvQiTJ8Cyh9S8aYZEUjszt mhQh7RELyw7hLur2J/TStDwavYjJNJ48mrYDWIHzY2M+ZP5hqeULvfyP/ogdBfWoVnARKEIsOzcoX wjKNO2K/mgUAIWuGa9551D0BAH8kLv7p8xPapTaI7hRxM/QguwfrcWSJFEGR/pPniJfI50dnQHf/b ariAFj0Q==; Received: from 77-249-17-252.cable.dynamic.v4.ziggo.nl ([77.249.17.252] helo=noisy.programming.kicks-ass.net) by desiato.infradead.org with esmtpsa (Exim 4.99.2 #2 (Red Hat Linux)) id 1wu6dv-0000000FKR2-0YME; Wed, 12 Aug 2026 10:57:07 +0000 Received: by noisy.programming.kicks-ass.net (Postfix, from userid 1000) id 03ED7300382; Wed, 12 Aug 2026 12:57:06 +0200 (CEST) Date: Wed, 12 Aug 2026 12:57:05 +0200 From: Peter Zijlstra To: Hyunwoo Kim Cc: tglx@kernel.org, mingo@redhat.com, dvhart@infradead.org, dave@stgolabs.net, andrealmeid@igalia.com, linux-kernel@vger.kernel.org Subject: Re: [PATCH] futex: Fix race on the initial mm->futex.phash.ref allocation Message-ID: <20260812105705.GK776954@noisy.programming.kicks-ass.net> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: On Tue, Aug 11, 2026 at 11:03:16PM +0900, Hyunwoo Kim wrote: > futex_hash_allocate() allocates mm->futex.phash.ref without any locking. > Commit d9b05321e21e ("futex: Move futex_hash_free() back to __mmput()") > moved the allocation here and assumed that the process has just a single > thread at this point. > > Commit ee9dce44362b ("futex: Drop CLONE_THREAD requirement for private > default hash alloc") widened need_futex_hash_allocate_default() to cover > any CLONE_VM clone, but left out vfork because the parent is suspended and > cannot race. > > That no longer holds once vfork is nested. If a vfork child calls vfork > again and is then killed with SIGKILL, the parent is released from its > vfork wait and runs concurrently with the grandchild in the same mm. > Neither of them went through futex_hash_allocate_default(). > > When both call prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS) at the same > time, each one sees mm->futex.phash.ref as NULL and stores its own percpu > counter. Only the last store survives. The counter stored first is no > longer reachable from the mm, so the references on it are not seen by > __futex_ref_atomic_end(). A private hash that still has references is then > considered dead and freed, and a task that still holds one of its buckets > writes into freed memory in futex_q_lock(). > > Store the counter once with cmpxchg() and let the loser free_percpu() its > own. The initial reference has to be taken before the store, otherwise > another task can install a private hash while the counter is still 0. > > Fixes: d9b05321e21e ("futex: Move futex_hash_free() back to __mmput()") > Cc: stable@vger.kernel.org > Signed-off-by: Hyunwoo Kim Yep :-( I'll go stick this in locking/urgent. Thanks! > --- > kernel/futex/core.c | 16 ++++++++++------ > 1 file changed, 10 insertions(+), 6 deletions(-) > > diff --git a/kernel/futex/core.c b/kernel/futex/core.c > index 128c5752f225c2..806576978fa84c 100644 > --- a/kernel/futex/core.c > +++ b/kernel/futex/core.c > @@ -1842,14 +1842,18 @@ static int futex_hash_allocate(unsigned int hash_slots, unsigned int flags) > } > > if (!mm->futex.phash.ref) { > + unsigned int __percpu *ref = alloc_percpu(unsigned int); > + > + if (!ref) > + return -ENOMEM; > + > /* > - * This will always be allocated by the first thread and > - * therefore requires no locking. > + * Tasks sharing the mm can run this concurrently, so take the > + * initial reference before publishing the counter. > */ > - mm->futex.phash.ref = alloc_percpu(unsigned int); > - if (!mm->futex.phash.ref) > - return -ENOMEM; > - this_cpu_inc(*mm->futex.phash.ref); /* 0 -> 1 */ > + this_cpu_inc(*ref); /* 0 -> 1 */ > + if (cmpxchg(&mm->futex.phash.ref, NULL, ref)) > + free_percpu(ref); > } > > fph = kvzalloc(struct_size(fph, queues, hash_slots), > -- > 2.43.0 >