Patch "stddef: Introduce struct_group() helper macro" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    stddef: Introduce struct_group() helper macro

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     stddef-introduce-struct_group-helper-macro.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 3ce381dd279808d9bd2fac5f4e57f9ccaa5b665b
Author: Kees Cook <keescook@xxxxxxxxxxxx>
Date:   Mon May 17 20:01:15 2021 -0700

    stddef: Introduce struct_group() helper macro
    
    [ Upstream commit 50d7bd38c3aafc4749e05e8d7fcb616979143602 ]
    
    Kernel code has a regular need to describe groups of members within a
    structure usually when they need to be copied or initialized separately
    from the rest of the surrounding structure. The generally accepted design
    pattern in C is to use a named sub-struct:
    
            struct foo {
                    int one;
                    struct {
                            int two;
                            int three, four;
                    } thing;
                    int five;
            };
    
    This would allow for traditional references and sizing:
    
            memcpy(&dst.thing, &src.thing, sizeof(dst.thing));
    
    However, doing this would mean that referencing struct members enclosed
    by such named structs would always require including the sub-struct name
    in identifiers:
    
            do_something(dst.thing.three);
    
    This has tended to be quite inflexible, especially when such groupings
    need to be added to established code which causes huge naming churn.
    Three workarounds exist in the kernel for this problem, and each have
    other negative properties.
    
    To avoid the naming churn, there is a design pattern of adding macro
    aliases for the named struct:
    
            #define f_three thing.three
    
    This ends up polluting the global namespace, and makes it difficult to
    search for identifiers.
    
    Another common work-around in kernel code avoids the pollution by avoiding
    the named struct entirely, instead identifying the group's boundaries using
    either a pair of empty anonymous structs of a pair of zero-element arrays:
    
            struct foo {
                    int one;
                    struct { } start;
                    int two;
                    int three, four;
                    struct { } finish;
                    int five;
            };
    
            struct foo {
                    int one;
                    int start[0];
                    int two;
                    int three, four;
                    int finish[0];
                    int five;
            };
    
    This allows code to avoid needing to use a sub-struct named for member
    references within the surrounding structure, but loses the benefits of
    being able to actually use such a struct, making it rather fragile. Using
    these requires open-coded calculation of sizes and offsets. The efforts
    made to avoid common mistakes include lots of comments, or adding various
    BUILD_BUG_ON()s. Such code is left with no way for the compiler to reason
    about the boundaries (e.g. the "start" object looks like it's 0 bytes
    in length), making bounds checking depend on open-coded calculations:
    
            if (length > offsetof(struct foo, finish) -
                         offsetof(struct foo, start))
                    return -EINVAL;
            memcpy(&dst.start, &src.start, offsetof(struct foo, finish) -
                                           offsetof(struct foo, start));
    
    However, the vast majority of places in the kernel that operate on
    groups of members do so without any identification of the grouping,
    relying either on comments or implicit knowledge of the struct contents,
    which is even harder for the compiler to reason about, and results in
    even more fragile manual sizing, usually depending on member locations
    outside of the region (e.g. to copy "two" and "three", use the start of
    "four" to find the size):
    
            BUILD_BUG_ON((offsetof(struct foo, four) <
                          offsetof(struct foo, two)) ||
                         (offsetof(struct foo, four) <
                          offsetof(struct foo, three));
            if (length > offsetof(struct foo, four) -
                         offsetof(struct foo, two))
                    return -EINVAL;
            memcpy(&dst.two, &src.two, length);
    
    In order to have a regular programmatic way to describe a struct
    region that can be used for references and sizing, can be examined for
    bounds checking, avoids forcing the use of intermediate identifiers,
    and avoids polluting the global namespace, introduce the struct_group()
    macro. This macro wraps the member declarations to create an anonymous
    union of an anonymous struct (no intermediate name) and a named struct
    (for references and sizing):
    
            struct foo {
                    int one;
                    struct_group(thing,
                            int two;
                            int three, four;
                    );
                    int five;
            };
    
            if (length > sizeof(src.thing))
                    return -EINVAL;
            memcpy(&dst.thing, &src.thing, length);
            do_something(dst.three);
    
    There are some rare cases where the resulting struct_group() needs
    attributes added, so struct_group_attr() is also introduced to allow
    for specifying struct attributes (e.g. __align(x) or __packed).
    Additionally, there are places where such declarations would like to
    have the struct be tagged, so struct_group_tagged() is added.
    
    Given there is a need for a handful of UAPI uses too, the underlying
    __struct_group() macro has been defined in UAPI so it can be used there
    too.
    
    To avoid confusing scripts/kernel-doc, hide the macro from its struct
    parsing.
    
    Co-developed-by: Keith Packard <keithp@xxxxxxxxxx>
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>
    Acked-by: Gustavo A. R. Silva <gustavoars@xxxxxxxxxx>
    Link: https://lore.kernel.org/lkml/20210728023217.GC35706@embeddedor
    Enhanced-by: Rasmus Villemoes <linux@xxxxxxxxxxxxxxxxxx>
    Link: https://lore.kernel.org/lkml/41183a98-bdb9-4ad6-7eab-5a7292a6df84@xxxxxxxxxxxxxxxxxx
    Enhanced-by: Dan Williams <dan.j.williams@xxxxxxxxx>
    Link: https://lore.kernel.org/lkml/1d9a2e6df2a9a35b2cdd50a9a68cac5991e7e5f0.camel@xxxxxxxxx
    Enhanced-by: Daniel Vetter <daniel.vetter@xxxxxxxx>
    Link: https://lore.kernel.org/lkml/YQKa76A6XuFqgM03@phenom.ffwll.local
    Acked-by: Dan Williams <dan.j.williams@xxxxxxxxx>
    Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
    Stable-dep-of: 58e0be1ef611 ("net: use struct_group to copy ip/ipv6 header addresses")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 998a4ba28eba..938216f8ab7e 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -36,4 +36,52 @@ enum {
 #define offsetofend(TYPE, MEMBER) \
 	(offsetof(TYPE, MEMBER)	+ sizeof_field(TYPE, MEMBER))
 
+/**
+ * struct_group() - Wrap a set of declarations in a mirrored struct
+ *
+ * @NAME: The identifier name of the mirrored sub-struct
+ * @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 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.
+ */
+#define struct_group(NAME, MEMBERS...)	\
+	__struct_group(/* no tag */, NAME, /* no attrs */, MEMBERS)
+
+/**
+ * struct_group_attr() - Create a struct_group() with trailing attributes
+ *
+ * @NAME: The identifier name of the mirrored sub-struct
+ * @ATTRS: Any struct attributes to apply
+ * @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 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. Includes structure attributes argument.
+ */
+#define struct_group_attr(NAME, ATTRS, MEMBERS...) \
+	__struct_group(/* no tag */, NAME, ATTRS, MEMBERS)
+
+/**
+ * struct_group_tagged() - Create a struct_group with a reusable tag
+ *
+ * @TAG: The tag name for the named sub-struct
+ * @NAME: The identifier name of the mirrored sub-struct
+ * @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 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. Includes struct tag argument for the named copy,
+ * so the specified layout can be reused later.
+ */
+#define struct_group_tagged(TAG, NAME, MEMBERS...) \
+	__struct_group(TAG, NAME, /* no attrs */, MEMBERS)
+
 #endif
diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h
index ee8220f8dcf5..610204f7c275 100644
--- a/include/uapi/linux/stddef.h
+++ b/include/uapi/linux/stddef.h
@@ -4,3 +4,24 @@
 #ifndef __always_inline
 #define __always_inline inline
 #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, as well
+ * as both having struct attributes appended.
+ */
+#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
+	union { \
+		struct { MEMBERS } ATTRS; \
+		struct TAG { MEMBERS } ATTRS NAME; \
+	}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 6325bec3f66f..19af6dd160e6 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1215,6 +1215,13 @@ sub dump_struct($$) {
 	$members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos;
 	$members =~ s/\s*____cacheline_aligned_in_smp/ /gos;
 	$members =~ s/\s*____cacheline_aligned/ /gos;
+	# unwrap struct_group():
+	# - first eat non-declaration parameters and rewrite for final match
+	# - then remove macro, outer parens, and trailing semicolon
+	$members =~ s/\bstruct_group\s*\(([^,]*,)/STRUCT_GROUP(/gos;
+	$members =~ s/\bstruct_group_(attr|tagged)\s*\(([^,]*,){2}/STRUCT_GROUP(/gos;
+	$members =~ s/\b__struct_group\s*\(([^,]*,){3}/STRUCT_GROUP(/gos;
+	$members =~ s/\bSTRUCT_GROUP(\(((?:(?>[^)(]+)|(?1))*)\))[^;]*;/$2/gos;
 
 	# replace DECLARE_BITMAP
 	$members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux