mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00

For the most part of the C++ history, it couldn't have type
declarations inside anonymous unions for different reasons. At the
same time, __struct_group() relies on the latters, so when the @TAG
argument is not empty, C++ code doesn't want to build (even under
`extern "C"`):
../linux/include/uapi/linux/pkt_cls.h:25:24: error:
'struct tc_u32_sel::<unnamed union>::tc_u32_sel_hdr,' invalid;
an anonymous union may only have public non-static data members
[-fpermissive]
The safest way to fix this without trying to switch standards (which
is impossible in UAPI anyway) etc., is to disable tag declaration
for that language. This won't break anything since for now it's not
buildable at all.
Use a separate definition for __struct_group() when __cplusplus is
defined to mitigate the error, including the version from tools/.
Fixes: 50d7bd38c3
("stddef: Introduce struct_group() helper macro")
Reported-by: Christopher Ferris <cferris@google.com>
Closes: https://lore.kernel.org/linux-hardening/Z1HZpe3WE5As8UAz@google.com
Suggested-by: Kees Cook <kees@kernel.org> # __struct_group_tag()
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://lore.kernel.org/r/20241219135734.2130002-1-aleksander.lobakin@intel.com
Signed-off-by: Kees Cook <kees@kernel.org>
74 lines
2.1 KiB
C
74 lines
2.1 KiB
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
#ifndef _UAPI_LINUX_STDDEF_H
|
|
#define _UAPI_LINUX_STDDEF_H
|
|
|
|
#include <linux/compiler_types.h>
|
|
|
|
#ifndef __always_inline
|
|
#define __always_inline inline
|
|
#endif
|
|
|
|
/* Not all C++ standards support type declarations inside an anonymous union */
|
|
#ifndef __cplusplus
|
|
#define __struct_group_tag(TAG) TAG
|
|
#else
|
|
#define __struct_group_tag(TAG)
|
|
#endif
|
|
|
|
/**
|
|
* __struct_group() - Create a mirrored named and anonyomous struct
|
|
*
|
|
* @TAG: The tag name for the named sub-struct (usually empty)
|
|
* @NAME: The identifier name of the mirrored sub-struct
|
|
* @ATTRS: Any struct attributes (usually empty)
|
|
* @MEMBERS: The member declarations for the mirrored structs
|
|
*
|
|
* Used to create an anonymous union of two structs with identical layout
|
|
* and size: one anonymous and one named. The former's members can be used
|
|
* normally without sub-struct naming, and the latter can be used to
|
|
* reason about the start, end, and size of the group of struct members.
|
|
* The named struct can also be explicitly tagged for layer reuse (C only),
|
|
* as well as both having struct attributes appended.
|
|
*/
|
|
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
|
|
union { \
|
|
struct { MEMBERS } ATTRS; \
|
|
struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
|
|
} ATTRS
|
|
|
|
#ifdef __cplusplus
|
|
/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
|
|
#define __DECLARE_FLEX_ARRAY(T, member) \
|
|
T member[0]
|
|
#else
|
|
/**
|
|
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
|
|
*
|
|
* @TYPE: The type of each flexible array element
|
|
* @NAME: The name of the flexible array member
|
|
*
|
|
* In order to have a flexible array member in a union or alone in a
|
|
* struct, it needs to be wrapped in an anonymous struct with at least 1
|
|
* named member, but that member can be empty.
|
|
*/
|
|
#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \
|
|
struct { \
|
|
struct { } __empty_ ## NAME; \
|
|
TYPE NAME[]; \
|
|
}
|
|
#endif
|
|
|
|
#ifndef __counted_by
|
|
#define __counted_by(m)
|
|
#endif
|
|
|
|
#ifndef __counted_by_le
|
|
#define __counted_by_le(m)
|
|
#endif
|
|
|
|
#ifndef __counted_by_be
|
|
#define __counted_by_be(m)
|
|
#endif
|
|
|
|
#endif /* _UAPI_LINUX_STDDEF_H */
|