Re: [patch V2 1/8] signal: Prevent exec() race
From: Peter Zijlstra
Date: Thu Sep 10 2026 - 09:35:49 EST
On Thu, Sep 10, 2026 at 03:21:54PM +0200, Frederic Weisbecker wrote:
> So I understand this one. Now unfortunately litmus doesn't support
> structures, but let's suppose it could. I'm taking the previous script
> and introduce a small change in P1:
>
> C MP+polocks
>
> {}
>
> P0(int *A, int *B, spinlock_t *mylock)
> {
> spin_lock(mylock);
> WRITE_ONCE(*A, 1);
> spin_unlock(mylock);
> spin_lock(mylock);
> WRITE_ONCE(*B, 1);
> spin_unlock(mylock);
> }
>
> P1(int *A, int *B)
> {
> int r0;
> int r1
>
> r0 = READ_ONCE(*B);
> spin_lock(r0->somelock)
> r1 = READ_ONCE(*A);
> spin_unlock(r0->somelock)
> }
>
> exists (1:r0=1 /\ 1:r1=0) (* Bad outcome. *)
>
>
> So instead of doing a LOAD-ACQUIRE on B, I do a plain READ but I also
> do a spin_lock right after on a data that depends on that READ. I can't
> run that on litmus but this is the same (simplified) pattern as what we
> had in this discussion and therefore I assume that it also works (ie: the
> bad outcome shouldn't happen), is that right?
>
> Would it also work if spin_lock() was just a LOAD-ACQUIRE?
Yes, see below.
> Does it mean that data dependency implies sufficient ordering such that
> a LOAD-ACQUIRE to a data that depends on B provides the same guarantees as
> a LOAD-ACQUIRE to B?
The way data dependencies work in this case is a LOAD->LOAD ordering.
The LOAD-ACQUIRE that is part of LOCK must happen after the initial
load. And then the later load is constrained by the ACQUIRE.
So LOAD(B) must resolve in order to do LOAD_ACQUIRE(B->lock.value).