From patchwork Fri Apr 19 14:42:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bethany Jamison X-Patchwork-Id: 1925575 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4VLcnF37FLz23hf for ; Sat, 20 Apr 2024 00:42:41 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1rxpRj-0001nz-G9; Fri, 19 Apr 2024 14:42:35 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1rxpRc-0001ZE-9I for kernel-team@lists.ubuntu.com; Fri, 19 Apr 2024 14:42:28 +0000 Received: from mail-io1-f69.google.com (mail-io1-f69.google.com [209.85.166.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 18DFE3F16A for ; Fri, 19 Apr 2024 14:42:28 +0000 (UTC) Received: by mail-io1-f69.google.com with SMTP id ca18e2360f4ac-7d676654758so232981239f.3 for ; Fri, 19 Apr 2024 07:42:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713537747; x=1714142547; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wkdHQjuSHxcpYBYMmrc45DjzNShVr41xHl6m3zGb/d4=; b=Sk3gHy9WmXUoQ83Qf6oykoo8xN30DQbbxjqlxytXhj5pPYTynIuBwl2PtP4g7ZjyRb YaR6rMJKvaek/qhSSZGyc/KlljHPaZVqHiS+dNdXuSQG1Lfzy6yqMQwxAu6KcyO2SCh+ JCaqZUkN2XdzTMMd+B0SnUaBLAQNjeSgkAzHXxZJdCnzJNA0IiWqROPjt9VYXNUFD72Y x/gKhyPjGtqE0fDHAo2BopcSBx8GHaB8fPx2l1qiWUDQZHCBKsKLTSTHb52dyxu+96QK roMq2v80BkfI+wJqQabXA2cJDSzg4BYE/RlZ8Y29hjIkqY6rAkWjEEATWbOCxA3GJnxe xb1g== X-Gm-Message-State: AOJu0YyYeZ3ntPFJIjwiDhuFRyKQx16wU/EiFK8E3ljx/A5tZLMdT6uK bwl3igldh/YP3KecD8rRnpMzLoPA+habED5xIrx9BdgiIKMosHaJpCi0tANK9Ck4oHi856lYFjs mNgIZwh/iWVFox+n96f1CY8jKn09A0YyoettUsx0fWhzuyfRcij3nQH0rYQDoWQrIZ1l34o577Y 5hewCYao3vFdHJ X-Received: by 2002:a5d:9314:0:b0:7da:6a19:2e2c with SMTP id l20-20020a5d9314000000b007da6a192e2cmr744055ion.13.1713537746756; Fri, 19 Apr 2024 07:42:26 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFpunjVJsuV/cG5U8UtjmBqZBnP+cRNP7XsI6t8bOgV3+AAg4C1RRUXfARhwuimB+rkTWaXoA== X-Received: by 2002:a5d:9314:0:b0:7da:6a19:2e2c with SMTP id l20-20020a5d9314000000b007da6a192e2cmr744028ion.13.1713537746285; Fri, 19 Apr 2024 07:42:26 -0700 (PDT) Received: from smtp.gmail.com (104-218-69-129.dynamic.lnk.ne.allofiber.net. [104.218.69.129]) by smtp.gmail.com with ESMTPSA id i10-20020a05663813ca00b00482d033889csm1089235jaj.171.2024.04.19.07.42.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 19 Apr 2024 07:42:26 -0700 (PDT) From: Bethany Jamison To: kernel-team@lists.ubuntu.com Subject: [SRU][F][PATCH 3/3] stddef: Introduce DECLARE_FLEX_ARRAY() helper Date: Fri, 19 Apr 2024 09:42:19 -0500 Message-Id: <20240419144219.21413-8-bethany.jamison@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240419144219.21413-1-bethany.jamison@canonical.com> References: <20240419144219.21413-1-bethany.jamison@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Kees Cook 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 Cc: "Gustavo A. R. Silva" Signed-off-by: Kees Cook (backported from commit 3080ea5553cc909b000d1f1d964a9041962f2c5b) [bjamison: context conflict because upstream has defined more since Focal so I added the fix change to the appropriate spot] CVE-2024-26733 Signed-off-by: Bethany Jamison --- include/linux/stddef.h | 13 +++++++++++++ include/uapi/linux/stddef.h | 16 ++++++++++++++++ scripts/kernel-doc | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/include/linux/stddef.h b/include/linux/stddef.h index 998a4ba28eba4..6a46c4c1c1ed6 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -36,4 +36,17 @@ enum { #define offsetofend(TYPE, MEMBER) \ (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) +/** + * 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) \ + __DECLARE_FLEX_ARRAY(TYPE, NAME) + #endif diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h index ee8220f8dcf5f..30bed3db15941 100644 --- a/include/uapi/linux/stddef.h +++ b/include/uapi/linux/stddef.h @@ -4,3 +4,19 @@ #ifndef __always_inline #define __always_inline inline #endif + +/** + * __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[]; \ + } diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 81dc91760b237..80fec06820a27 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1085,7 +1085,8 @@ sub dump_struct($$) { $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; # replace DECLARE_KFIFO_PTR $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos; - + # replace DECLARE_FLEX_ARRAY + $members =~ s/(?:__)?DECLARE_FLEX_ARRAY\s*\($args,\s*$args\)/$1 $2\[\]/gos; my $declaration = $members; # Split nested struct/union elements as newer ones