Skip to content

CNB: stddef: Introduce DECLARE_FLEX_ARRAY() helper

Josef Oškera requested to merge joskera/centos-stream-9:bz2069567 into main

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2069567

Tested: Sanity only, new unused macros

commit 3080ea5553cc909b000d1f1d964a9041962f2c5b
Author: Kees Cook <keescook@chromium.org>
Date:   Mon Aug 9 11:21:23 2021 -0700

    stddef: Introduce DECLARE_FLEX_ARRAY() helper

    There are many places where kernel code wants to have several different
    typed trailing flexible arrays. This would normally be done with multiple
    flexible arrays in a union, but since GCC and Clang don't (on the surface)
    allow this, there have been many open-coded workarounds, usually involving
    neighboring 0-element arrays at the end of a structure. For example,
    instead of something like this:

    struct thing {
            ...
            union {
                    struct type1 foo[];
                    struct type2 bar[];
            };
    };

    code works around the compiler with:

    struct thing {
            ...
            struct type1 foo[0];
            struct type2 bar[];
    };

    Another case is when a flexible array is wanted as the single member
    within a struct (which itself is usually in a union). For example, this
    would be worked around as:

    union many {
            ...
            struct {
                    struct type3 baz[0];
            };
    };

    These kinds of work-arounds cause problems with size checks against such
    zero-element arrays (for example when building with -Warray-bounds and
    -Wzero-length-bounds, and with the coming FORTIFY_SOURCE improvements),
    so they must all be converted to "real" flexible arrays, avoiding warnings
    like this:

    fs/hpfs/anode.c: In function 'hpfs_add_sector_to_btree':
    fs/hpfs/anode.c:209:27: warning: array subscript 0 is outside the bounds of an interior zero-length array 'struct bplus_internal_node[0]' [-Wzero-length-bounds]
      209 |    anode->btree.u.internal[0].down = cpu_to_le32(a);
          |    ~~~~~~~~~~~~~~~~~~~~~~~^~~
    In file included from fs/hpfs/hpfs_fn.h:26,
                     from fs/hpfs/anode.c:10:
    fs/hpfs/hpfs.h:412:32: note: while referencing 'internal'
      412 |     struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
          |                                ^~~~~~~~

    drivers/net/can/usb/etas_es58x/es58x_fd.c: In function 'es58x_fd_tx_can_msg':
    drivers/net/can/usb/etas_es58x/es58x_fd.c:360:35: warning: array subscript 65535 is outside the bounds of an interior zero-length array 'u8[0]' {aka 'unsigned char[]'} [-Wzero-length-bounds]
      360 |  tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len];
          |                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from drivers/net/can/usb/etas_es58x/es58x_core.h:22,
                     from drivers/net/can/usb/etas_es58x/es58x_fd.c:17:
    drivers/net/can/usb/etas_es58x/es58x_fd.h:231:6: note: while referencing 'raw_msg'
      231 |   u8 raw_msg[0];
          |      ^~~~~~~

    However, it _is_ entirely possible to have one or more flexible arrays
    in a struct or union: it just has to be in another struct. And since it
    cannot be alone in a struct, such a struct must have at least 1 other
    named member -- but that member can be zero sized. Wrap all this nonsense
    into the new DECLARE_FLEX_ARRAY() in support of having flexible arrays
    in unions (or alone in a struct).

    As with struct_group(), since this is needed in UAPI headers as well,
    implement the core there, with a non-UAPI wrapper.

    Additionally update kernel-doc to understand its existence.

    https://github.com/KSPP/linux/issues/137

    Cc: Arnd Bergmann <arnd@arndb.de>
    Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
    Signed-off-by: Kees Cook <keescook@chromium.org>

Signed-off-by: Josef Oskera joskera@redhat.com

Edited by Josef Oškera

Merge request reports