From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) (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 A79BD2868AB for ; Thu, 12 Mar 2026 09:55:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.50.34 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773309343; cv=none; b=WPIIBPESJAf88H+17T5e5uRphVQN9P6gDLosugNMjJ56aqGovOHYkhwEx+ey3Pa1JyewBf1z5PlKc53JxPktThGgxhRZB1pMmLmekMzQULiJ14H+0JmsIjpboyGR7CoDBGgtzslOapTRwda3H964EsIWvAnQPUdmV3LLMdx/mpU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773309343; c=relaxed/simple; bh=157ZiNx1rY/T2YGvI2Oyv5eNP2CW3yeHJB06Noq2lwc=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=e7xqWGvsYw16/v0sNa+O8BHEV4LHPdjssgZJwJLlI00EpzzMmj9dBjFBZCVYRY3YctYcUx3kBuC9hE77wDmxv9Y7Hle/8Bft5cePrA8AxCgIUen5mn3FUjispZxpJ+40jlE7IZwvQxu432UCvGt8pnXiwI+gLfOAMR2hFl/icfg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=none smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=LnEdLsjc; arc=none smtp.client-ip=90.155.50.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=none 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="LnEdLsjc" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; 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=y2DzxEMgtpiaxkD5sGTYNeoqP35JUF+tY0XC2lRyENY=; b=LnEdLsjcZkdFV+b1k4KluhtHAh SZkdTstWniLdezauC2bSEti206Th/bgJy16Kfi2W3K4kFAzxUTJkKzRQqwihnK17Rahb8tzMCc4Vl TIMUydEEtpYaS4iLOX2mg2nXh2d92MIC2NrNrc0/PdPHDrrMn+dKNjmvY9SS+cs/imlnBXNfDhxjs Suz8L1B4e0MpB8Z0aPzmR5KY7d1hKKztEVE4FvG6b09xj/l2Q9/kEbqyBLHybmK5qIfhyr2HV+DqV VxMcau+5KuD/2fh5KDDnenv6ZcwmEU8mImrOdOsBwQ4bRDyGJpWDmRI0YX5bR0ZQgatVkj8xVyuba holACG2g==; Received: from 77-249-17-252.cable.dynamic.v4.ziggo.nl ([77.249.17.252] helo=noisy.programming.kicks-ass.net) by casper.infradead.org with esmtpsa (Exim 4.98.2 #2 (Red Hat Linux)) id 1w0clT-0000000B8y0-1vu9; Thu, 12 Mar 2026 09:55:35 +0000 Received: by noisy.programming.kicks-ass.net (Postfix, from userid 1000) id 6A2B8301150; Thu, 12 Mar 2026 10:55:34 +0100 (CET) Date: Thu, 12 Mar 2026 10:55:34 +0100 From: Peter Zijlstra To: Sebastian Andrzej Siewior Cc: Chengfeng Ye , tglx@kernel.org, mingo@redhat.com, linux-kernel@vger.kernel.org, dvhart@infradead.org, dave@stgolabs.net, andrealmeid@igalia.com, security@kernel.org Subject: Re: [PATCH] futex: fix NUMA node publication race causing missed wakeups Message-ID: <20260312095534.GZ1282955@noisy.programming.kicks-ass.net> References: <20260303030100.819744-1-dg573847474@gmail.com> <20260312093709.aFSyBhv-@linutronix.de> 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: <20260312093709.aFSyBhv-@linutronix.de> On Thu, Mar 12, 2026 at 10:37:09AM +0100, Sebastian Andrzej Siewior wrote: > On 2026-03-03 03:01:00 [+0000], Chengfeng Ye wrote: > > get_futex_key() publishes the FUTEX2_NUMA node side word in userspace. > > The publication path used a non-atomic read/compute/write sequence, so > > concurrent callers could overwrite each other during initialization. > > > > This race can make concurrent operations on the same futex derive > > different node values while the NUMA hint is being initialized, > > resulting in inconsistent futex keying between wait and wake sides. > > In practice this can lead to missed wakeups; at user level, missed > > wakeups can manifest as threads waiting indefinitely > > (application-level deadlock/hang). > > > > PoC description (see Link below): > > - two threads repeatedly exercising FUTEX2_NUMA wait/wake on the > > same futex, > > - waiter and waker pinned to CPUs from different NUMA nodes, > > - waker continuously issuing wake calls while waiter performs > > 10-second timed waits. > > > > PoC output on unpatched kernel (wake sigal missed and waiter timeout): > > - observed on Linux v7.0-rc2 running in qemu-system-x86_64 with > > 4 vCPUs > > Using CPU 0 (waiter) and CPU 2 (waker) from different NUMA nodes > > [TRIGGER EVENT #1] iter=38 timed out (futex.node=1) > > [TRIGGER EVENT #2] iter=85 timed out (futex.node=1) > > [TRIGGER EVENT #3] iter=95 timed out (futex.node=1) > > > > Fix by making node-hint publication publish-once via atomic cmpxchg on > > naddr (FUTEX_NO_NODE -> computed node), retrying transient -EAGAIN, > > and adopting/validating the winner value on contention. > > > > Fixes: c042c505210d ("futex: Implement FUTEX2_MPOL") > > Link: https://gist.github.com/Ychame/d4a5e95401a471f4211a751734b5d164 > > Signed-off-by: Chengfeng Ye > > I did point out this scenario and it was said that this should not be > done this way. Initialize once and be done with it plus with mpol the > value should be consistent. Right, see tools/testing/selftests/futex/functional/futex_numa.c, that has a very simple numa lock implementation you can crib from. You can only clear the node word when you clear the waiter bit (eg, there are no more waiters left) and it must be done atomically such that any concurrent lock operation will DTRT. Specifically, futex_numa_32 requires an 64bit cmpxchg.