Re: [PATCH 2/2] x86/uaccess: Fix casting in put_user

From: Ricardo Ribalda

Date: Wed Aug 26 2026 - 07:24:57 EST


Hi David

On Wed, 26 Aug 2026 at 11:58, David Laight <david.laight.linux@xxxxxxxxx> wrote:
>
> On Tue, 25 Aug 2026 23:15:02 +0200
> Ricardo Ribalda <ribalda@xxxxxxxxxxxx> wrote:
>
> > Hi Dave
> >
> > On Tue, 25 Aug 2026 at 23:06, Dave Hansen <dave.hansen@xxxxxxxxx> wrote:
> > >
> > > On 8/25/26 13:02, Ricardo Ribalda wrote:
> > > > Recent versions of smatch preserved the address space qualifiers with
> > > > typeof()[1].
> > > >
> > > > This fix has discovered an invalid casting in put_user.
> > > >
> > > > This patch fixes tens of smatch errors like the following:
> > > > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: warning: incorrect type in argument 2 (different address spaces)
> > > > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: expected void const *from
> > > > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: got unsigned int __user *
> > >
> > > Could we beef up the changelog here a bit, please?
> > >
> > > What _is_ the invalid casting?
> > >
> > > What is the fix?
> > >
> > > Why does it work?
> >
> > Something like this would be better? I will send a v2 if there are no
> > more comments.
> >
> >
> > Recent versions of smatch preserved the address space qualifiers with
> > typeof()[1].
> >
> > This fix has discovered an invalid casting in put_user.
> >
> > put_user is using a casting with __typeof__(*(ptr)), which keeps the
> > qualifiers (__user), instead it should use the macro TYPEOF_UNQUAL()
> > that will use __typeof_unqual__ where the compiler supports it.
> > __typeof_unqual__ copies the type but not the qualifiers.
>
> This is a spares 'bug'.
> You need to fix it without changing normal compiles.

It seems that Sparse is doing the right thing. From Dan [1]

```
The do_put_user_call() is doing this:

__typeof__(*(ptr)) __x = (x); /* eval x once */

And ptr is the __user pointer so Sparse is doing the correct thing.
We could change the __typeof__ to __typeof_unqual__
```

[1] https://lore.kernel.org/all/aS1RhxHtknHzZE3Z@stanley.mountain/

>
> There are enough put_user() calls that is will slow down compiles.

I tried a defconfig build with and without the patch to see the
impact. The build time is almost identical (the 0.6s difference in
mean time is within the standard deviation)

with the patch:
Time (mean ± σ): 69.958 s ± 1.072 s [User: 2601.772 s,
System: 386.266 s]
Range (min … max): 69.028 s … 71.517 s 5 runs

without the patch:
Time (mean ± σ): 69.326 s ± 0.718 s [User: 2552.068 s,
System: 378.156 s]
Range (min … max): 68.268 s … 70.055 s 5 runs

$ gcc --version
gcc (Debian 15.2.0-8) 15.2.0


( Benchmark: git clean -fxd; make defconfig; make -j >/tmp/out )


>
> David
>
> >
> >
> > This patch fixes tens of smatch errors like the following:
> > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: warning: incorrect type in
> > argument 2 (different address spaces)
> > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: expected void const *from
> > drivers/media/usb/uvc/uvc_v4l2.c:1112:13: got unsigned int __user *
> >
> > [1] https://github.com/error27/smatch/commit/e53027a4e816a772403baafa83c09e4a94c1cb8f
> >
> >
>


--
Ricardo Ribalda