asm-generic: avoid sparse {get,put}_unaligned warning

Started by Sven Eckelmann on Jul 24, 2021 · 6 messages from 4 authors · Last reply Jul 27, 2021

Subsystems (2)

Maintainers (2)

STALE1931d

open the first message on its own page

Message details and related content
Sparse will try to check casting of simple integer types which are marked
as __bitwise. This for example "disallows" simple casting of __be{16,32,64}
or __le{16,32,64} to other types. This is also true for pointers to
variables with this type.

But the new generic {get,put}_unaligned is doing that by (reinterpret)
casting the original pointer to a new (anonymous) struct pointer. This will
then create warnings like:

  net/batman-adv/distributed-arp-table.c:1461:19: warning: cast from restricted __be32 *
  net/batman-adv/distributed-arp-table.c:1510:23: warning: cast from restricted __be32 [usertype] *[assigned] magic
  net/batman-adv/distributed-arp-table.c:1588:24: warning: cast from restricted __be32 [usertype] *[assigned] yiaddr

The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.

Fixes: 803f4e1eab7a ("asm-generic: simplify asm/unaligned.h")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 include/asm-generic/unaligned.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 1c4242416c9f..e2b23e5bf945 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -10,12 +10,13 @@
 #include <asm/byteorder.h>
 
 #define __get_unaligned_t(type, ptr) ({						\
-	const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);	\
+	const struct { type x; } __packed *__pptr;				\
+	__pptr = (__force typeof(__pptr))(ptr);					\
 	__pptr->x;								\
 })
 
 #define __put_unaligned_t(type, val, ptr) do {					\
-	struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);		\
+	struct { type x; } __packed *__pptr = (__force typeof(__pptr))(ptr);	\
 	__pptr->x = (val);							\
 } while (0)
 
-- 
2.30.2
Message details and related content
On Sat, Jul 24, 2021 at 06:24:29PM +0200, Sven Eckelmann wrote:
The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.
	How about container_of(ptr, typeof(*__pptr), x) instead of a cast?
Would be easier to follow...
Message details and related content
On Sat, Jul 24, 2021 at 7:01 PM Al Viro [off-list ref] wrote:
On Sat, Jul 24, 2021 at 06:24:29PM +0200, Sven Eckelmann wrote:
quoted
The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.
I can see why this would warn, but I'm having trouble reproducing the
warning on linux-next.
        How about container_of(ptr, typeof(*__pptr), x) instead of a cast?
Would be easier to follow...
If both work equally well, I'd prefer Sven's patch since that only
expands 'type'
once, while container_of() expands it three more times. This may not make
much of a difference, but I've seen a number of cases where nested macros
can explode the preprocessed code size enough to slow down kernel compilation
over all, and it's quite possible to have get_unaligned()/put_unaligned in
the middle of that, with a complex expression passed into that.

      Arnd
Message details and related content
On Monday, 26 July 2021 14:57:31 CEST Arnd Bergmann wrote:
quoted
quoted
The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.
I can see why this would warn, but I'm having trouble reproducing the
warning on linux-next.
I have sparse 0.6.3 on an Debian bullseye amd64 system. Sources are from 
linux-next next-20210723

    make allnoconfig
    cat >> .config << "EOF"
    CONFIG_NET=y
    CONFIG_INET=y
    CONFIG_BATMAN_ADV=y
    CONFIG_BATMAN_ADV_DAT=y
    EOF
    make olddefconfig
    make CHECK="sparse -Wbitwise-pointer" C=1

I should maybe have made this clearer in the last sentence of the first 
paragraph: "This is also true for pointers to variables with this type when
-Wbitwise-pointer is activated."

Kind regards,
	Sven
Message details and related content
On Mon, Jul 26, 2021 at 5:04 PM Sven Eckelmann [off-list ref] wrote:
On Monday, 26 July 2021 14:57:31 CEST Arnd Bergmann wrote:
quoted
quoted
quoted
The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.
I can see why this would warn, but I'm having trouble reproducing the
warning on linux-next.
I have sparse 0.6.3 on an Debian bullseye amd64 system. Sources are from
linux-next next-20210723

    make allnoconfig
    cat >> .config << "EOF"
    CONFIG_NET=y
    CONFIG_INET=y
    CONFIG_BATMAN_ADV=y
    CONFIG_BATMAN_ADV_DAT=y
    EOF
    make olddefconfig
    make CHECK="sparse -Wbitwise-pointer" C=1

I should maybe have made this clearer in the last sentence of the first
paragraph: "This is also true for pointers to variables with this type when
-Wbitwise-pointer is activated."
Ok, got it. I assumed this would be turned on by an 'allmodconfig' build.
quoted
If both work equally well, I'd prefer Sven's patch since that only
expands 'type' once, while container_of() expands it three more times
Not sure what I was thinking here, as it's not 'type' that gets expanded
here but 'ptr'. We could do Al's suggestion to avoid the __force without
multiple expansions, using
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 1c4242416c9f..d138dc5fd8e3 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -10,17 +10,25 @@
 #include <asm/byteorder.h>

 #define __get_unaligned_t(type, ptr) ({
                 \
-       const struct { type x; } __packed *__pptr =
(typeof(__pptr))(ptr);      \
+       const struct { type x; } __packed *__pptr =
         \
+                               container_of(ptr, typeof(*__pptr), x);
         \
        __pptr->x;
         \
 })

 #define __put_unaligned_t(type, val, ptr) do {
         \
-       struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);
         \
+       struct { type x; } __packed *__pptr =
         \
+                               container_of(ptr, typeof(*__pptr), x);
         \
        __pptr->x = (val);
         \
 } while (0)

-#define get_unaligned(ptr)     __get_unaligned_t(typeof(*(ptr)), (ptr))
-#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr))
+#define get_unaligned(ptr)     ({
         \
+       __auto_type _ptr = (ptr);
         \
+       __get_unaligned_t(typeof(*(_ptr)), (_ptr));
         \
+})
+#define put_unaligned(val, ptr)        ({
                 \
+       __auto_type _ptr = (ptr);
         \
+       __put_unaligned_t(typeof(*(_ptr)), (val), (_ptr));
         \
+})

 static inline u16 get_unaligned_le16(const void *p)
 {

4 more lines

Message details and related content
From: Sven Eckelmann
Sent: 24 July 2021 17:24

Sparse will try to check casting of simple integer types which are marked
as __bitwise. This for example "disallows" simple casting of __be{16,32,64}
or __le{16,32,64} to other types. This is also true for pointers to
variables with this type.

But the new generic {get,put}_unaligned is doing that by (reinterpret)
casting the original pointer to a new (anonymous) struct pointer. This will
then create warnings like:

  net/batman-adv/distributed-arp-table.c:1461:19: warning: cast from restricted __be32 *
  net/batman-adv/distributed-arp-table.c:1510:23: warning: cast from restricted __be32 [usertype]
*[assigned] magic
  net/batman-adv/distributed-arp-table.c:1588:24: warning: cast from restricted __be32 [usertype]
*[assigned] yiaddr

The special attribute force must be used in such statements when the cast
is known to be safe to avoid these warnings.
At least the __force is being added to an existing cast.

The real problems are when a (__force __le32)value cast is used
to silence sparse.
These should really be something like:
	__tell_sparce(__le32, value)
so that the whole thing can be removed by the preprocessor when
compiling the code.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help