Subject: [PATCH] UAPI: net/sched: Open-code __struct_group() in flex struct tc_u32_sel

From: Kees Cook <[email-masked]>
Date: Mon, 16 Dec 2024 18:59:55 -0800

This switches to using a manually constructed form of struct tagging
to avoid issues with C++ being unable to parse tagged structs within
anonymous unions, even under 'extern "C"':

  ../linux/include/uapi/linux/pkt_cls.h:25124: error: ‘struct tc_u32_sel::<unnamed union>::tc_u32_sel_hdr,’ invalid; an anonymous union may only have public non-static data members [-fpermissive]

To avoid having multiple struct member lists, use a define to declare
them.

Reported-by: [email-masked]
Closes: https://lore.kernel.org/linux-hardening/[email-masked]/
Fixes: 216203bdc228 ("UAPI: net/sched: Use __struct_group() in flex struct tc_u32_sel")
Link: https://lore.kernel.org/r/202412120927.943DFEDD@keescook
Signed-off-by: Kees Cook <[email-masked]>
---
Cc: Jakub Kicinski <[email-masked]>
Cc: Jamal Hadi Salim <[email-masked]>
Cc: Cong Wang <[email-masked]>
Cc: Jiri Pirko <[email-masked]>
Cc: [email-masked]
---
 include/uapi/linux/pkt_cls.h | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 2c32080416b5..02aee6ed6bf0 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -245,20 +245,28 @@ struct tc_u32_key {
 	int		offmask;
 };
 
+#define tc_u32_sel_hdr_members			\
+	unsigned char		flags;		\
+	unsigned char		offshift;	\
+	unsigned char		nkeys;		\
+	__be16			offmask;	\
+	__u16			off;		\
+	short			offoff;		\
+	short			hoff;		\
+	__be32			hmask
+
+struct tc_u32_sel_hdr {
+	tc_u32_sel_hdr_members;
+};
+
 struct tc_u32_sel {
-	/* New members MUST be added within the __struct_group() macro below. */
-	__struct_group(tc_u32_sel_hdr, hdr, /* no attrs */,
-		unsigned char		flags;
-		unsigned char		offshift;
-		unsigned char		nkeys;
-
-		__be16			offmask;
-		__u16			off;
-		short			offoff;
-
-		short			hoff;
-		__be32			hmask;
-	);
+	/* Open-coded struct_group() to avoid C++ errors. */
+	union {
+		struct tc_u32_sel_hdr hdr;
+		struct {
+			tc_u32_sel_hdr_members;
+		};
+	};
 	struct tc_u32_key	keys[];
 };
 
-- 
2.34.1