Re: [PATCH 1/2] scsi: bsg: fix TOCTOU in io_uring passthrough command setup

Yang Xiuwei <[email protected]> Sat, 25 Jul 2026 11:24:11 +0800
Newsgroups org.kernel.vger.io-uring,org.kernel.vger.linux-scsi,org.kernel.vger.stable
Message-ID <[email protected]>
Hi Caleb,

On Fri, Jul 24, 2026 at 08:43:42AM -0700, Caleb Sander Mateos wrote:
> On Thu, Jul 23, 2026 at 7:03 PM Yang Xiuwei <[email protected]> wrote:
> >
> > Hi Caleb,
> >
> > On Thu, Jul 23, 2026 at 06:10:27PM -0700, Caleb Sander Mateos wrote:
> > > On Thu, Jul 23, 2026 at 5:50 PM Yang Xiuwei <[email protected]> wrote:
> > > >
> > > > max_response_len is similar here: we clamp with
> > > > min(..., SCSI_SENSE_BUFFERSIZE), so it cannot overflow the sense
> > > > buffer. Same idea for response.
> > >
> > > I don't think that's true. Without READ_ONCE(), the compiler can
> > > assume no other thread will concurrently write cmd->max_response_len
> > > (else it would be UB). So it's allowed to load it multiple times:
> > > cmd->max_response_len ? min(cmd->max_response_len, SCSI_SENSE_BUFFERSIZE)
> > >                       : SCSI_SENSE_BUFFERSIZE
> > > becomes
> > > cmd->max_response_len ? (cmd->max_response_len < SCSI_SENSE_BUFFERSIZE ?
> > >                          cmd->max_response_len : SCSI_SENSE_BUFFERSIZE)
> > >                       : SCSI_SENSE_BUFFERSIZE
> > > And if cmd->max_response_len changes between the second and third
> > > loads, this could definitely evaluate to a value greater than
> > > SCSI_SENSE_BUFFERSIZE.
> >
> > IIUC Kernel min() is __careful_cmp() -> __careful_cmp_once(), which does:
> >
> >   auto ux = (x); auto uy = (y);
> >   (ux < uy) ? ux : uy;
> >
> > so cmd->max_response_len is only loaded once inside min(). The outer
> > ?: may load it again for the condition, but the value coming out of
> > min() should still be <= SCSI_SENSE_BUFFERSIZE. Did I get that right?
>
> Without READ_ONCE(), there is no requirement that
> cmd->max_response_len only be loaded once. The compiler is allowed to
> assume the value won't be modified concurrently by another thread
> (that would be a data race, undefined behavior). So it's free to
> combine or separate the loads. If you want to ensure that the value
> read from cmd->max_response_len is consistent, READ_ONCE() is
> required.

Right —  I'll add READ_ONCE() for max_response_len in the next revision.

Thanks,
Yang Xiuwei