From: Greg KH <gregkh@linuxfoundation.org>
To: Tadeusz Struk <tadeusz.struk@linaro.org>
Cc: stable@vger.kernel.org, Keith Packard <keithp@keithp.com>,
"Gustavo A . R . Silva" <gustavoars@kernel.org>,
Rasmus Villemoes <linux@rasmusvillemoes.dk>,
Dan Williams <dan.j.williams@intel.com>,
Daniel Vetter <daniel.vetter@ffwll.ch>,
Kees Cook <keescook@chromium.org>
Subject: Re: [PATCH 1/2] stddef: Introduce struct_group() helper macro
Date: Wed, 30 Mar 2022 18:37:12 +0200 [thread overview]
Message-ID: <YkSHOIOUwweHuog9@kroah.com> (raw)
In-Reply-To: <20220329220256.72283-1-tadeusz.struk@linaro.org>
On Tue, Mar 29, 2022 at 03:02:55PM -0700, Tadeusz Struk wrote:
> Please apply this to stable 5.10.y, 5.15.y
> ---8<---
>
> From: Kees Cook <keescook@chromium.org>
>
> Upstream commit: 50d7bd38c3aa ("stddef: Introduce struct_group() helper macro")
>
> 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@keithp.com>
> Signed-off-by: Keith Packard <keithp@keithp.com>
> Acked-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> Link: https://lore.kernel.org/lkml/20210728023217.GC35706@embeddedor
> Enhanced-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Link: https://lore.kernel.org/lkml/41183a98-bdb9-4ad6-7eab-5a7292a6df84@rasmusvillemoes.dk
> Enhanced-by: Dan Williams <dan.j.williams@intel.com>
> Link: https://lore.kernel.org/lkml/1d9a2e6df2a9a35b2cdd50a9a68cac5991e7e5f0.camel@intel.com
> Enhanced-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> Link: https://lore.kernel.org/lkml/YQKa76A6XuFqgM03@phenom.ffwll.local
> Acked-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
> ---
> include/linux/stddef.h | 48 +++++++++++++++++++++++++++++++++++++
> include/uapi/linux/stddef.h | 24 +++++++++++++++++++
> 2 files changed, 72 insertions(+)
Any specific reason this backport dropped a whole file from the original
commit?
You can't send me modified patches without mentioning it, otherwise I
assume you are doing something wrong :(
greg k-h
next prev parent reply other threads:[~2022-03-30 16:37 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-29 22:02 [PATCH 1/2] stddef: Introduce struct_group() helper macro Tadeusz Struk
2022-03-29 22:02 ` [PATCH 2/2] skbuff: Extract list pointers to silence compiler warnings Tadeusz Struk
2022-03-30 14:46 ` Greg KH
2022-03-30 14:59 ` Tadeusz Struk
2022-03-30 15:29 ` Greg KH
2022-03-30 15:38 ` Tadeusz Struk
2022-03-30 21:46 ` Kees Cook
2022-03-30 22:53 ` Tadeusz Struk
2022-03-30 16:37 ` Greg KH
2022-03-30 17:10 ` Tadeusz Struk
2022-03-30 16:39 ` Greg KH
2022-03-30 4:44 ` [PATCH 1/2] stddef: Introduce struct_group() helper macro Greg KH
2022-03-30 14:38 ` Tadeusz Struk
2022-03-30 14:45 ` Greg KH
2022-03-30 14:58 ` Tadeusz Struk
2022-03-30 16:37 ` Greg KH [this message]
2022-03-30 16:55 ` Tadeusz Struk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YkSHOIOUwweHuog9@kroah.com \
--to=gregkh@linuxfoundation.org \
--cc=dan.j.williams@intel.com \
--cc=daniel.vetter@ffwll.ch \
--cc=gustavoars@kernel.org \
--cc=keescook@chromium.org \
--cc=keithp@keithp.com \
--cc=linux@rasmusvillemoes.dk \
--cc=stable@vger.kernel.org \
--cc=tadeusz.struk@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.