Replace uses of "__auto_type" in arch/nios2/include/asm/uaccess.h with
"auto".
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
---
arch/nios2/include/asm/uaccess.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h
index b8299082adbe..fa9b06a7d7c6 100644
--- a/arch/nios2/include/asm/uaccess.h
+++ b/arch/nios2/include/asm/uaccess.h
@@ -172,14 +172,14 @@ do { \
#define __put_user(x, ptr) \
({ \
- __auto_type __pu_ptr = (ptr); \
+ auto __pu_ptr = (ptr); \
typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
__put_user_common(__pu_val, __pu_ptr); \
})
#define put_user(x, ptr) \
({ \
- __auto_type __pu_ptr = (ptr); \
+ auto __pu_ptr = (ptr); \
typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
access_ok(__pu_ptr, sizeof(*__pu_ptr)) ? \
__put_user_common(__pu_val, __pu_ptr) : \
--
2.50.1
On Fri, 18 Jul 2025 at 14:34, H. Peter Anvin <hpa@zytor.com> wrote: > > - __auto_type __pu_ptr = (ptr); \ > + auto __pu_ptr = (ptr); \ > typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \ Side note: I think some coccinelle (or sed) script that replaces that older form of typeof(x) Y = (typeof(x))(Z); or typeof(Z) Y = Z; with just auto Y = Z; is also worthwhile at some point. We have more of those, because that's the really traditional gcc way to do things that predates __auto_type. And the patterns are a bit more complicated, so they need care: not all of the "typeof (x) Z = Y" patterns have the same type in the assignment. So it's not the universal case, but it's the _common_ case, I think. For example, it's obviously the case in the above, where we use the exact same "typeof" on both sides, but in other uaccess.h files we also have patterns like __typeof__(*(ptr)) __x = (x); /* eval x once */ __typeof__(ptr) __ptr = (ptr); /* eval ptr once */ where that *first* case very much needs to use that "__typeof__" model, because 'x' typically does not necessarily have the same type as '*(ptr)' (and we absolutely do not want to use a cast: we want integer types to convert naturally, but we very much want warnings if somebody were to mix types wrong). But that second case obviously is exactly the "auto type" case, just written using __typeof__. Linus
On Fri, 18 Jul 2025 14:49:41 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: ... > Side note: I think some coccinelle (or sed) script that replaces that > older form of > > typeof(x) Y = (typeof(x))(Z); ... > > with just > > auto Y = Z; > > is also worthwhile at some point. That one needs to keep the typeof() - but the cast might be spurious. It could be either: typeof(x) Y = Z; or: auto Y = (typeof(x))(Z); but the latter could hide compilation errors. I'm waiting for the next 'duck shoot' (after strings) to be casts. While casts of 'buffer' to/from 'void *' are fine (and not needed), casts to/from 'integer_type *' are definitely problematic. And 'random' casts of integer values could easily hide real bugs and most just aren't needed. Although you might want the compiler to make the result of 'u64_var & 0xffu' 'unsigned int'. David
On Fri, 18 Jul 2025 14:49:41 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Fri, 18 Jul 2025 at 14:34, H. Peter Anvin <hpa@zytor.com> wrote: > > > > - __auto_type __pu_ptr = (ptr); \ > > + auto __pu_ptr = (ptr); \ > > typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \ You need to align the \ Plausibly possible by post-processing the diffs. David
On Fri, 18 Jul 2025 at 14:49, Linus Torvalds <torvalds@linux-foundation.org> wrote: > > On Fri, 18 Jul 2025 at 14:34, H. Peter Anvin <hpa@zytor.com> wrote: > > > > - __auto_type __pu_ptr = (ptr); \ > > + auto __pu_ptr = (ptr); \ > > typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \ > > But that second case obviously is exactly the "auto type" case, just > written using __typeof__. Actually, looking at it, I actually think the NIOS2 header is a bit buggy here, exactly because it should *not* have that cast to force the types the same. It's the exact same situation that on x86 is inside do_put_user_call(), and on x86 uses that __typeof__(*(ptr)) __x = (x); /* eval x once */ pattern instead: we don't want a cast, because we actually want just the implicit type conversions, and a warning if the types aren't compatible. Writing things to user space is still supposed to catch type safety issues. So having that '(typeof(*__pu_ptr))' cast of the value of '(x)' is actually wrong, because it will silently (for example) convert a pointer into a 'unsigned long' or vice versa, and __put_user() just shouldn't do that. If the user access is to a 'unsigned long __user *' location, the kernel shouldn't be writing pointers into it. Do we care? No. This is obviously nios2-specific, and the x86 version will catch any generic mis-uses where somebody would try to 'put_user()' the wrong type. And any "auto" conversion wouldn't change the bug anyway. But I thought I'd mention it since it started bothering me and I went and looked closer at that case I quoted. And while looking at this, I think we have a similar mis-feature / bug on x86 too: the unsafe_put_user() macro does exactly that cast: #define unsafe_put_user(x, ptr, label) \ __put_user_size((__typeof__(*(ptr)))(x), .. and I think that cast is wrong. I wonder if it's actively hiding some issue with unsafe_put_user(), or if I'm just missing something. Linus
On Fri, 18 Jul 2025 at 15:48, Linus Torvalds <torvalds@linux-foundation.org> wrote: > > And while looking at this, I think we have a similar mis-feature / bug > on x86 too: the unsafe_put_user() macro does exactly that cast: > > #define unsafe_put_user(x, ptr, label) \ > __put_user_size((__typeof__(*(ptr)))(x), .. > > and I think that cast is wrong. > > I wonder if it's actively hiding some issue with unsafe_put_user(), or > if I'm just missing something. ... and I decided to try to look into it by just removing the cast. And yes indeed, there's a reason for the cast - or at least it's hiding problems: arch/x86/kernel/signal_64.c:128: unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault); arch/x86/kernel/signal_64.c:188: unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault); arch/x86/kernel/signal_64.c:332: unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault); The one on line 188 at least makes some sense. The other ones are literally hiding the fact that we explicitly cast things to the wrong pointer. I suspect it's just very old historical "we have been lazy and mixing 'unsigned long' and 'pointer value'" issues. Oh well. None of these are actual *bugs*, they are more just ugly. And the cast that is hiding this ugliness might be hiding other things. Not worth the churn at least late in the release cycle, but one of those "this might be worth cleaning up some day" issues. Linus
On 2025-07-18 14:49, Linus Torvalds wrote: > > Side note: I think some coccinelle (or sed) script that replaces that > older form of > > typeof(x) Y = (typeof(x))(Z); > > or > > typeof(Z) Y = Z; > > > with just > > auto Y = Z; > > is also worthwhile at some point. > > We have more of those, because that's the really traditional gcc way > to do things that predates __auto_type. > Agreed. And I think that this, indeed is a job more for Coccinelle than for sed, because the patterns can be rather complex and we don't want false positives. -hpa
© 2016 - 2025 Red Hat, Inc.