Received: by 2002:a05:7412:3290:b0:fa:6e18:a558 with SMTP id ev16csp817820rdb; Fri, 26 Jan 2024 11:33:42 -0800 (PST) X-Google-Smtp-Source: AGHT+IEt0F7rW+rK8HySEztRTlJBdJF/6nExRbybeT/Dh2IEMGDOHKWPcm3kdONJQT/09kSsqdVI X-Received: by 2002:a17:902:ea0c:b0:1d8:b0f6:3514 with SMTP id s12-20020a170902ea0c00b001d8b0f63514mr25779plg.118.1706297621978; Fri, 26 Jan 2024 11:33:41 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706297621; cv=pass; d=google.com; s=arc-20160816; b=iaH0zzfWNQUHzL8e+QDk5b8BGMpXG9rhHH/1BZIZicdbVxyMkweBWz+PI9K3RLjgsK 3T2wANUUIEZQhNLmfeXITPYHtRBoM8i8exWvyMAsGs6BQ9wJB6pWGrW/Sha+04XNuHBi O8m1/SHuEbLTyz0ViKhXOrVpUQFlHaR8TEPjNT9sGM0KQ2h06Yw/4vMdqSVmhfPh0YPq 41P1hqXH+LMJj+nSv5jERXngGVKIdi9cghyy3enLkLH6DX1vY/Qqk6B+lUHI5bGMi1W2 EIT7KC6EAXxhFnQ2aSGn44MMuG1u2DY13D03U9pnRKpRvvFY/SZH78Ng76lpoGCXQgI1 5PHg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=eqI96hRzeZufW0ClV7Eu2Ltn/Oun6Dp0FoRFLWxc1ig=; fh=PQx0q8z0dSOA5a5JeDmhUSEr5hfBv+WCBgjyodEtICg=; b=lTX8qfoHUpAKV75FEgLymS0/QqRNiOFHKO+Rf/UpWXQs7OzTXm6fAafQii4Qu/TLiY uScucrNnKTY1YChDWlD9hq/ow8BaLZcydfkK/swnOmC3ISXYxBYxGIcV3SPit95tWDF6 1hzEB8As16ZlIFh4nkCfHGxw94uKFkwD15EBO28puXt4IX6Y/tMykxPec8aGUBKqLRIs BWF+wyNYNiZEr/EF46tlyU4yMocc69LTy1Bc2NA2BYxcDP3BK3NAWReVnQChLECn+D7i oFT0Llynqukbc+9vCEUZcOpTccJV3r5K9l79EL9btOagjU95OOyGVOLRrvxOul2eYl3Z 6SQw== ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=altlinux.org); spf=pass (google.com: domain of linux-kernel+bounces-40573-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-40573-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id v15-20020a1709028d8f00b001d4786a4cdcsi1569529plo.497.2024.01.26.11.33.41 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Jan 2024 11:33:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-40573-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=altlinux.org); spf=pass (google.com: domain of linux-kernel+bounces-40573-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-40573-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 0D702283C27 for ; Fri, 26 Jan 2024 19:33:08 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 457A824205; Fri, 26 Jan 2024 19:32:16 +0000 (UTC) Received: from air.basealt.ru (air.basealt.ru [194.107.17.39]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 638932375C; Fri, 26 Jan 2024 19:32:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=194.107.17.39 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706297535; cv=none; b=bj7Zt1ogeAX4LG+vGwhVOovqOYG7v2tAqBDmpGqE7z0GF9fVNqriEAp7h6ecOfZ9HsP1TLBwgVTj9FHI21TSrI50e1RpkjArOhB+WNkxEdz/6kFZjx9X2kpUQRYzApWuV5F1OgxCNB/An1K0kYfKc26gw7kVQ+v6QIsgtdlEnbQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706297535; c=relaxed/simple; bh=kBUsdBRGibggPisS6UgH+qECKvgWl3qwx3c5ZrsthAo=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Z7cjrlUYqn6WoU7/ayv/hko/KCo7O2KgbwfFkVgBuUlz823keMJKzLsRSG26/AUuXbIlkjUe9tafAVnxG7D86vr/VAHXYcuO5E/btwZndGIacC2+BYNnz6r2VnRKHSK+j/n9SH7UAX1Bc40pER3brIOyZvHf15/wpwH2tF5Ksts= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=altlinux.org; spf=pass smtp.mailfrom=altlinux.org; arc=none smtp.client-ip=194.107.17.39 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=altlinux.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=altlinux.org Received: by air.basealt.ru (Postfix, from userid 490) id 3A0182F2023E; Fri, 26 Jan 2024 19:32:10 +0000 (UTC) X-Spam-Level: Received: from altlinux.ipa.basealt.ru (unknown [178.76.204.78]) by air.basealt.ru (Postfix) with ESMTPSA id 5C7532F20238; Fri, 26 Jan 2024 19:32:05 +0000 (UTC) From: kovalev@altlinux.org To: stable@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-cifs@vger.kernel.org, samba-technical@lists.samba.org Cc: keescook@chromium.org, sfrench@samba.org, corbet@lwn.net, natechancellor@gmail.com, ndesaulniers@google.com, kovalev@altlinux.org, Arnd Bergmann , "Gustavo A. R. Silva" Subject: [PATCH 1/2] stddef: Introduce DECLARE_FLEX_ARRAY() helper Date: Fri, 26 Jan 2024 22:31:42 +0300 Message-Id: <20240126193143.245122-2-kovalev@altlinux.org> X-Mailer: git-send-email 2.33.8 In-Reply-To: <20240126193143.245122-1-kovalev@altlinux.org> References: <20240126193143.245122-1-kovalev@altlinux.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Kees Cook commit 3080ea5553cc909b000d1f1d964a9041962f2c5b upstream. 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: Vasiliy Kovalev --- 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 938216f8ab7e7c..31fdbb784c24e2 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 c3725b49226323..7837ba4fe72890 100644 --- a/include/uapi/linux/stddef.h +++ b/include/uapi/linux/stddef.h @@ -28,4 +28,20 @@ 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[]; \ + } #endif diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 19af6dd160e6b7..7a04d4c0532607 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1232,7 +1232,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 -- 2.33.8