Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp3178846imw; Mon, 11 Jul 2022 03:39:55 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tpvG09JMaTzmhoY60Ira4YdaurnmMOZfVmERVoxJuPSeo7NsfzOwDj7YzcmK+mPMCm/NfR X-Received: by 2002:a17:907:ea5:b0:726:2c1c:312f with SMTP id ho37-20020a1709070ea500b007262c1c312fmr17714084ejc.248.1657535995493; Mon, 11 Jul 2022 03:39:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657535995; cv=none; d=google.com; s=arc-20160816; b=HbKfPl5KpTSmhj+PEpd0n06n/wi2F+R/hdVa7GivjS6X6TfJv2vjlyd8TBF3U9uJYN /XYWerWwiqlSLyDV1cFSXjsDBqdSnXjfFiK4IJGjw7n2Bjs84nkCMvTOCrHmPWLxUt0j 3EQs2khPuzEmvIh7J9TtVsa9JAvbN1Oh/4XPkNeQNh6F4G7HQf8Zfr2pRdnfTCaFj7cO k9xMgk58ozufAtAojLy6vILMO6DtWEygKqi161XbbmzbLgTRWjz9eaoVRpFH8ezju11V ZRm52rT76zgNUtr+wTSYNB3wCzHn3ogF4vCn63Mn9Sr424hNZar2b9q+oo0+7rF0kn12 HhBg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=UAeuKpu+aWNUCqp07XFIObJKqqKIwcaqYR3KUfST6Uk=; b=jROAQTdxzm7zjfw8QAc1ScpK/e4eLtfn8HcPtS9k1rJA2acIfAi9IUruBqGv+tkNnt QhEx7vSDmmRiBqRChk9bniOjHqfCTfop+dGnv6dMJbq4Z+CjKTyNmlpt6gCAt7HLhQ5G UGJk2W0Ob1AWsVPNyh6jtQUB3wODjthsSdiUpUcEcwe1GPwx/6ZwvT/MWlkgS9Eord4C i0OcN1KraCOxqG/6gTAQvJN9BMf2SX2RtZBVzvFax7OiRy0xUq8ti4/J8fObKGkEcQDy mf8SYWicQCwuaRfGVcbK0C4k2RkkmHr9pdZzpB6dD7BqkoZM3o6T7MqyESZiZKvxoRiz svRw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=GPnwAFAc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id hr30-20020a1709073f9e00b0072b6504d411si1407151ejc.852.2022.07.11.03.39.30; Mon, 11 Jul 2022 03:39:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=GPnwAFAc; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233496AbiGKJuq (ORCPT + 99 others); Mon, 11 Jul 2022 05:50:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233928AbiGKJtf (ORCPT ); Mon, 11 Jul 2022 05:49:35 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2738E4B0CB; Mon, 11 Jul 2022 02:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2C710612B7; Mon, 11 Jul 2022 09:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B718C34115; Mon, 11 Jul 2022 09:24:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1657531457; bh=SHtzspCuhbnM1/YWBdJUS3Fsa20mVhf+ATOcOxMdMA4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GPnwAFAchAtVt85Lu6VC32sb9xPwnzia/rg/u5uYNw0XSlTCjtrdKXKJcVrutsHLC ULihrM6CENp0zex0h2siDkuDqGFSMv5F2OM6xGGTmZux09J7xtgTq3FTjUDYDJQ1q/ 44C7zkpEwnsDxMAdTbsW4XdsrkDqYM/Fi4t6XsMM= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Arnd Bergmann , "Gustavo A. R. Silva" , Kees Cook , Sasha Levin Subject: [PATCH 5.15 112/230] stddef: Introduce DECLARE_FLEX_ARRAY() helper Date: Mon, 11 Jul 2022 11:06:08 +0200 Message-Id: <20220711090607.243974627@linuxfoundation.org> X-Mailer: git-send-email 2.37.0 In-Reply-To: <20220711090604.055883544@linuxfoundation.org> References: <20220711090604.055883544@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kees Cook [ Upstream commit 3080ea5553cc909b000d1f1d964a9041962f2c5b ] 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 Signed-off-by: Sasha Levin --- include/linux/stddef.h | 13 +++++++++++++ include/uapi/linux/stddef.h | 16 ++++++++++++++++ scripts/kernel-doc | 2 ++ 3 files changed, 31 insertions(+) diff --git a/include/linux/stddef.h b/include/linux/stddef.h index 938216f8ab7e..31fdbb784c24 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -84,4 +84,17 @@ enum { #define struct_group_tagged(TAG, NAME, MEMBERS...) \ __struct_group(TAG, NAME, /* no attrs */, MEMBERS) +/** + * 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 610204f7c275..3021ea25a284 100644 --- a/include/uapi/linux/stddef.h +++ b/include/uapi/linux/stddef.h @@ -25,3 +25,19 @@ struct { MEMBERS } ATTRS; \ struct TAG { MEMBERS } ATTRS NAME; \ } + +/** + * __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 38aa799a776c..5d54b57ff90c 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1263,6 +1263,8 @@ sub dump_struct($$) { $members =~ s/DECLARE_KFIFO\s*\($args,\s*$args,\s*$args\)/$2 \*$1/gos; # replace DECLARE_KFIFO_PTR $members =~ s/DECLARE_KFIFO_PTR\s*\($args,\s*$args\)/$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 -- 2.35.1