All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/32] Introduce flexible array struct memcpy() helpers
@ 2022-05-04  1:44 Kees Cook
  2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
                   ` (33 more replies)
  0 siblings, 34 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

Hi,

This is the next phase of memcpy() buffer bounds checking[1], which
starts by adding a new set of helpers to address common code patterns
that result in memcpy() usage that can't be easily verified by the
compiler (i.e. dynamic bounds due to flexible arrays). The runtime WARN
from memcpy has been posted before, but now there's more context around
alternatives for refactoring false positives, etc.

The core of this series is patches 2 (flex_array.h), 3 (flex_array
KUnit), and 4 (runtime memcpy WARN). Patch 1 is a fix to land before 4
(and I can send separately), and everything else are examples of what the
conversions look like for one of the helpers, mem_to_flex_dup(). These
will need to land via their respective trees, but they all depend on
patch 2, which I'm hoping to land in the coming merge window.

I'm happy to also point out that the conversions (patches 5+) are actually
a net reduction in lines of code:
 49 files changed, 154 insertions(+), 244 deletions(-)

Anyway, please let me know what you think. And apologies in advance
if this is spammy; the CC list got rather large due to the "treewide"
nature of the example conversions.

Also available here:
https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=flexcpy/next-20220502

-Kees

[1] https://lwn.net/Articles/864521/

Kees Cook (32):
  netlink: Avoid memcpy() across flexible array boundary
  Introduce flexible array struct memcpy() helpers
  flex_array: Add Kunit tests
  fortify: Add run-time WARN for cross-field memcpy()
  brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item
  iwlwifi: calib: Prepare to use mem_to_flex_dup()
  iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result
  iwlwifi: mvm: Use mem_to_flex_dup() with struct ieee80211_key_conf
  p54: Use mem_to_flex_dup() with struct p54_cal_database
  wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg
  nl80211: Use mem_to_flex_dup() with struct cfg80211_cqm_config
  cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies
  mac80211: Use mem_to_flex_dup() with several structs
  af_unix: Use mem_to_flex_dup() with struct unix_address
  802/garp: Use mem_to_flex_dup() with struct garp_attr
  802/mrp: Use mem_to_flex_dup() with struct mrp_attr
  net/flow_offload: Use mem_to_flex_dup() with struct flow_action_cookie
  firewire: Use __mem_to_flex_dup() with struct iso_interrupt_event
  afs: Use mem_to_flex_dup() with struct afs_acl
  ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data
  soc: qcom: apr: Use mem_to_flex_dup() with struct apr_rx_buf
  atags_proc: Use mem_to_flex_dup() with struct buffer
  Bluetooth: Use mem_to_flex_dup() with struct
    hci_op_configure_data_path
  IB/hfi1: Use mem_to_flex_dup() for struct tid_rb_node
  Drivers: hv: utils: Use mem_to_flex_dup() with struct cn_msg
  ima: Use mem_to_flex_dup() with struct modsig
  KEYS: Use mem_to_flex_dup() with struct user_key_payload
  selinux: Use mem_to_flex_dup() with xfrm and sidtab
  xtensa: Use mem_to_flex_dup() with struct property
  usb: gadget: f_fs: Use mem_to_flex_dup() with struct ffs_buffer
  xenbus: Use mem_to_flex_dup() with struct read_buffer
  esas2r: Use __mem_to_flex() with struct atto_ioctl

 arch/arm/kernel/atags_proc.c                  |  12 +-
 arch/xtensa/platforms/xtfpga/setup.c          |   9 +-
 drivers/firewire/core-cdev.c                  |   7 +-
 drivers/hv/hv_utils_transport.c               |   7 +-
 drivers/infiniband/hw/hfi1/user_exp_rcv.c     |   7 +-
 drivers/infiniband/hw/hfi1/user_exp_rcv.h     |   4 +-
 drivers/net/wireless/ath/wcn36xx/smd.c        |   8 +-
 drivers/net/wireless/ath/wcn36xx/smd.h        |   4 +-
 .../broadcom/brcm80211/brcmfmac/fweh.c        |  11 +-
 drivers/net/wireless/intel/iwlwifi/dvm/agn.h  |   2 +-
 .../net/wireless/intel/iwlwifi/dvm/calib.c    |  23 +-
 .../net/wireless/intel/iwlwifi/dvm/ucode.c    |   8 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c  |   8 +-
 drivers/net/wireless/intersil/p54/eeprom.c    |   8 +-
 drivers/net/wireless/intersil/p54/p54.h       |   4 +-
 drivers/scsi/esas2r/atioctl.h                 |   1 +
 drivers/scsi/esas2r/esas2r_ioctl.c            |  11 +-
 drivers/soc/qcom/apr.c                        |  12 +-
 drivers/usb/gadget/function/f_fs.c            |  11 +-
 drivers/xen/xenbus/xenbus_dev_frontend.c      |  12 +-
 fs/afs/internal.h                             |   4 +-
 fs/afs/xattr.c                                |   7 +-
 include/keys/user-type.h                      |   4 +-
 include/linux/flex_array.h                    | 637 ++++++++++++++++++
 include/linux/fortify-string.h                |  70 +-
 include/linux/of.h                            |   3 +-
 include/linux/string.h                        |   1 +
 include/net/af_unix.h                         |  14 +-
 include/net/bluetooth/hci.h                   |   4 +-
 include/net/cfg80211.h                        |   4 +-
 include/net/flow_offload.h                    |   4 +-
 include/net/garp.h                            |   4 +-
 include/net/mac80211.h                        |   4 +-
 include/net/mrp.h                             |   4 +-
 include/uapi/linux/connector.h                |   4 +-
 include/uapi/linux/firewire-cdev.h            |   4 +-
 include/uapi/linux/netlink.h                  |   1 +
 include/uapi/linux/stddef.h                   |  14 +
 include/uapi/linux/xfrm.h                     |   4 +-
 lib/Kconfig.debug                             |  12 +-
 lib/Makefile                                  |   1 +
 lib/flex_array_kunit.c                        | 523 ++++++++++++++
 net/802/garp.c                                |   9 +-
 net/802/mrp.c                                 |   9 +-
 net/bluetooth/hci_request.c                   |   9 +-
 net/core/flow_offload.c                       |   7 +-
 net/mac80211/cfg.c                            |  22 +-
 net/mac80211/ieee80211_i.h                    |  12 +-
 net/netlink/af_netlink.c                      |   5 +-
 net/unix/af_unix.c                            |   7 +-
 net/wireless/core.h                           |   4 +-
 net/wireless/nl80211.c                        |  15 +-
 net/wireless/scan.c                           |  21 +-
 security/integrity/ima/ima_modsig.c           |  12 +-
 security/keys/user_defined.c                  |   7 +-
 security/selinux/ss/sidtab.c                  |   9 +-
 security/selinux/xfrm.c                       |   7 +-
 sound/soc/codecs/sigmadsp.c                   |  11 +-
 58 files changed, 1409 insertions(+), 253 deletions(-)
 create mode 100644 include/linux/flex_array.h
 create mode 100644 lib/flex_array_kunit.c

-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  3:12   ` Introduce flexible array struct memcpy() helpers bluez.test.bot
  2022-05-04  3:31   ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Gustavo A. R. Silva
  2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (32 subsequent siblings)
  33 siblings, 2 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Rasmus Villemoes, David S. Miller, Jakub Kicinski,
	Rich Felker, Eric Dumazet, netdev, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

In preparation for run-time memcpy() bounds checking, split the nlmsg
copying for error messages (which crosses a previous unspecified flexible
array boundary) in half. Avoids the future run-time warning:

memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16)

Creates an explicit flexible array at the end of nlmsghdr for the payload,
named "nlmsg_payload". There is no impact on UAPI; the sizeof(struct
nlmsghdr) does not change, but now the compiler can better reason about
where things are being copied.

Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Rich Felker <dalias@aerifal.cx>
Cc: Eric Dumazet <edumazet@google.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/uapi/linux/netlink.h | 1 +
 net/netlink/af_netlink.c     | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index 855dffb4c1c3..47f9342d51bc 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -47,6 +47,7 @@ struct nlmsghdr {
 	__u16		nlmsg_flags;	/* Additional flags */
 	__u32		nlmsg_seq;	/* Sequence number */
 	__u32		nlmsg_pid;	/* Sending process port ID */
+	__u8		nlmsg_payload[];/* Contents of message */
 };
 
 /* Flags values */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1b5a9c2e1c29..09346aee1022 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2445,7 +2445,10 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
 			  NLMSG_ERROR, payload, flags);
 	errmsg = nlmsg_data(rep);
 	errmsg->error = err;
-	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
+	errmsg->msg = *nlh;
+	if (payload > sizeof(*errmsg))
+		memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload,
+		       nlh->nlmsg_len - sizeof(*nlh));
 
 	if (nlk_has_extack && extack) {
 		if (extack->_msg) {
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
  2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  7:25   ` Johannes Berg
  2022-05-04  1:44 ` [PATCH 03/32] flex_array: Add Kunit tests Kees Cook
                   ` (31 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Keith Packard, Francis Laniel, Daniel Axtens,
	Dan Williams, Vincenzo Frascino, Guenter Roeck, Daniel Vetter,
	Tadeusz Struk, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

The compiler is not able to automatically perform bounds checking
on structures that end in flexible arrays: __builtin_object_size()
is compile-time only. Any possible run-time checks are currently
short-circuited because there isn't an obvious common way to figure out
the bounds of such a structure. C has no way (yet[1]) to signify which
struct member holds the number of allocated flexible array elements
(like exists in other languages).

As a result, the kernel (and C projects generally) need to manually
check the bounds, check the element size calculations, and perform sanity
checking on all the associated variable types in between (e.g. 260
cannot be stored in a u8). This is extremely fragile.

However, even if we could do all this through a magic memcpy(), the API
itself doesn't provide meaningful feedback, which forces the kernel into
an "all or nothing" approach: either do the copy or panic the system. Any
failure conditions should be _detectable_, with API users able to
gracefully recover.

To deal with these needs, create a set of helper functions that do the
work of memcpy() but perform the needed bounds checking based on the
arguments given: flex_cpy(). The common pattern of "allocate and copy"
is also included: flex_dup(). However, one of the most common patterns
is deserialization: allocating and populating flexible array members
from a byte array: mem_to_flex_dup(). And if the elements are already
allocated: mem_to_flex().

The concept of a "flexible array structure" is introduced, which is a
struct that has both a trailing flexible array member _and_ an element
count member. If a struct lacks the element count member, it's just a
blob: there are no bounds associated with it.

The most common style of flexible array struct in the kernel is a
"normal" one, where both the flex-array and element-count are present:

    struct flex_array_struct_example {
        ...		/* arbitrary members */
        u16 part_count;	/* count of elements stored in "parts" below. */
        ...		/* arbitrary members */
        u32 parts[];	/* flexible array with elements of type u32. */
    };

Next are "encapsulating flexible array structs", which is just a struct
that contains a flexible array struct as its final member:

    struct encapsulating_example {
        ...		/* arbitrary members */
        struct flex_array_struct_example fas;
    };

There are also "split" flex array structs, which have the element-count
member in a separate struct level than the flex-array member:

    struct split_example {
        ...		/* arbitrary members */
        u16 part_count;	/* count of elements stored in "parts" below. */
        ...		/* arbitrary members */
        struct blob_example {
            ...		/* other blob members */
            u32 parts[];/* flexible array with elements of type u32. */
        } blob;
    };

To have the helpers deal with these arbitrary layouts, the names of the
flex-array and element-count members need to be specified with each use
(since C lacks the array-with-length syntax[1] so the compiler cannot
automatically determine them). However, for the "normal" (most common)
case, we can get close to "automatic" by explicitly declaring common
member aliases "__flex_array_elements", and "__flex_array_elements_count"
respectively. The regular helpers use these members, but extended helpers
exist to cover the other two code patterns.

For example, using the most complicated helper, mem_to_flex_dup():

    /* Flexible array struct with members identified. */
    struct something {
        int mode;
        DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, how_many);
        unsigned long flags;
        DECLARE_FLEX_ARRAY_ELEMENTS(u32, value);
    };
    ...
    struct something *instance = NULL;
    int rc;

    rc = mem_to_flex_dup(&instance, byte_array, count, GFP_KERNEL);
    if (rc)
        return rc;

This will:

- validate "instance" is non-NULL (no NULL dereference).
- validate "*instance" is NULL (no memory allocation resource leak).
- validate that "count" is:
  - non-negative (no arithmetic underflow).
  - has a value that can be stored in the "how_many" type (no value
    truncation).
- calculate the bytes needed to store "count"-many trailing u32 elements
  (no arithmetic overflow/underflow).
- calculate the bytes needed for a "struct something" with the above
  trailing elements (no arithmetic overflow/underflow).
- allocate the memory and check the result (no NULL dereference).
- initialize the non-flex-array portion of the struct to zero (no
  uninitialized memory usage).
- copy from "buf" into the flexible array elements.

If anything goes wrong, it returns a negative errno.

With these helpers the kernel can move away from many of the open-coded
patterns of using memcpy() with a dynamically-sized destination buffer.

[1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1990.htm

Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Keith Packard <keithp@keithp.com>
Cc: Francis Laniel <laniel_francis@privacyrequired.com>
Cc: Daniel Axtens <dja@axtens.net>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Tadeusz Struk <tadeusz.struk@linaro.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/flex_array.h  | 637 ++++++++++++++++++++++++++++++++++++
 include/linux/string.h      |   1 +
 include/uapi/linux/stddef.h |  14 +
 3 files changed, 652 insertions(+)
 create mode 100644 include/linux/flex_array.h

diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h
new file mode 100644
index 000000000000..b2cf219f7b56
--- /dev/null
+++ b/include/linux/flex_array.h
@@ -0,0 +1,637 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_FLEX_ARRAY_H_
+#define _LINUX_FLEX_ARRAY_H_
+
+#include <linux/string.h>
+/*
+ * A "flexible array structure" is a struct which ends with a flexible
+ * array _and_ contains a member that represents how many array elements
+ * are present in the flexible array structure:
+ *
+ * struct flex_array_struct_example {
+ *	...		// arbitrary members
+ *	u16 part_count;	// count of elements stored in "parts" below.
+ *	..		// arbitrary members
+ *	u32 parts[];	// flexible array with elements of type u32.
+ * };
+ *
+ * Without the "count of elements" member, a structure ending with a
+ * flexible array has no way to check its own size, and should be
+ * considered just a blob of memory that is length-checked through some
+ * other means. Kernel structures with flexible arrays should strive to
+ * always be true flexible array structures so that they can be operated
+ * on with the flex*()-family of helpers defined below.
+ *
+ * An "encapsulating flexible array structure" is a structure that contains
+ * a full "flexible array structure" as its final struct member. These are
+ * used frequently when needing to pass around a copy of a flexible array
+ * structure, and track other things about the data outside of the scope of
+ * the flexible array structure itself:
+ *
+ * struct encapsulating_example {
+ *	...		// other members
+ *	struct flex_array_struct_example fas;
+ * };
+ *
+ * For bounds checking operations on a flexible array structure, member
+ * aliases must be created so the helpers can always locate the associated
+ * members. Marking up the examples above would look like this:
+ *
+ * struct flex_array_struct_example {
+ *	...		// arbitrary members
+ *	// count of elements stored in "parts" below.
+ *	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u16, part_count);
+ *	..		// arbitrary members
+ *	// flexible array with elements of type u32.
+ *	DECLARE_FLEX_ARRAY_ELEMENTS(u32, parts);
+ * };
+ *
+ * The above creates the aliases for part_count as __flex_array_elements_count
+ * and parts as __flex_array_elements.
+ *
+ * For encapsulated flexible array structs, there are alternative helpers
+ * below where the flexible array struct member name can be explicitly
+ * included as an argument. (See the @dot_fas_member arguments below.)
+ *
+ *
+ * Examples:
+ *
+ * Using mem_to_flex():
+ *
+ *        struct single {
+ *                u32 flags;
+ *                u32 count;
+ *                u8 data[];
+ *        };
+ *        struct single *ptr_single;
+ *
+ *        struct encap {
+ *                u16 info;
+ *                struct single single;
+ *        };
+ *        struct encap *ptr_encap;
+ *
+ *        struct blob {
+ *                u32 flags;
+ *                u8 data[];
+ *        };
+ *
+ *        struct split {
+ *                u32 count;
+ *                struct blob blob;
+ *        };
+ *        struct split *ptr_split;
+ *
+ *        mem_to_flex(ptr_one, src, count);
+ *        __mem_to_flex(ptr_encap, single.data, single.count, src, count);
+ *        __mem_to_flex(ptr_split, count, blob.data, src, count);
+ *
+ */
+
+/* These are wrappers around the UAPI macros. */
+#define DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(TYPE, NAME)			\
+	__DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(TYPE, NAME)
+
+#define DECLARE_FLEX_ARRAY_ELEMENTS(TYPE, NAME)				\
+	__DECLARE_FLEX_ARRAY_ELEMENTS(TYPE, NAME)
+
+/* All the helpers return negative on failure, as must be checked. */
+static inline int __must_check __must_check_errno(int err)
+{
+	return err;
+}
+
+/**
+ * __fas_elements_bytes - Calculate potential size of the flexible
+ *			  array elements of a given flexible array
+ *			  structure.
+ *
+ * @p: Pointer to flexible array structure.
+ * @flex_member: Member name of the flexible array elements.
+ * @count_member: Member name of the flexible array elements count.
+ * @elements_count: Count of proposed number of @p->__flex_array_elements
+ * @bytes: Pointer to variable to write calculation of total size in bytes.
+ *
+ * Returns: 0 on successful calculation, -ve on error.
+ *
+ * This performs the same calculation as flex_array_size(), except
+ * that the result is bounds checked and written to @bytes instead
+ * of being returned.
+ */
+#define __fas_elements_bytes(p, flex_member, count_member,		\
+			     elements_count, bytes)			\
+__must_check_errno(({							\
+	int __feb_err = -EINVAL;					\
+	size_t __feb_elements_count = (elements_count);			\
+	size_t __feb_elements_max =					\
+		type_max(typeof((p)->count_member));			\
+	if (__feb_elements_count > __feb_elements_max ||		\
+	    check_mul_overflow(sizeof(*(p)->flex_member),		\
+			       __feb_elements_count, bytes)) {		\
+		*(bytes) = 0;						\
+		__feb_err = -E2BIG;					\
+	} else {							\
+		__feb_err = 0;						\
+	}								\
+	__feb_err;							\
+}))
+
+/**
+ * fas_elements_bytes - Calculate current size of the flexible array
+ *			elements of a given flexible array structure.
+ *
+ * @p: Pointer to flexible array structure.
+ * @bytes: Pointer to variable to write calculation of total size in bytes.
+ *
+ * Returns: 0 on successful calculation, -ve on error.
+ *
+ * This performs the same calculation as flex_array_size(), except
+ * that the result is bounds checked and written to @bytes instead
+ * of being returned.
+ */
+#define fas_elements_bytes(p, bytes)					\
+	__fas_elements_bytes(p, __flex_array_elements,			\
+			     __flex_array_elements_count,		\
+			     (p)->__flex_array_elements_count, bytes)
+
+/** __fas_bytes - Calculate potential size of flexible array structure
+ *
+ * @p: Pointer to flexible array structure.
+ * @flex_member: Member name of the flexible array elements.
+ * @count_member: Member name of the flexible array elements count.
+ * @elements_count: Count of proposed number of @p->__flex_array_elements
+ * @bytes: Pointer to variable to write calculation of total size in bytes.
+ *
+ * Returns: 0 on successful calculation, -ve on error.
+ *
+ * This performs the same calculation as struct_size(), except
+ * that the result is bounds checked and written to @bytes instead
+ * of being returned.
+ */
+#define __fas_bytes(p, flex_member, count_member, elements_count, bytes)\
+__must_check_errno(({							\
+	int __fasb_err;							\
+	typeof(*bytes) __fasb_bytes;					\
+									\
+	if (__fas_elements_bytes(p, flex_member, count_member,		\
+				 elements_count, &__fasb_bytes) ||	\
+	    check_add_overflow(sizeof(*(p)), __fasb_bytes, bytes)) {	\
+		*(bytes) = 0;						\
+		__fasb_err = -E2BIG;					\
+	} else {							\
+		__fasb_err = 0;						\
+	}								\
+	__fasb_err;							\
+}))
+
+/** fas_bytes - Calculate current size of flexible array structure
+ *
+ * @p: Pointer to flexible array structure.
+ * @bytes: Pointer to variable to write calculation of total size in bytes.
+ *
+ * This performs the same calculation as struct_size(), except
+ * that the result is bounds checked and written to @bytes instead
+ * of being returned, using the current size of the flexible array
+ * structure (via @p->__flexible_array_elements_count).
+ *
+ * Returns: 0 on successful calculation, -ve on error.
+ */
+#define fas_bytes(p, bytes)						\
+	__fas_bytes(p, __flex_array_elements,				\
+		    __flex_array_elements_count,			\
+		    (p)->__flex_array_elements_count, bytes)
+
+/** flex_cpy - Copy from one flexible array struct into another with count conversion
+ *
+ * @dst: Destination pointer
+ * @src: Source pointer
+ *
+ * The full structure of @src will be copied to @dst, including all trailing
+ * flexible array elements. @dst->__flex_array_elements_count must be large
+ * enough to hold @src->__flex_array_elements_count. Any elements left over
+ * in @dst will be zero-wiped.
+ *
+ * Returns: 0 on successful calculation, -ve on error.
+ */
+#define flex_cpy(dst, src) __must_check_errno(({			\
+	int __fc_err = -EINVAL;						\
+	typeof(*(dst)) *__fc_dst = (dst);				\
+	typeof(*(src)) *__fc_src = (src);				\
+	size_t __fc_dst_bytes, __fc_src_bytes;				\
+									\
+	BUILD_BUG_ON(!__same_type(*(__fc_dst), *(__fc_src)));		\
+									\
+	do {								\
+		if (fas_bytes(__fc_dst, &__fc_dst_bytes) ||		\
+		    fas_bytes(__fc_src, &__fc_src_bytes) ||		\
+		    __fc_dst_bytes < __fc_src_bytes) {			\
+			/* do we need to wipe dst here? */		\
+			__fc_err = -E2BIG;				\
+			break;						\
+		}							\
+		__builtin_memcpy(__fc_dst, __fc_src, __fc_src_bytes);	\
+		/* __flex_array_elements_count is included in memcpy */	\
+		/* Wipe any now-unused trailing elements in @dst: */	\
+		__builtin_memset((u8 *)__fc_dst + __fc_src_bytes, 0,	\
+				 __fc_dst_bytes - __fc_src_bytes);	\
+		__fc_err = 0;						\
+	} while (0);							\
+	__fc_err;							\
+}))
+
+/** __flex_dup - Allocate and copy an arbitrarily encapsulated flexible
+ *		 array struct
+ *
+ * @alloc: Pointer to Pointer to hold to-be-allocated (optionally
+ *	   encapsulating) flexible array struct.
+ * @dot_fas_member: For encapsulating flexible arrays, the name of the
+ *		    flexible array struct member preceded with a literal
+ *		    dot (e.g. .foo.bar.flex_array_struct_name). For a
+ *		    regular flexible array struct, this macro arument is
+ *		    empty.
+ * @src: Pointer to source flexible array struct.
+ * @gfp: GFP allocation flags
+ *
+ * This copies the contents of one flexible array struct into another.
+ * The (**@alloc)@dot_fas_member and @src arguments must resolve to the
+ * same type. Everything prior to @dot_fas_member in *@alloc will be
+ * initialized to zero.
+ *
+ * Failure modes:
+ * - @alloc is NULL.
+ * - *@alloc is not NULL (something was already allocated).
+ * - Required allocation size is larger than size_t can hold.
+ * - No available memory to allocate @alloc.
+ *
+ * Returns: 0 on success, -ve on failure.
+ */
+#define __flex_dup(alloc, dot_fas_member, src, gfp)			\
+__must_check_errno(({							\
+	int __fd_err = -EINVAL;						\
+	typeof(*(src)) *__fd_src = (src);				\
+	typeof(**(alloc)) *__fd_alloc;					\
+	typeof((*__fd_alloc)dot_fas_member) *__fd_dst;			\
+	size_t __fd_alloc_bytes, __fd_copy_bytes;			\
+									\
+	BUILD_BUG_ON(!__same_type(*(__fd_dst), *(__fd_src)));		\
+									\
+	do {								\
+		if ((uintptr_t)(alloc) < 1 || *(alloc)) {		\
+			__fd_err = -EINVAL;				\
+			break;						\
+		}							\
+		if (fas_bytes(__fd_src, &__fd_copy_bytes) ||		\
+		    check_add_overflow(__fd_copy_bytes,			\
+				       sizeof(*__fd_alloc) -		\
+					sizeof(*__fd_dst),		\
+				       &__fd_alloc_bytes)) {		\
+			__fd_err = -E2BIG;				\
+			break;						\
+		}							\
+		__fd_alloc = kmalloc(__fd_alloc_bytes, gfp);		\
+		if (!__fd_alloc) {					\
+			__fd_err = -ENOMEM;				\
+			break;						\
+		}							\
+		__fd_dst = &((*__fd_alloc)dot_fas_member);		\
+		/* Optimize away any unneeded memset. */		\
+		if (sizeof(*__fd_alloc) != sizeof(*__fd_dst))		\
+			__builtin_memset(__fd_alloc, 0,			\
+					 __fd_alloc_bytes -		\
+						__fd_copy_bytes);	\
+		__builtin_memcpy(__fd_dst, src, __fd_copy_bytes);	\
+		/* __flex_array_elements_count is included in memcpy */	\
+		*(alloc) = __fd_alloc;					\
+		__fd_err = 0;						\
+	} while (0);							\
+	__fd_err;							\
+}))
+
+/** flex_dup - Allocate and copy a flexible array struct
+ *
+ * @alloc: Pointer to Pointer to hold to-be-allocated flexible array struct.
+ * @src: Pointer to source flexible array struct.
+ * @gfp: GFP allocation flags
+ *
+ * This copies the contents of one flexible array struct into another.
+ * The *@alloc and @src arguments must resolve to the same type.
+ *
+ * Failure modes:
+ * - @alloc is NULL.
+ * - *@alloc is not NULL (something was already allocated).
+ * - Required allocation size is larger than size_t can hold.
+ * - No available memory to allocate @alloc.
+ *
+ * Returns: 0 on success, -ve on failure.
+ */
+#define flex_dup(alloc, src, gfp)					\
+	__flex_dup(alloc, /* alloc itself */, src, gfp)
+
+/** __mem_to_flex - Copy from memory buffer into a flexible array structure's
+ *		    flexible array elements.
+ *
+ * @ptr: Pointer to already allocated flexible array struct.
+ * @flex_member: Member name of the flexible array elements.
+ * @count_member: Member name of the flexible array elements count.
+ * @src: Source memory pointer.
+ * @elements_count: Number of @ptr's flexible array elements to copy from
+ *		    @src into @ptr.
+ *
+ * Copies @elements_count-many elements from memory buffer at @src into
+ * @ptr->@flex_member, wipes any remaining elements, and updates
+ * @ptr->@count_member.
+ *
+ * This is essentially a simple deserializer.
+ *
+ * TODO: It would be nice to automatically discover the max bounds of @src
+ *	 besides @elements_count. There is currently no universal way to ask
+ *	 "what is the size of a given pointer's allocation?" So for
+ *	 now just use __builtin_object_size(@src, 1) to validate known
+ *	 compile-time too-large conditions. Perhaps in the future if
+ *	 __mtf_copy_bytes above is > PAGE_SIZE, perform a dynamic lookup
+ *	 using something similar to __check_heap_object().
+ *
+ * Failure conditions:
+ * - The value of @elements_count cannot fit in the @ptr's @count_member
+ *   type (e.g. 260 in a u8).
+ * - @ptr's @count_member value is smaller than @elements_count (e.g. not
+ *   enough space was previously allocated).
+ * - @elements_count yields a byte count greater than:
+ *   - INT_MAX (as a simple "too big" sanity check)
+ *   - the compile-time size of @src (when it can be determined)
+ *
+ * Returns: 0 on success, -ve on error.
+ */
+#define __mem_to_flex(ptr, flex_member, count_member, src,		\
+		      elements_count)					\
+__must_check_errno(({							\
+	int __mtf_err = -EINVAL;					\
+	typeof(*(ptr)) *__mtf_ptr = (ptr);				\
+	typeof(elements_count) __mtf_src_count = (elements_count);	\
+	size_t __mtf_copy_bytes, __mtf_dst_bytes;			\
+	u8 *__mtf_dst = (u8 *)__mtf_ptr->flex_member;			\
+									\
+	do {								\
+		if (is_negative(__mtf_src_count) ||			\
+		    __fas_elements_bytes(__mtf_ptr, flex_member,	\
+					 count_member,			\
+					 __mtf_src_count,		\
+					 &__mtf_copy_bytes) ||		\
+		    __mtf_copy_bytes > INT_MAX ||			\
+		    __mtf_copy_bytes > __builtin_object_size(src, 1) ||	\
+		    __fas_elements_bytes(__mtf_ptr, flex_member,	\
+					 count_member,			\
+					 __mtf_ptr->count_member,	\
+					 &__mtf_dst_bytes) ||		\
+		    __mtf_dst_bytes < __mtf_copy_bytes) {		\
+			__mtf_err = -E2BIG;				\
+			break;						\
+		}							\
+		__builtin_memcpy(__mtf_dst, src, __mtf_copy_bytes);	\
+		/* Wipe any now-unused trailing elements in @dst: */	\
+		__builtin_memset(__mtf_dst + __mtf_dst_bytes, 0,	\
+				 __mtf_dst_bytes - __mtf_copy_bytes);	\
+		/* Make sure in-struct count of elements is updated: */	\
+		__mtf_ptr->count_member = __mtf_src_count;		\
+		__mtf_err = 0;						\
+	} while (0);							\
+	__mtf_err;							\
+}))
+
+#define mem_to_flex(ptr, src, elements_count)				\
+	__mem_to_flex(ptr, __flex_array_elements,			\
+		      __flex_array_elements_count, src, elements_count)
+
+/** __mem_to_flex_dup - Allocate a flexible array structure and copy into
+ *			its flexible array elements from a memory buffer.
+ *
+ * @alloc: Pointer to pointer to hold allocation for flexible array struct.
+ * @dot_fas_member: For encapsulating flexible array structs, the name of
+ *		    the flexible array struct member preceded with a
+ *		    literal dot (e.g. .foo.bar.flex_array_struct_name).
+ *		    For a regular flexible array struct, this macro arument
+ *		    is empty.
+ * @src: Source memory buffer pointer.
+ * @elements_count: Number of @alloc's flexible array elements to copy from
+ *		    @src into @ptr.
+ * @gfp: GFP allocation flags
+ *
+ * This behaves like mem_to_flex(), but allocates the needed space for
+ * a new flexible array struct and its trailing elements.
+ *
+ * This is essentially a simple allocating deserializer.
+ *
+ * TODO: It would be nice to automatically discover the max bounds of @src
+ *	 besides @elements_count. There is currently no universal way to ask
+ *	 "what is the size of a given pointer's allocation?" So for now just
+ *	 use __builtin_object_size(@src, 1) to validate known compile-time
+ *	 too-large conditions. Perhaps in the future if __mtfd_copy_bytes
+ *	 above is > PAGE_SIZE, perform a dynamic lookup using something
+ *	 similar to __check_heap_object().
+ *
+ * Failure conditions:
+ * - @alloc is NULL.
+ * - *@alloc is not NULL (something was already allocated).
+ * - The value of @elements_count cannot fit in the @alloc's
+ *   __flex_array_elements_count member type (e.g. 260 in u8).
+ * - @elements_count yields a byte count greater than:
+ *   - INT_MAX (as a simple "too big" sanity check)
+ *   - the compile-time size of @src (when it can be determined)
+ * - @alloc could not be allocated.
+ *
+ * Returns: 0 on success, -ve on error.
+ */
+#define __mem_to_flex_dup(alloc, dot_fas_member, src, elements_count,	\
+			  gfp)						\
+__must_check_errno(({							\
+	int __mtfd_err = -EINVAL;					\
+	typeof(elements_count) __mtfd_src_count = (elements_count);	\
+	typeof(**(alloc)) *__mtfd_alloc;				\
+	typeof((*__mtfd_alloc)dot_fas_member) *__mtfd_fas;		\
+	u8 *__mtfd_dst;							\
+	size_t __mtfd_alloc_bytes, __mtfd_copy_bytes;			\
+									\
+	do {								\
+		if ((uintptr_t)(alloc) < 1 || *(alloc)) {		\
+			__mtfd_err = -EINVAL;				\
+			break;						\
+		}							\
+		if (is_negative(__mtfd_src_count) ||			\
+		    __fas_elements_bytes(__mtfd_fas,			\
+					 __flex_array_elements,		\
+					 __flex_array_elements_count,	\
+					 __mtfd_src_count,		\
+					 &__mtfd_copy_bytes) ||		\
+		    __mtfd_copy_bytes > INT_MAX ||			\
+		    __mtfd_copy_bytes > __builtin_object_size(src, 1) ||\
+		    check_add_overflow(sizeof(*__mtfd_alloc),		\
+				       __mtfd_copy_bytes,		\
+				       &__mtfd_alloc_bytes)) {		\
+			__mtfd_err = -E2BIG;				\
+			break;						\
+		}							\
+		__mtfd_alloc = kmalloc(__mtfd_alloc_bytes, gfp);	\
+		if (!__mtfd_alloc) {					\
+			__mtfd_err = -ENOMEM;				\
+			break;						\
+		}							\
+		__mtfd_fas = &((*__mtfd_alloc)dot_fas_member);		\
+		__mtfd_dst = (u8 *)__mtfd_fas->__flex_array_elements;	\
+		__builtin_memset(__mtfd_alloc, 0, __mtfd_alloc_bytes -	\
+						  __mtfd_copy_bytes);	\
+		__builtin_memcpy(__mtfd_dst, src, __mtfd_copy_bytes);	\
+		/* Make sure in-struct count of elements is updated: */	\
+		__mtfd_fas->__flex_array_elements_count =		\
+						    __mtfd_src_count;	\
+		*(alloc) = __mtfd_alloc;				\
+		__mtfd_err = 0;						\
+	} while (0);							\
+	__mtfd_err;							\
+}))
+
+/** mem_to_flex_dup - Allocate a flexible array structure and copy
+ *			into it from a memory buffer.
+ *
+ * @alloc: Pointer to pointer to hold allocation for flexible array struct.
+ * @src: Source memory pointer.
+ * @elements_count: Number of @alloc's flexible array elements to copy from
+ *		   @src into @alloc.
+ * @gfp: GFP allocation flags
+ *
+ * This behaves like mem_to_flex(), but allocates the needed space for
+ * a new flexible array struct and its trailing elements.
+ *
+ * This is essentially a simple allocating deserializer.
+ *
+ * TODO: It would be nice to automatically discover the max bounds of @src
+ *	 besides @elements_count. There is currently no universal way to ask
+ *	 "what is the size of a given pointer's allocation?" So for
+ *	 now just use __builtin_object_size(@src, 1) to validate known
+ *	 compile-time too-large conditions. Perhaps in the future if
+ *	 __mtf_copy_bytes above is > PAGE_SIZE, perform a dynamic lookup
+ *	 using something similar to __check_heap_object().
+ *
+ * Failure conditions:
+ * - @alloc is NULL.
+ * - *@alloc is not NULL (something was already allocated).
+ * - The value of @elements_count cannot fit in the @alloc's
+ *   __flex_array_elements_count member type (e.g. 260 in u8).
+ * - @elements_count yields a byte count greater than:
+ *   - INT_MAX (as a simple "too big" sanity check)
+ *   - the compile-time size of @src (when it can be determined)
+ * - @alloc could not be allocated.
+ *
+ * Returns: 0 on success, -ve on error.
+ */
+#define mem_to_flex_dup(alloc, src, elements_count, gfp)		\
+	__mem_to_flex_dup(alloc, /* alloc itself */, src, elements_count, gfp)
+
+/** flex_to_mem - Copy all flexible array structure elements into memory
+ *		  buffer.
+ *
+ * @dst: Destination buffer pointer.
+ * @bytes_available: How many bytes are available in @dst.
+ * @ptr: Pointer to allocated flexible array struct.
+ * @bytes_written: Pointer to variable to store how many bytes were written
+ *		   (may be NULL).
+ *
+ * Copies all of @ptr's flexible array elements into @dst.
+ *
+ * This is essentially a simple serializer.
+ *
+ * Failure conditions:
+ * - @bytes_available in @dst is any of:
+ *   - negative.
+ *   - larger than INT_MAX.
+ *   - not large enough to hold the resulting copy.
+ * - @bytes_written's type cannot hold the size of the copy (e.g. 260 in u8).
+ *
+ * Return: 0 on success, -ve on failure.
+ *
+ */
+#define flex_to_mem(dst, bytes_available, ptr, bytes_written)		\
+__must_check_errno(({							\
+	int __ftm_err = -EINVAL;					\
+	typeof(*(ptr)) *__ftm_ptr = (ptr);				\
+	u8 *__ftm_src = (u8 *)__ftm_ptr->__flex_array_elements;		\
+	typeof(*(bytes_written)) *__ftm_written = (bytes_written);	\
+	size_t __ftm_written_max = type_max(typeof(*__ftm_written));	\
+	typeof(bytes_available) __ftm_dst_bytes = (bytes_available);	\
+	size_t __ftm_copy_bytes;					\
+									\
+	do {								\
+		if (is_negative(__ftm_dst_bytes) ||			\
+		    __ftm_dst_bytes > INT_MAX ||			\
+		    fas_elements_bytes(__ftm_ptr, &__ftm_copy_bytes) ||	\
+		    __ftm_dst_bytes < __ftm_copy_bytes ||		\
+		    (!__same_type(typeof(bytes_written), NULL) &&	\
+		     __ftm_copy_bytes > __ftm_written_max)) {		\
+			__ftm_err = -E2BIG;				\
+			break;						\
+		}							\
+		__builtin_memcpy(dst, __ftm_src, __ftm_copy_bytes);	\
+		if (__ftm_written)					\
+			*__ftm_written = __ftm_copy_bytes;		\
+		__ftm_err = 0;						\
+	} while (0);							\
+	__ftm_err;							\
+}))
+
+/** flex_to_mem_dup - Copy entire flexible array structure into newly
+ *		      allocated memory buffer.
+ *
+ * @alloc: Pointer to pointer to newly allocated memory region to hold contents
+ *	   of the copy.
+ * @alloc_size: Pointer to variable to hold the size of the allocated memory.
+ * @ptr: Pointer to allocated flexible array struct.
+ * @gfp: GFP allocation flags
+ *
+ * Allocates @alloc and copies all of @ptr's flexible array elements.
+ *
+ * This is essentially a simple allocating serializer.
+ *
+ * Failure conditions:
+ * - @alloc is NULL.
+ * - *@alloc is not NULL (something was already allocated).
+ * - @alloc_size is NULL.
+ * - @alloc_size's type cannot hold the size of the copy (e.g. 260 in u8).
+ * - @alloc could not be allocated.
+ *
+ * Return: 0 on success, -ve on failure.
+ */
+#define flex_to_mem_dup(alloc, alloc_size, ptr, gfp)			\
+__must_check_errno(({							\
+	int __ftmd_err = -EINVAL;					\
+	typeof(**(alloc)) *__ftmd_alloc;				\
+	typeof(*(alloc_size)) *__ftmd_alloc_size = (alloc_size);	\
+	typeof(*(ptr)) *__ftmd_ptr = (ptr);				\
+	u8 *__ftmd_src = (u8 *)__ftmd_ptr->__flex_array_elements;	\
+	size_t __ftmd_alloc_max = type_max(typeof(*__ftmd_alloc_size));	\
+	size_t __ftmd_copy_bytes;					\
+									\
+	do {								\
+		if ((uintptr_t)(alloc) < 1 || *(alloc) ||		\
+		    (uintptr_t)(alloc_size) < 1) {			\
+			__ftmd_err = -EINVAL;				\
+			break;						\
+		}							\
+		if (fas_elements_bytes(__ftmd_ptr,			\
+				       &__ftmd_copy_bytes) ||		\
+		    __ftmd_copy_bytes > __ftmd_alloc_max) {		\
+			__ftmd_err = -E2BIG;				\
+			break;						\
+		}							\
+		__ftmd_alloc = kmemdup(__ftmd_src, __ftmd_copy_bytes,	\
+				       gfp);				\
+		if (!__ftmd_alloc) {					\
+			__ftmd_err = -ENOMEM;				\
+			break;						\
+		}							\
+		*__ftmd_alloc_size = __ftmd_copy_bytes;			\
+		*(alloc) = __ftmd_alloc;				\
+		__ftmd_err = 0;						\
+	} while (0);							\
+	__ftmd_err;							\
+}))
+
+#endif /* _LINUX_FLEX_ARRAY_H_ */
diff --git a/include/linux/string.h b/include/linux/string.h
index b6572aeca2f5..c01b76f73e99 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -252,6 +252,7 @@ static inline const char *kbasename(const char *path)
 #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
 #include <linux/fortify-string.h>
 #endif
+#include <linux/flex_array.h>
 
 void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
 		    int pad);
diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h
index 7837ba4fe728..04870274f33b 100644
--- a/include/uapi/linux/stddef.h
+++ b/include/uapi/linux/stddef.h
@@ -44,4 +44,18 @@
 		struct { } __empty_ ## NAME; \
 		TYPE NAME[]; \
 	}
+
+/* For use with flexible array structure helpers, in <linux/flex_array.h> */
+#define __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(TYPE, NAME)			\
+	union {								\
+		TYPE __flex_array_elements_count;			\
+		TYPE NAME;						\
+	}
+
+#define __DECLARE_FLEX_ARRAY_ELEMENTS(TYPE, NAME)			\
+	union {								\
+		__DECLARE_FLEX_ARRAY(TYPE, __flex_array_elements);	\
+		__DECLARE_FLEX_ARRAY(TYPE, NAME);			\
+	}
+
 #endif
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 03/32] flex_array: Add Kunit tests
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
  2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
  2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  3:00   ` David Gow
  2022-05-04 19:58   ` Daniel Latypov
  2022-05-04  1:44 ` [PATCH 04/32] fortify: Add run-time WARN for cross-field memcpy() Kees Cook
                   ` (30 subsequent siblings)
  33 siblings, 2 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David Gow, kunit-dev, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

Add tests for the new flexible array structure helpers. These can be run
with:

  make ARCH=um mrproper
  ./tools/testing/kunit/kunit.py config
  ./tools/testing/kunit/kunit.py run flex_array

Cc: David Gow <davidgow@google.com>
Cc: kunit-dev@googlegroups.com
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 lib/Kconfig.debug      |  12 +-
 lib/Makefile           |   1 +
 lib/flex_array_kunit.c | 523 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+), 5 deletions(-)
 create mode 100644 lib/flex_array_kunit.c

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 9077bb38bc93..8bae6b169c50 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2551,11 +2551,6 @@ config OVERFLOW_KUNIT_TEST
 	  Builds unit tests for the check_*_overflow(), size_*(), allocation, and
 	  related functions.
 
-	  For more information on KUnit and unit tests in general please refer
-	  to the KUnit documentation in Documentation/dev-tools/kunit/.
-
-	  If unsure, say N.
-
 config STACKINIT_KUNIT_TEST
 	tristate "Test level of stack variable initialization" if !KUNIT_ALL_TESTS
 	depends on KUNIT
@@ -2567,6 +2562,13 @@ config STACKINIT_KUNIT_TEST
 	  CONFIG_GCC_PLUGIN_STRUCTLEAK, CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF,
 	  or CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL.
 
+config FLEX_ARRAY_KUNIT_TEST
+	tristate "Test flex_*() family of helper functions at runtime" if !KUNIT_ALL_TESTS
+	depends on KUNIT
+	default KUNIT_ALL_TESTS
+	help
+	  Builds unit tests for flexible array copy helper functions.
+
 config TEST_UDELAY
 	tristate "udelay test driver"
 	help
diff --git a/lib/Makefile b/lib/Makefile
index 6b9ffc1bd1ee..9884318db330 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -366,6 +366,7 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
 obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
 CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
 obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
+obj-$(CONFIG_FLEX_ARRAY_KUNIT_TEST) += flex_array_kunit.o
 
 obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
 
diff --git a/lib/flex_array_kunit.c b/lib/flex_array_kunit.c
new file mode 100644
index 000000000000..48bee88945b4
--- /dev/null
+++ b/lib/flex_array_kunit.c
@@ -0,0 +1,523 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for flex_*() array manipulation helpers.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <kunit/test.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/flex_array.h>
+
+#define COMPARE_STRUCTS(STRUCT_A, STRUCT_B)	do {			\
+	STRUCT_A *ptr_A;						\
+	STRUCT_B *ptr_B;						\
+	int rc;								\
+	size_t size_A, size_B;						\
+									\
+	/* matching types for flex array elements and count */		\
+	KUNIT_EXPECT_EQ(test, sizeof(*ptr_A), sizeof(*ptr_B));		\
+	KUNIT_EXPECT_TRUE(test, __same_type(*ptr_A->data,		\
+		*ptr_B->__flex_array_elements));			\
+	KUNIT_EXPECT_TRUE(test, __same_type(ptr_A->datalen,		\
+		ptr_B->__flex_array_elements_count));			\
+	KUNIT_EXPECT_EQ(test, sizeof(*ptr_A->data),			\
+			      sizeof(*ptr_B->__flex_array_elements));	\
+	KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), data),		\
+			      offsetof(typeof(*ptr_B),			\
+				       __flex_array_elements));		\
+	KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), datalen),	\
+			      offsetof(typeof(*ptr_B),			\
+				       __flex_array_elements_count));	\
+									\
+	/* struct_size() vs __fas_bytes() */				\
+	size_A = struct_size(ptr_A, data, 13);				\
+	rc = __fas_bytes(ptr_B, __flex_array_elements,			\
+			 __flex_array_elements_count, 13, &size_B);	\
+	KUNIT_EXPECT_EQ(test, rc, 0);					\
+	KUNIT_EXPECT_EQ(test, size_A, size_B);				\
+									\
+	/* flex_array_size() vs __fas_elements_bytes() */		\
+	size_A = flex_array_size(ptr_A, data, 13);			\
+	rc = __fas_elements_bytes(ptr_B, __flex_array_elements,		\
+			 __flex_array_elements_count, 13, &size_B);	\
+	KUNIT_EXPECT_EQ(test, rc, 0);					\
+	KUNIT_EXPECT_EQ(test, size_A, size_B);				\
+									\
+	KUNIT_EXPECT_EQ(test, sizeof(*ptr_A) + size_A,			\
+			      offsetof(typeof(*ptr_A), data) +		\
+			      (sizeof(*ptr_A->data) * 13));		\
+	KUNIT_EXPECT_EQ(test, sizeof(*ptr_B) + size_B,			\
+			      offsetof(typeof(*ptr_B),			\
+				       __flex_array_elements) +		\
+			      (sizeof(*ptr_B->__flex_array_elements) *	\
+			       13));					\
+} while (0)
+
+struct normal {
+	size_t	datalen;
+	u32	data[];
+};
+
+struct decl_normal {
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, datalen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u32, data);
+};
+
+struct aligned {
+	unsigned short	datalen;
+	char		data[] __aligned(__alignof__(u64));
+};
+
+struct decl_aligned {
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned short, datalen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, data) __aligned(__alignof__(u64));
+};
+
+static void struct_test(struct kunit *test)
+{
+	COMPARE_STRUCTS(struct normal, struct decl_normal);
+	COMPARE_STRUCTS(struct aligned, struct decl_aligned);
+}
+
+/* Flexible array structure with internal padding. */
+struct flex_cpy_obj {
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, count);
+	unsigned long empty;
+	char induce_padding;
+	/* padding ends up here */
+	unsigned long after_padding;
+	DECLARE_FLEX_ARRAY_ELEMENTS(u32, flex);
+};
+
+/* Encapsulating flexible array structure. */
+struct flex_dup_obj {
+	unsigned long flags;
+	int junk;
+	struct flex_cpy_obj fas;
+};
+
+/* Flexible array struct of only bytes. */
+struct tiny_flex {
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, count);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, byte_array);
+};
+
+#define CHECK_COPY(ptr)		do {						\
+	typeof(*(ptr)) *_cc_dst = (ptr);					\
+	KUNIT_EXPECT_EQ(test, _cc_dst->induce_padding, 0);			\
+	memcpy(&padding, &_cc_dst->induce_padding + sizeof(_cc_dst->induce_padding), \
+	       sizeof(padding));						\
+	/* Padding should be zero too. */					\
+	KUNIT_EXPECT_EQ(test, padding, 0);					\
+	KUNIT_EXPECT_EQ(test, src->count, _cc_dst->count);			\
+	KUNIT_EXPECT_EQ(test, _cc_dst->count, TEST_TARGET);			\
+	for (i = 0; i < _cc_dst->count - 1; i++) {				\
+		/* 'A' is 0x41, and here repeated in a u32. */			\
+		KUNIT_EXPECT_EQ(test, _cc_dst->flex[i], 0x41414141);		\
+	}									\
+	/* Last item should be different. */					\
+	KUNIT_EXPECT_EQ(test, _cc_dst->flex[_cc_dst->count - 1], 0x14141414);	\
+} while (0)
+
+/* Test copying from one flexible array struct into another. */
+static void flex_cpy_test(struct kunit *test)
+{
+#define TEST_BOUNDS	13
+#define TEST_TARGET	12
+#define TEST_SMALL	10
+	struct flex_cpy_obj *src, *dst;
+	unsigned long padding;
+	int i, rc;
+
+	/* Prepare open-coded source. */
+	src = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);
+	src->count = TEST_BOUNDS;
+	memset(src->flex, 'A', flex_array_size(src, flex, TEST_BOUNDS));
+	src->flex[src->count - 2] = 0x14141414;
+	src->flex[src->count - 1] = 0x24242424;
+
+	/* Prepare open-coded destination, alloc only. */
+	dst = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);
+	/* Pre-fill with 0xFE marker. */
+	memset(dst, 0xFE, struct_size(src, flex, TEST_BOUNDS));
+	/* Pretend we're 1 element smaller. */
+	dst->count = TEST_TARGET;
+
+	/* Pretend to match the target destination size. */
+	src->count = TEST_TARGET;
+
+	rc = flex_cpy(dst, src);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	CHECK_COPY(dst);
+	/* Item past last copied item is unchanged from initial memset. */
+	KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
+
+	/* Now trip overflow, and verify we didn't clobber beyond end. */
+	src->count = TEST_BOUNDS;
+	rc = flex_cpy(dst, src);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Item past last copied item is unchanged from initial memset. */
+	KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
+
+	/* Reset destination contents. */
+	memset(dst, 0xFD, struct_size(src, flex, TEST_BOUNDS));
+	dst->count = TEST_TARGET;
+
+	/* Copy less than max. */
+	src->count = TEST_SMALL;
+	rc = flex_cpy(dst, src);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	/* Verify count was adjusted. */
+	KUNIT_EXPECT_EQ(test, dst->count, TEST_SMALL);
+	/* Verify element beyond src size was wiped. */
+	KUNIT_EXPECT_EQ(test, dst->flex[TEST_SMALL], 0);
+	/* Verify element beyond original dst size was untouched. */
+	KUNIT_EXPECT_EQ(test, dst->flex[TEST_TARGET], 0xFDFDFDFD);
+
+	kfree(dst);
+	kfree(src);
+#undef TEST_BOUNDS
+#undef TEST_TARGET
+#undef TEST_SMALL
+}
+
+static void flex_dup_test(struct kunit *test)
+{
+#define TEST_TARGET	12
+	struct flex_cpy_obj *src, *dst = NULL, **null = NULL;
+	struct flex_dup_obj *encap = NULL;
+	unsigned long padding;
+	int i, rc;
+
+	/* Prepare open-coded source. */
+	src = kzalloc(struct_size(src, flex, TEST_TARGET), GFP_KERNEL);
+	src->count = TEST_TARGET;
+	memset(src->flex, 'A', flex_array_size(src, flex, TEST_TARGET));
+	src->flex[src->count - 1] = 0x14141414;
+
+	/* Reject NULL @alloc. */
+	rc = flex_dup(null, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+
+	/* Check good copy. */
+	rc = flex_dup(&dst, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_ASSERT_TRUE(test, dst != NULL);
+	CHECK_COPY(dst);
+
+	/* Reject non-NULL *@alloc. */
+	rc = flex_dup(&dst, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+
+	kfree(dst);
+
+	/* Check good encap copy. */
+	rc = __flex_dup(&encap, .fas, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_ASSERT_TRUE(test, dst != NULL);
+	CHECK_COPY(&encap->fas);
+	/* Check that items external to "fas" are zero. */
+	KUNIT_EXPECT_EQ(test, encap->flags, 0);
+	KUNIT_EXPECT_EQ(test, encap->junk, 0);
+	kfree(encap);
+#undef MAGIC_WORD
+#undef TEST_TARGET
+}
+
+static void mem_to_flex_test(struct kunit *test)
+{
+#define TEST_TARGET	9
+#define TEST_MAX	U8_MAX
+#define MAGIC_WORD	0x03030303
+	u8 magic_byte = MAGIC_WORD & 0xff;
+	struct flex_cpy_obj *dst;
+	size_t big = (size_t)INT_MAX + 1;
+	char small[] = "Hello";
+	char *src;
+	u32 src_len;
+	int rc;
+
+	/* Open coded allocations, 1 larger than actually used. */
+	src_len = flex_array_size(dst, flex, TEST_MAX + 1);
+	src = kzalloc(src_len, GFP_KERNEL);
+	dst = kzalloc(struct_size(dst, flex, TEST_MAX + 1), GFP_KERNEL);
+	dst->count = TEST_TARGET;
+
+	/* Fill source. */
+	memset(src, magic_byte, src_len);
+
+	/* Short copy is fine. */
+	KUNIT_EXPECT_EQ(test, dst->flex[0], 0);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+	rc = mem_to_flex(dst, src, 1);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_EXPECT_EQ(test, dst->count, 1);
+	KUNIT_EXPECT_EQ(test, dst->after_padding, 0);
+	KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+	dst->count = TEST_TARGET;
+
+	/* Reject negative elements count. */
+	rc = mem_to_flex(dst, small, -1);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure dst is unchanged. */
+	KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+
+	/* Reject compile-time read overflow. */
+	rc = mem_to_flex(dst, small, 20);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure dst is unchanged. */
+	KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+
+	/* Reject giant buffer source. */
+	rc = mem_to_flex(dst, small, big);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure dst is unchanged. */
+	KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+
+	/* Copy beyond storage size is rejected. */
+	dst->count = TEST_MAX;
+	KUNIT_EXPECT_EQ(test, dst->flex[TEST_MAX - 1], 0);
+	KUNIT_EXPECT_EQ(test, dst->flex[TEST_MAX], 0);
+	rc = mem_to_flex(dst, src, TEST_MAX + 1);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure dst is unchanged. */
+	KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
+
+	kfree(dst);
+	kfree(src);
+#undef MAGIC_WORD
+#undef TEST_MAX
+#undef TEST_TARGET
+}
+
+static void mem_to_flex_dup_test(struct kunit *test)
+{
+#define ELEMENTS_COUNT	259
+#define MAGIC_WORD	0xABABABAB
+	u8 magic_byte = MAGIC_WORD & 0xff;
+	struct flex_dup_obj *obj = NULL;
+	struct tiny_flex *tiny = NULL, **null = NULL;
+	size_t src_len, count, big = (size_t)INT_MAX + 1;
+	char small[] = "Hello";
+	u8 *src;
+	int rc;
+
+	src_len = struct_size(tiny, byte_array, ELEMENTS_COUNT);
+	src = kzalloc(src_len, GFP_KERNEL);
+	KUNIT_ASSERT_TRUE(test, src != NULL);
+	/* Fill with bytes. */
+	memset(src, magic_byte, src_len);
+	KUNIT_EXPECT_EQ(test, src[0], magic_byte);
+	KUNIT_EXPECT_EQ(test, src[src_len / 2], magic_byte);
+	KUNIT_EXPECT_EQ(test, src[src_len - 1], magic_byte);
+
+	/* Reject storage exceeding elements_count type. */
+	count = ELEMENTS_COUNT;
+	rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	KUNIT_EXPECT_TRUE(test, tiny == NULL);
+
+	/* Reject negative elements count. */
+	rc = mem_to_flex_dup(&tiny, src, -1, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	KUNIT_EXPECT_TRUE(test, tiny == NULL);
+
+	/* Reject compile-time read overflow. */
+	rc = mem_to_flex_dup(&tiny, small, 20, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	KUNIT_EXPECT_TRUE(test, tiny == NULL);
+
+	/* Reject giant buffer source. */
+	rc = mem_to_flex_dup(&tiny, small, big, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	KUNIT_EXPECT_TRUE(test, tiny == NULL);
+
+	/* Reject NULL @alloc. */
+	rc = mem_to_flex_dup(null, src, count, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+
+	/* Allow reasonable count.*/
+	count = ELEMENTS_COUNT / 2;
+	rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_ASSERT_TRUE(test, tiny != NULL);
+	/* Spot check the copy happened. */
+	KUNIT_EXPECT_EQ(test, tiny->count, count);
+	KUNIT_EXPECT_EQ(test, tiny->byte_array[0], magic_byte);
+	KUNIT_EXPECT_EQ(test, tiny->byte_array[count / 2], magic_byte);
+	KUNIT_EXPECT_EQ(test, tiny->byte_array[count - 1], magic_byte);
+
+	/* Reject non-NULL *@alloc. */
+	rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+	kfree(tiny);
+
+	/* Works with encapsulation too. */
+	count = ELEMENTS_COUNT / 10;
+	rc = __mem_to_flex_dup(&obj, .fas, src, count, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_ASSERT_TRUE(test, obj != NULL);
+	/* Spot check the copy happened. */
+	KUNIT_EXPECT_EQ(test, obj->fas.count, count);
+	KUNIT_EXPECT_EQ(test, obj->fas.after_padding, 0);
+	KUNIT_EXPECT_EQ(test, obj->fas.flex[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, obj->fas.flex[count / 2], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, obj->fas.flex[count - 1], MAGIC_WORD);
+	/* Check members before flexible array struct are zero. */
+	KUNIT_EXPECT_EQ(test, obj->flags, 0);
+	KUNIT_EXPECT_EQ(test, obj->junk, 0);
+	kfree(obj);
+#undef MAGIC_WORD
+#undef ELEMENTS_COUNT
+}
+
+static void flex_to_mem_test(struct kunit *test)
+{
+#define ELEMENTS_COUNT	200
+#define MAGIC_WORD	0xF1F2F3F4
+	struct flex_cpy_obj *src;
+	typeof(*src->flex) *cast;
+	size_t src_len = struct_size(src, flex, ELEMENTS_COUNT);
+	size_t copy_len = flex_array_size(src, flex, ELEMENTS_COUNT);
+	int i, rc;
+	size_t bytes = 0;
+	u8 too_small;
+	u8 *dst;
+
+	/* Create a filled flexible array struct. */
+	src = kzalloc(src_len, GFP_KERNEL);
+	KUNIT_ASSERT_TRUE(test, src != NULL);
+	src->count = ELEMENTS_COUNT;
+	src->after_padding = 13;
+	for (i = 0; i < ELEMENTS_COUNT; i++)
+		src->flex[i] = MAGIC_WORD;
+
+	/* Over-allocate space to do past-src_len checking. */
+	dst = kzalloc(src_len * 2, GFP_KERNEL);
+	KUNIT_ASSERT_TRUE(test, dst != NULL);
+	cast = (void *)dst;
+
+	/* Fail if dst is too small. */
+	rc = flex_to_mem(dst, copy_len - 1, src, &bytes);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure nothing was copied. */
+	KUNIT_EXPECT_EQ(test, bytes, 0);
+	KUNIT_EXPECT_EQ(test, cast[0], 0);
+
+	/* Fail if type too small to hold size of copy. */
+	KUNIT_EXPECT_GT(test, copy_len, type_max(typeof(too_small)));
+	rc = flex_to_mem(dst, copy_len, src, &too_small);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	/* Make sure nothing was copied. */
+	KUNIT_EXPECT_EQ(test, bytes, 0);
+	KUNIT_EXPECT_EQ(test, cast[0], 0);
+
+	/* Check good copy. */
+	rc = flex_to_mem(dst, copy_len, src, &bytes);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_EXPECT_EQ(test, bytes, copy_len);
+	/* Spot check the copy */
+	KUNIT_EXPECT_EQ(test, cast[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT / 2], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT - 1], MAGIC_WORD);
+	/* Make sure nothing was written after last element. */
+	KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT], 0);
+
+	kfree(dst);
+	kfree(src);
+#undef MAGIC_WORD
+#undef ELEMENTS_COUNT
+}
+
+static void flex_to_mem_dup_test(struct kunit *test)
+{
+#define ELEMENTS_COUNT	210
+#define MAGIC_WORD	0xF0F1F2F3
+	struct flex_dup_obj *obj, **null = NULL;
+	struct flex_cpy_obj *src;
+	typeof(*src->flex) *cast;
+	size_t obj_len = struct_size(obj, fas.flex, ELEMENTS_COUNT);
+	size_t src_len = struct_size(src, flex, ELEMENTS_COUNT);
+	size_t copy_len = flex_array_size(src, flex, ELEMENTS_COUNT);
+	int i, rc;
+	size_t bytes = 0;
+	u8 too_small = 0;
+	u8 *dst = NULL;
+
+	/* Create a filled flexible array struct. */
+	obj = kzalloc(obj_len, GFP_KERNEL);
+	KUNIT_ASSERT_TRUE(test, obj != NULL);
+	obj->fas.count = ELEMENTS_COUNT;
+	obj->fas.after_padding = 13;
+	for (i = 0; i < ELEMENTS_COUNT; i++)
+		obj->fas.flex[i] = MAGIC_WORD;
+	src = &obj->fas;
+
+	/* Fail if type too small to hold size of copy. */
+	KUNIT_EXPECT_GT(test, src_len, type_max(typeof(too_small)));
+	rc = flex_to_mem_dup(&dst, &too_small, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -E2BIG);
+	KUNIT_EXPECT_TRUE(test, dst == NULL);
+	KUNIT_EXPECT_EQ(test, too_small, 0);
+
+	/* Fail if @alloc_size is NULL. */
+	KUNIT_EXPECT_TRUE(test, dst == NULL);
+	rc = flex_to_mem_dup(&dst, dst, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+	KUNIT_EXPECT_TRUE(test, dst == NULL);
+
+	/* Fail if @alloc is NULL. */
+	rc = flex_to_mem_dup(null, &bytes, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+	KUNIT_EXPECT_TRUE(test, dst == NULL);
+	KUNIT_EXPECT_EQ(test, bytes, 0);
+
+	/* Check good copy. */
+	rc = flex_to_mem_dup(&dst, &bytes, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, 0);
+	KUNIT_EXPECT_TRUE(test, dst != NULL);
+	KUNIT_EXPECT_EQ(test, bytes, copy_len);
+	cast = (void *)dst;
+	/* Spot check the copy */
+	KUNIT_EXPECT_EQ(test, cast[0], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT / 2], MAGIC_WORD);
+	KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT - 1], MAGIC_WORD);
+
+	/* Fail if *@alloc is non-NULL. */
+	bytes = 0;
+	rc = flex_to_mem_dup(&dst, &bytes, src, GFP_KERNEL);
+	KUNIT_EXPECT_EQ(test, rc, -EINVAL);
+	KUNIT_EXPECT_EQ(test, bytes, 0);
+
+	kfree(dst);
+	kfree(obj);
+#undef MAGIC_WORD
+#undef ELEMENTS_COUNT
+}
+
+static struct kunit_case flex_array_test_cases[] = {
+	KUNIT_CASE(struct_test),
+	KUNIT_CASE(flex_cpy_test),
+	KUNIT_CASE(flex_dup_test),
+	KUNIT_CASE(mem_to_flex_test),
+	KUNIT_CASE(mem_to_flex_dup_test),
+	KUNIT_CASE(flex_to_mem_test),
+	KUNIT_CASE(flex_to_mem_dup_test),
+	{}
+};
+
+static struct kunit_suite flex_array_test_suite = {
+	.name = "flex_array",
+	.test_cases = flex_array_test_cases,
+};
+
+kunit_test_suite(flex_array_test_suite);
+
+MODULE_LICENSE("GPL");
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 04/32] fortify: Add run-time WARN for cross-field memcpy()
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (2 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 03/32] flex_array: Add Kunit tests Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item Kees Cook
                   ` (29 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Nathan Chancellor, Nick Desaulniers, Tom Rix,
	linux-hardening, llvm, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hyperv, linux-integrity, linux-rdma, linux-scsi,
	linux-security-module, linux-usb, linux-wireless, linux-xtensa,
	Loic Poulain, Louis Peens, Luca Coelho, Luiz Augusto von Dentz,
	Marc Dionne, Marcel Holtmann, Mark Brown, Martin K. Petersen,
	Max Filippov, Mimi Zohar, Muchun Song, netdev, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

Enable run-time checking of dynamic memcpy() and memmove() lengths,
issuing a WARN when a write would exceed the size of the target struct
member, when built with CONFIG_FORTIFY_SOURCE=y. This would have caught
all of the memcpy()-based buffer overflows from 2018 through 2020,
specifically covering all the cases where the destination buffer size
is known at compile time.

This change ONLY adds a run-time warning. As false positives are currently
still expected, this will not block the overflow. The new warnings will
look like this:

  memcpy: detected field-spanning write (size N) of single field "var->dest" (size M)
  WARNING: CPU: n PID: pppp at source/file/path.c:nr function+0xXX/0xXX [module]

The false positives are most likely where intentional field-spanning
writes are happening. These need to be addressed similarly to how the
compile-time cases were addressed: add a struct_group(), split the
memcpy(), use a flex_array.h helper, or some other refactoring.

In order to make identifying/investigating instances of added runtime
checks easier, each instance includes the destination variable name as a
WARN argument, prefixed with 'field "'. Therefore, on any given build,
it is trivial to inspect the artifacts to find instances. For example
on an x86_64 defconfig build, there are 78 new run-time memcpy() bounds
checks added:

  $ for i in vmlinux $(find . -name '*.ko'); do \
      strings "$i" | grep '^field "'; done | wc -l
  78

Currently, the common case where a destination buffer is known to be a
dynamic size (i.e. has a trailing flexible array) does not generate a
WARN. For example:

    struct normal_flex_array {
	void *a;
	int b;
	size_t array_size;
	u32 c;
	u8 flex_array[];
    };

    struct normal_flex_array *instance;
    ...
    /* These cases will be ignored for run-time bounds checking. */
    memcpy(instance, src, len);
    memcpy(instance->flex_array, src, len);

This code pattern will need to be addressed separately, likely by
migrating to one of the flex_array.h family of helpers.

Note that one of the dynamic-sized destination cases is irritatingly
unable to be detected by the compiler: when using memcpy() to target
a composite struct member which contains a trailing flexible array
struct. For example:

    struct wrapper {
	int foo;
	char bar;
	struct normal_flex_array embedded;
    };

    struct wrapper *instance;
    ...
    /* This will incorrectly WARN when len > sizeof(instance->embedded) */
    memcpy(&instance->embedded, src, len);

These cases end up appearing to the compiler to be sized as if the
flexible array had 0 elements. :( For more details see:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101832
https://godbolt.org/z/vW6x8vh4P

Regardless, all cases of copying to/from flexible array structures
should be migrated to using the new flex*()-family of helpers to gain
their added safety checking, but priority will need to be given to the
"composite flexible array structure destination" cases noted above.

As mentioned, none of these bounds checks block any overflows
currently. For users that have tested their workloads, do not encounter
any warnings, and wish to make these checks stop any overflows, they
can use a big hammer and set the sysctl panic_on_warn=1.

Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Tom Rix <trix@redhat.com>
Cc: linux-hardening@vger.kernel.org
Cc: llvm@lists.linux.dev
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/linux/fortify-string.h | 70 ++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
index 295637a66c46..9f65527fff40 100644
--- a/include/linux/fortify-string.h
+++ b/include/linux/fortify-string.h
@@ -3,6 +3,7 @@
 #define _LINUX_FORTIFY_STRING_H_
 
 #include <linux/const.h>
+#include <linux/bug.h>
 
 #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
 #define __RENAME(x) __asm__(#x)
@@ -303,7 +304,7 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size,
  * V = vulnerable to run-time overflow (will need refactoring to solve)
  *
  */
-__FORTIFY_INLINE void fortify_memcpy_chk(__kernel_size_t size,
+__FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size,
 					 const size_t p_size,
 					 const size_t q_size,
 					 const size_t p_size_field,
@@ -352,16 +353,79 @@ __FORTIFY_INLINE void fortify_memcpy_chk(__kernel_size_t size,
 	if ((p_size != (size_t)(-1) && p_size < size) ||
 	    (q_size != (size_t)(-1) && q_size < size))
 		fortify_panic(func);
+
+	/*
+	 * Warn when writing beyond destination field size.
+	 *
+	 * We must ignore p_size_field == 0 and -1 for existing
+	 * 0-element and flexible arrays, until they are all converted
+	 * to flexible arrays and use the flex()-family of helpers.
+	 *
+	 * The implementation of __builtin_object_size() behaves
+	 * like sizeof() when not directly referencing a flexible
+	 * array member, which means there will be many bounds checks
+	 * that will appear at run-time, without a way for them to be
+	 * detected at compile-time (as can be done when the destination
+	 * is specifically the flexible array member).
+	 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101832
+	 */
+	if (p_size_field != 0 && p_size_field != (size_t)(-1) &&
+	    p_size != p_size_field && p_size_field < size)
+		return true;
+
+	return false;
 }
 
 #define __fortify_memcpy_chk(p, q, size, p_size, q_size,		\
 			     p_size_field, q_size_field, op) ({		\
 	size_t __fortify_size = (size_t)(size);				\
-	fortify_memcpy_chk(__fortify_size, p_size, q_size,		\
-			   p_size_field, q_size_field, #op);		\
+	WARN_ONCE(fortify_memcpy_chk(__fortify_size, p_size, q_size,	\
+				     p_size_field, q_size_field, #op),	\
+		  #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \
+		  __fortify_size,					\
+		  "field \"" #p "\" at " __FILE__ ":" __stringify(__LINE__), \
+		  p_size_field);					\
 	__underlying_##op(p, q, __fortify_size);			\
 })
 
+/*
+ * Notes about compile-time buffer size detection:
+ *
+ * With these types...
+ *
+ *	struct middle {
+ *		u16 a;
+ *		u8 middle_buf[16];
+ *		int b;
+ *	};
+ *	struct end {
+ *		u16 a;
+ *		u8 end_buf[16];
+ *	};
+ *	struct flex {
+ *		int a;
+ *		u8 flex_buf[];
+ *	};
+ *
+ *	void func(TYPE *ptr) { ... }
+ *
+ * Cases where destination size cannot be currently detected:
+ * - the size of ptr's object (seemingly by design, gcc & clang fail):
+ *	__builtin_object_size(ptr, 1) == -1
+ * - the size of flexible arrays in ptr's obj (by design, dynamic size):
+ *      __builtin_object_size(ptr->flex_buf, 1) == -1
+ * - the size of ANY array at the end of ptr's obj (gcc and clang bug):
+ *	__builtin_object_size(ptr->end_buf, 1) == -1
+ *	https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836
+ *
+ * Cases where destination size is currently detected:
+ * - the size of non-array members within ptr's object:
+ *	__builtin_object_size(ptr->a, 1) == 2
+ * - the size of non-flexible-array in the middle of ptr's obj:
+ *	__builtin_object_size(ptr->middle_buf, 1) == 16
+ *
+ */
+
 /*
  * __builtin_object_size() must be captured here to avoid evaluating argument
  * side-effects further into the macro layers.
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (3 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 04/32] fortify: Add run-time WARN for cross-field memcpy() Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-16 12:49   ` Arend van Spriel
  2022-05-04  1:44 ` [PATCH 06/32] iwlwifi: calib: Prepare to use mem_to_flex_dup() Kees Cook
                   ` (28 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Arend van Spriel, Franky Lin, Hante Meuleman,
	Kalle Valo, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-wireless, brcm80211-dev-list.pdl,
	SHA-cyfmac-dev-list, netdev, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Herbert Xu, Hulk Robot, James E.J. Bottomley,
	James Morris, Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe,
	Jens Axboe, Johan Hedberg, Johannes Berg, Johannes Berg,
	John Keeping, Juergen Gross, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-xtensa, llvm,
	Loic Poulain, Louis Peens, Luca Coelho, Luiz Augusto von Dentz,
	Marc Dionne, Marcel Holtmann, Mark Brown, Martin K. Petersen,
	Max Filippov, Mimi Zohar, Muchun Song, Nathan Chancellor,
	Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, Simon Horman, Stefano Stabellini,
	Stefan Richter, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Arend van Spriel <aspriel@gmail.com>
Cc: Franky Lin <franky.lin@broadcom.com>
Cc: Hante Meuleman <hante.meuleman@broadcom.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-wireless@vger.kernel.org
Cc: brcm80211-dev-list.pdl@broadcom.com
Cc: SHA-cyfmac-dev-list@infineon.com
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 .../net/wireless/broadcom/brcm80211/brcmfmac/fweh.c   | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index bc3f4e4edcdf..bea798ca6466 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -32,8 +32,8 @@ struct brcmf_fweh_queue_item {
 	u8 ifidx;
 	u8 ifaddr[ETH_ALEN];
 	struct brcmf_event_msg_be emsg;
-	u32 datalen;
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, datalen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 /*
@@ -395,7 +395,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
 {
 	enum brcmf_fweh_event_code code;
 	struct brcmf_fweh_info *fweh = &drvr->fweh;
-	struct brcmf_fweh_queue_item *event;
+	struct brcmf_fweh_queue_item *event = NULL;
 	void *data;
 	u32 datalen;
 
@@ -414,8 +414,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
 	    datalen + sizeof(*event_packet) > packet_len)
 		return;
 
-	event = kzalloc(sizeof(*event) + datalen, gfp);
-	if (!event)
+	if (mem_to_flex_dup(&event, data, datalen, gfp))
 		return;
 
 	event->code = code;
@@ -423,8 +422,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
 
 	/* use memcpy to get aligned event message */
 	memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
-	memcpy(event->data, data, datalen);
-	event->datalen = datalen;
 	memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
 
 	brcmf_fweh_queue_event(fweh, event);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 06/32] iwlwifi: calib: Prepare to use mem_to_flex_dup()
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (4 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result Kees Cook
                   ` (27 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Luca Coelho, David S. Miller, Jakub Kicinski,
	Lee Jones, Johannes Berg, Gregory Greenman, Kalle Valo,
	Eric Dumazet, Paolo Abeni, Andy Lavr, linux-wireless, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Arend van Spriel, Baowen Zheng,
	Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, John Keeping, Juergen Gross,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

In preparation for replacing an open-coded memcpy() of a dynamically
side buffer, rearrange the structures to pass enough information into
the calling function to examine the bounds of the struct.

Rearrange the argument passing to use "cmd", rather than "hdr", since
"res" expects to operate on the "data" flex array in "cmd" (that follows
"hdr").

Cc: Luca Coelho <luciano.coelho@intel.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Johannes Berg <johannes.berg@intel.com>
Cc: Gregory Greenman <gregory.greenman@intel.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Andy Lavr <andy.lavr@gmail.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/wireless/intel/iwlwifi/dvm/agn.h   |  2 +-
 drivers/net/wireless/intel/iwlwifi/dvm/calib.c | 10 +++++-----
 drivers/net/wireless/intel/iwlwifi/dvm/ucode.c |  8 ++++----
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
index abb8696ba294..744e111d2ea3 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
@@ -112,7 +112,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
 			      enum iwl_ucode_type ucode_type);
 int iwl_send_calib_results(struct iwl_priv *priv);
 int iwl_calib_set(struct iwl_priv *priv,
-		  const struct iwl_calib_hdr *cmd, int len);
+		  const struct iwl_calib_cmd *cmd, int len);
 void iwl_calib_free_results(struct iwl_priv *priv);
 int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
 			    char **buf);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
index a11884fa254b..ae1f0cf560e2 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
@@ -19,7 +19,7 @@
 struct iwl_calib_result {
 	struct list_head list;
 	size_t cmd_len;
-	struct iwl_calib_hdr hdr;
+	struct iwl_calib_cmd cmd;
 	/* data follows */
 };
 
@@ -43,12 +43,12 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 		int ret;
 
 		hcmd.len[0] = res->cmd_len;
-		hcmd.data[0] = &res->hdr;
+		hcmd.data[0] = &res->cmd;
 		hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
 		ret = iwl_dvm_send_cmd(priv, &hcmd);
 		if (ret) {
 			IWL_ERR(priv, "Error %d on calib cmd %d\n",
-				ret, res->hdr.op_code);
+				ret, res->cmd.hdr.op_code);
 			return ret;
 		}
 	}
@@ -57,7 +57,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 }
 
 int iwl_calib_set(struct iwl_priv *priv,
-		  const struct iwl_calib_hdr *cmd, int len)
+		  const struct iwl_calib_cmd *cmd, int len)
 {
 	struct iwl_calib_result *res, *tmp;
 
@@ -69,7 +69,7 @@ int iwl_calib_set(struct iwl_priv *priv,
 	res->cmd_len = len;
 
 	list_for_each_entry(tmp, &priv->calib_results, list) {
-		if (tmp->hdr.op_code == res->hdr.op_code) {
+		if (tmp->cmd.hdr.op_code == res->cmd.hdr.op_code) {
 			list_replace(&tmp->list, &res->list);
 			kfree(tmp);
 			return 0;
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
index 4b27a53d0bb4..bb13ca5d666c 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
@@ -356,18 +356,18 @@ static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait,
 			      struct iwl_rx_packet *pkt, void *data)
 {
 	struct iwl_priv *priv = data;
-	struct iwl_calib_hdr *hdr;
+	struct iwl_calib_cmd *cmd;
 
 	if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) {
 		WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION);
 		return true;
 	}
 
-	hdr = (struct iwl_calib_hdr *)pkt->data;
+	cmd = (struct iwl_calib_cmd *)pkt->data;
 
-	if (iwl_calib_set(priv, hdr, iwl_rx_packet_payload_len(pkt)))
+	if (iwl_calib_set(priv, cmd, iwl_rx_packet_payload_len(pkt)))
 		IWL_ERR(priv, "Failed to record calibration data %d\n",
-			hdr->op_code);
+			cmd->hdr.op_code);
 
 	return false;
 }
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (5 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 06/32] iwlwifi: calib: Prepare to use mem_to_flex_dup() Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 08/32] iwlwifi: mvm: Use mem_to_flex_dup() with struct ieee80211_key_conf Kees Cook
                   ` (26 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Andy Lavr, Luca Coelho, Kalle Valo, David S. Miller,
	Jakub Kicinski, Paolo Abeni, Gregory Greenman, Eric Dumazet,
	linux-wireless, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-xtensa, llvm,
	Loic Poulain, Louis Peens, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Avoids future false-positive warning when strict run-time memcpy()
bounds checking is enabled:

memcpy: detected field-spanning write (size 8) of single field "&res->hdr" (size 4)

Adds an additional size check since the minimum isn't 0.

Reported-by: Andy Lavr <andy.lavr@gmail.com>
Cc: Luca Coelho <luciano.coelho@intel.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Gregory Greenman <gregory.greenman@intel.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/wireless/intel/iwlwifi/dvm/calib.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
index ae1f0cf560e2..7480c19d7af0 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/calib.c
@@ -18,8 +18,11 @@
 /* Opaque calibration results */
 struct iwl_calib_result {
 	struct list_head list;
-	size_t cmd_len;
-	struct iwl_calib_cmd cmd;
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, cmd_len);
+	union {
+		struct iwl_calib_cmd cmd;
+		DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
+	};
 	/* data follows */
 };
 
@@ -59,14 +62,10 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 int iwl_calib_set(struct iwl_priv *priv,
 		  const struct iwl_calib_cmd *cmd, int len)
 {
-	struct iwl_calib_result *res, *tmp;
+	struct iwl_calib_result *res = NULL, *tmp;
 
-	res = kmalloc(sizeof(*res) + len - sizeof(struct iwl_calib_hdr),
-		      GFP_ATOMIC);
-	if (!res)
+	if (len < sizeof(*cmd) || mem_to_flex_dup(&res, cmd, len, GFP_ATOMIC))
 		return -ENOMEM;
-	memcpy(&res->hdr, cmd, len);
-	res->cmd_len = len;
 
 	list_for_each_entry(tmp, &priv->calib_results, list) {
 		if (tmp->cmd.hdr.op_code == res->cmd.hdr.op_code) {
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 08/32] iwlwifi: mvm: Use mem_to_flex_dup() with struct ieee80211_key_conf
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (6 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 09/32] p54: Use mem_to_flex_dup() with struct p54_cal_database Kees Cook
                   ` (25 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Luca Coelho, Kalle Valo, David S. Miller,
	Jakub Kicinski, Paolo Abeni, Johannes Berg, Gregory Greenman,
	Eric Dumazet, linux-wireless, netdev, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Guenter Roeck, Haiyang Zhang,
	Hante Meuleman, Herbert Xu, Hulk Robot, James E.J. Bottomley,
	James Morris, Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe,
	Jens Axboe, Johan Hedberg, Johannes Berg, John Keeping,
	Juergen Gross, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-xtensa, llvm,
	Loic Poulain, Louis Peens, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Luca Coelho <luciano.coelho@intel.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Gregory Greenman <gregory.greenman@intel.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 8 ++------
 include/net/mac80211.h                       | 4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 406f0a50a5bf..23cade528dcf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -4108,7 +4108,7 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	int ret;
 	u16 queue;
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	struct ieee80211_key_conf *keyconf;
+	struct ieee80211_key_conf *keyconf = NULL;
 
 	ret = iwl_mvm_allocate_int_sta(mvm, sta, 0,
 				       NL80211_IFTYPE_UNSPECIFIED,
@@ -4122,15 +4122,11 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 	if (ret)
 		goto out;
 
-	keyconf = kzalloc(sizeof(*keyconf) + key_len, GFP_KERNEL);
-	if (!keyconf) {
+	if (mem_to_flex_dup(&keyconf, key, key_len, GFP_KERNEL)) {
 		ret = -ENOBUFS;
 		goto out;
 	}
-
 	keyconf->cipher = cipher;
-	memcpy(keyconf->key, key, key_len);
-	keyconf->keylen = key_len;
 
 	ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false,
 				   0, NULL, 0, 0, true);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 75880fc70700..4abe52963a96 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1890,8 +1890,8 @@ struct ieee80211_key_conf {
 	u8 hw_key_idx;
 	s8 keyidx;
 	u16 flags;
-	u8 keylen;
-	u8 key[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, keylen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, key);
 };
 
 #define IEEE80211_MAX_PN_LEN	16
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 09/32] p54: Use mem_to_flex_dup() with struct p54_cal_database
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (7 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 08/32] iwlwifi: mvm: Use mem_to_flex_dup() with struct ieee80211_key_conf Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg Kees Cook
                   ` (24 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Christian Lamparter, Kalle Valo, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-wireless,
	netdev, Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Chris Zankel, Cong Wang, Daniel Axtens,
	Daniel Vetter, Dan Williams, David Gow, David Howells,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Francis Laniel, Frank Rowand, Franky Lin, Greg Kroah-Hartman,
	Gregory Greenman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-xtensa, llvm,
	Loic Poulain, Louis Peens, Luca Coelho, Luiz Augusto von Dentz,
	Marc Dionne, Marcel Holtmann, Mark Brown, Martin K. Petersen,
	Max Filippov, Mimi Zohar, Muchun Song, Nathan Chancellor,
	Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Christian Lamparter <chunkeey@googlemail.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/wireless/intersil/p54/eeprom.c | 8 ++------
 drivers/net/wireless/intersil/p54/p54.h    | 4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c
index 5bd35c147e19..bd9b3ea327b9 100644
--- a/drivers/net/wireless/intersil/p54/eeprom.c
+++ b/drivers/net/wireless/intersil/p54/eeprom.c
@@ -702,7 +702,7 @@ static int p54_convert_output_limits(struct ieee80211_hw *dev,
 static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
 					       size_t total_len)
 {
-	struct p54_cal_database *dst;
+	struct p54_cal_database *dst = NULL;
 	size_t payload_len, entries, entry_size, offset;
 
 	payload_len = le16_to_cpu(src->len);
@@ -713,16 +713,12 @@ static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src,
 	     (payload_len + sizeof(*src) != total_len))
 		return NULL;
 
-	dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL);
-	if (!dst)
+	if (mem_to_flex_dup(&dst, src->data, payload_len, GFP_KERNEL))
 		return NULL;
 
 	dst->entries = entries;
 	dst->entry_size = entry_size;
 	dst->offset = offset;
-	dst->len = payload_len;
-
-	memcpy(dst->data, src->data, payload_len);
 	return dst;
 }
 
diff --git a/drivers/net/wireless/intersil/p54/p54.h b/drivers/net/wireless/intersil/p54/p54.h
index 3356ea708d81..22bbb6d28245 100644
--- a/drivers/net/wireless/intersil/p54/p54.h
+++ b/drivers/net/wireless/intersil/p54/p54.h
@@ -125,8 +125,8 @@ struct p54_cal_database {
 	size_t entries;
 	size_t entry_size;
 	size_t offset;
-	size_t len;
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 #define EEPROM_READBACK_LEN 0x3fc
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (8 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 09/32] p54: Use mem_to_flex_dup() with struct p54_cal_database Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  5:42   ` Kalle Valo
  2022-05-04  1:44 ` [PATCH 11/32] nl80211: Use mem_to_flex_dup() with struct cfg80211_cqm_config Kees Cook
                   ` (23 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Loic Poulain, Kalle Valo, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, wcn36xx,
	linux-wireless, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Loic Poulain <loic.poulain@linaro.org>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: wcn36xx@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/net/wireless/ath/wcn36xx/smd.c | 8 ++------
 drivers/net/wireless/ath/wcn36xx/smd.h | 4 ++--
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index dc3805609284..106af0a2ffc4 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -3343,7 +3343,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
 	const struct wcn36xx_hal_msg_header *msg_header = buf;
 	struct ieee80211_hw *hw = priv;
 	struct wcn36xx *wcn = hw->priv;
-	struct wcn36xx_hal_ind_msg *msg_ind;
+	struct wcn36xx_hal_ind_msg *msg_ind = NULL;
 	wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
 
 	switch (msg_header->msg_type) {
@@ -3407,16 +3407,12 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
 	case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
 	case WCN36XX_HAL_PRINT_REG_INFO_IND:
 	case WCN36XX_HAL_SCAN_OFFLOAD_IND:
-		msg_ind = kmalloc(struct_size(msg_ind, msg, len), GFP_ATOMIC);
-		if (!msg_ind) {
+		if (mem_to_flex_dup(&msg_ind, buf, len, GFP_ATOMIC)) {
 			wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
 				    msg_header->msg_type);
 			return -ENOMEM;
 		}
 
-		msg_ind->msg_len = len;
-		memcpy(msg_ind->msg, buf, len);
-
 		spin_lock(&wcn->hal_ind_lock);
 		list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
 		queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 3fd598ac2a27..76ecac46f36b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
 
 struct wcn36xx_hal_ind_msg {
 	struct list_head list;
-	size_t msg_len;
-	u8 msg[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, msg_len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, msg);
 };
 
 struct wcn36xx;
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 11/32] nl80211: Use mem_to_flex_dup() with struct cfg80211_cqm_config
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (9 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies Kees Cook
                   ` (22 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Johannes Berg, David S. Miller, Jakub Kicinski,
	Paolo Abeni, linux-wireless, netdev, Eric Dumazet,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 net/wireless/core.h    |  4 ++--
 net/wireless/nl80211.c | 15 ++++-----------
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3a7dbd63d8c6..899d111993c6 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -295,8 +295,8 @@ struct cfg80211_beacon_registration {
 struct cfg80211_cqm_config {
 	u32 rssi_hyst;
 	s32 last_rssi_event_value;
-	int n_rssi_thresholds;
-	s32 rssi_thresholds[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, n_rssi_thresholds);
+	DECLARE_FLEX_ARRAY_ELEMENTS(s32, rssi_thresholds);
 };
 
 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 945ed87d12e0..70df7132cce8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12096,21 +12096,14 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
 
 	wdev_lock(wdev);
 	if (n_thresholds) {
-		struct cfg80211_cqm_config *cqm_config;
+		struct cfg80211_cqm_config *cqm_config = NULL;
 
-		cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
-						 n_thresholds),
-				     GFP_KERNEL);
-		if (!cqm_config) {
-			err = -ENOMEM;
+		err = mem_to_flex_dup(&cqm_config, thresholds, n_thresholds,
+				      GFP_KERNEL);
+		if (err)
 			goto unlock;
-		}
 
 		cqm_config->rssi_hyst = hysteresis;
-		cqm_config->n_rssi_thresholds = n_thresholds;
-		memcpy(cqm_config->rssi_thresholds, thresholds,
-		       flex_array_size(cqm_config, rssi_thresholds,
-				       n_thresholds));
 
 		wdev->cqm_config = cqm_config;
 	}
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (10 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 11/32] nl80211: Use mem_to_flex_dup() with struct cfg80211_cqm_config Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  7:28   ` Johannes Berg
  2022-05-04  1:44 ` [PATCH 13/32] mac80211: Use mem_to_flex_dup() with several structs Kees Cook
                   ` (21 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Johannes Berg, David S. Miller, Jakub Kicinski,
	Paolo Abeni, Eric Dumazet, linux-wireless, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/cfg80211.h |  4 ++--
 net/wireless/scan.c    | 21 ++++++---------------
 2 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 68713388b617..fa236015f6ef 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2600,9 +2600,9 @@ struct cfg80211_inform_bss {
 struct cfg80211_bss_ies {
 	u64 tsf;
 	struct rcu_head rcu_head;
-	int len;
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
 	bool from_beacon;
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 /**
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 4a6d86432910..9f53d05c6aaa 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1932,7 +1932,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
 				gfp_t gfp)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-	struct cfg80211_bss_ies *ies;
+	struct cfg80211_bss_ies *ies = NULL;
 	struct ieee80211_channel *channel;
 	struct cfg80211_internal_bss tmp = {}, *res;
 	int bss_type;
@@ -1978,13 +1978,10 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
 	 * override the IEs pointer should we have received an earlier
 	 * indication of Probe Response data.
 	 */
-	ies = kzalloc(sizeof(*ies) + ielen, gfp);
-	if (!ies)
+	if (mem_to_flex_dup(&ies, ie, ielen, gfp))
 		return NULL;
-	ies->len = ielen;
 	ies->tsf = tsf;
 	ies->from_beacon = false;
-	memcpy(ies->data, ie, ielen);
 
 	switch (ftype) {
 	case CFG80211_BSS_FTYPE_BEACON:
@@ -2277,7 +2274,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
 	size_t ielen = len - offsetof(struct ieee80211_mgmt,
 				      u.probe_resp.variable);
 	size_t new_ie_len;
-	struct cfg80211_bss_ies *new_ies;
+	struct cfg80211_bss_ies *new_ies = NULL;
 	const struct cfg80211_bss_ies *old;
 	u8 cpy_len;
 
@@ -2314,8 +2311,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
 	if (!new_ie)
 		return;
 
-	new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
-	if (!new_ies)
+	if (mem_to_flex_dup(&new_ies, new_ie, new_ie_len, GFP_ATOMIC))
 		goto out_free;
 
 	pos = new_ie;
@@ -2333,10 +2329,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
 	memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len)));
 
 	/* update ie */
-	new_ies->len = new_ie_len;
 	new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
 	new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
-	memcpy(new_ies->data, new_ie, new_ie_len);
 	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
 		old = rcu_access_pointer(nontrans_bss->proberesp_ies);
 		rcu_assign_pointer(nontrans_bss->proberesp_ies, new_ies);
@@ -2363,7 +2357,7 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
 				      gfp_t gfp)
 {
 	struct cfg80211_internal_bss tmp = {}, *res;
-	struct cfg80211_bss_ies *ies;
+	struct cfg80211_bss_ies *ies = NULL;
 	struct ieee80211_channel *channel;
 	bool signal_valid;
 	struct ieee80211_ext *ext = NULL;
@@ -2442,14 +2436,11 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy,
 		capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
 	}
 
-	ies = kzalloc(sizeof(*ies) + ielen, gfp);
-	if (!ies)
+	if (mem_to_flex_dup(&ies, variable, ielen, gfp))
 		return NULL;
-	ies->len = ielen;
 	ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
 	ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control) ||
 			   ieee80211_is_s1g_beacon(mgmt->frame_control);
-	memcpy(ies->data, variable, ielen);
 
 	if (ieee80211_is_probe_resp(mgmt->frame_control))
 		rcu_assign_pointer(tmp.pub.proberesp_ies, ies);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 13/32] mac80211: Use mem_to_flex_dup() with several structs
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (11 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 14/32] af_unix: Use mem_to_flex_dup() with struct unix_address Kees Cook
                   ` (20 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Johannes Berg, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-wireless, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying:

    struct probe_resp
    struct fils_discovery_data
    struct unsol_bcast_probe_resp_data

Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 net/mac80211/cfg.c         | 22 ++++++----------------
 net/mac80211/ieee80211_i.h | 12 ++++++------
 2 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index f1d211e61e49..355edbf41707 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -867,20 +867,16 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
 			 const struct ieee80211_csa_settings *csa,
 			 const struct ieee80211_color_change_settings *cca)
 {
-	struct probe_resp *new, *old;
+	struct probe_resp *new = NULL, *old;
 
 	if (!resp || !resp_len)
 		return 1;
 
 	old = sdata_dereference(sdata->u.ap.probe_resp, sdata);
 
-	new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
-	if (!new)
+	if (mem_to_flex_dup(&new, resp, resp_len, GFP_KERNEL))
 		return -ENOMEM;
 
-	new->len = resp_len;
-	memcpy(new->data, resp, resp_len);
-
 	if (csa)
 		memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_presp,
 		       csa->n_counter_offsets_presp *
@@ -898,7 +894,7 @@ ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
 static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
 					struct cfg80211_fils_discovery *params)
 {
-	struct fils_discovery_data *new, *old = NULL;
+	struct fils_discovery_data *new = NULL, *old = NULL;
 	struct ieee80211_fils_discovery *fd;
 
 	if (!params->tmpl || !params->tmpl_len)
@@ -909,11 +905,8 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
 	fd->max_interval = params->max_interval;
 
 	old = sdata_dereference(sdata->u.ap.fils_discovery, sdata);
-	new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
-	if (!new)
+	if (mem_to_flex_dup(&new, params->tmpl, params->tmpl_len, GFP_KERNEL))
 		return -ENOMEM;
-	new->len = params->tmpl_len;
-	memcpy(new->data, params->tmpl, params->tmpl_len);
 	rcu_assign_pointer(sdata->u.ap.fils_discovery, new);
 
 	if (old)
@@ -926,17 +919,14 @@ static int
 ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
 				     struct cfg80211_unsol_bcast_probe_resp *params)
 {
-	struct unsol_bcast_probe_resp_data *new, *old = NULL;
+	struct unsol_bcast_probe_resp_data *new = NULL, *old = NULL;
 
 	if (!params->tmpl || !params->tmpl_len)
 		return -EINVAL;
 
 	old = sdata_dereference(sdata->u.ap.unsol_bcast_probe_resp, sdata);
-	new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
-	if (!new)
+	if (mem_to_flex_dup(&new, params->tmpl, params->tmpl_len, GFP_KERNEL))
 		return -ENOMEM;
-	new->len = params->tmpl_len;
-	memcpy(new->data, params->tmpl, params->tmpl_len);
 	rcu_assign_pointer(sdata->u.ap.unsol_bcast_probe_resp, new);
 
 	if (old)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d4a7ba4a8202..2e9bbfb12c0d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -263,21 +263,21 @@ struct beacon_data {
 
 struct probe_resp {
 	struct rcu_head rcu_head;
-	int len;
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
 	u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 struct fils_discovery_data {
 	struct rcu_head rcu_head;
-	int len;
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 struct unsol_bcast_probe_resp_data {
 	struct rcu_head rcu_head;
-	int len;
-	u8 data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 struct ps_data {
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 14/32] af_unix: Use mem_to_flex_dup() with struct unix_address
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (12 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 13/32] mac80211: Use mem_to_flex_dup() with several structs Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 15/32] 802/garp: Use mem_to_flex_dup() with struct garp_attr Kees Cook
                   ` (19 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Kuniyuki Iwashima, Alexei Starovoitov, Cong Wang,
	Al Viro, netdev, alsa-devel, Andrew Gabbasov, Andrew Morton,
	Andy Gross, Andy Lavr, Arend van Spriel, Baowen Zheng,
	Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Cong Wang <cong.wang@bytedance.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/af_unix.h | 14 ++++++++++++--
 net/unix/af_unix.c    |  7 ++-----
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index a7ef624ed726..422535b71295 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -25,8 +25,18 @@ extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
 
 struct unix_address {
 	refcount_t	refcnt;
-	int		len;
-	struct sockaddr_un name[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
+	union {
+		DECLARE_FLEX_ARRAY(struct sockaddr_un, name);
+		/*
+		 * While a struct is used to access the flexible
+		 * array, it may only be partially populated, and
+		 * "len" above is actually tracking bytes, not a
+		 * count of struct sockaddr_un elements, so also
+		 * include a byte-size flexible array.
+		 */
+		DECLARE_FLEX_ARRAY_ELEMENTS(u8, bytes);
+	};
 };
 
 struct unix_skb_parms {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e1dd9e9c8452..8410cbc82ded 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -244,15 +244,12 @@ EXPORT_SYMBOL_GPL(unix_peer_get);
 static struct unix_address *unix_create_addr(struct sockaddr_un *sunaddr,
 					     int addr_len)
 {
-	struct unix_address *addr;
+	struct unix_address *addr = NULL;
 
-	addr = kmalloc(sizeof(*addr) + addr_len, GFP_KERNEL);
-	if (!addr)
+	if (mem_to_flex_dup(&addr, sunaddr, addr_len, GFP_KERNEL))
 		return NULL;
 
 	refcount_set(&addr->refcnt, 1);
-	addr->len = addr_len;
-	memcpy(addr->name, sunaddr, addr_len);
 
 	return addr;
 }
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 15/32] 802/garp: Use mem_to_flex_dup() with struct garp_attr
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (13 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 14/32] af_unix: Use mem_to_flex_dup() with struct unix_address Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 16/32] 802/mrp: Use mem_to_flex_dup() with struct mrp_attr Kees Cook
                   ` (18 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Hulk Robot, Yang Yingliang, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, James E.J. Bottomley,
	James Morris, Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe,
	Jens Axboe, Johan Hedberg, Johannes Berg, Johannes Berg,
	John Keeping, Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, Nick Desaulniers,
	Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Hulk Robot <hulkci@huawei.com>
Cc: Yang Yingliang <yangyingliang@huawei.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/garp.h | 4 ++--
 net/802/garp.c     | 9 +++------
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/net/garp.h b/include/net/garp.h
index 4d9a0c6a2e5f..ec087ae534e7 100644
--- a/include/net/garp.h
+++ b/include/net/garp.h
@@ -80,8 +80,8 @@ struct garp_attr {
 	struct rb_node			node;
 	enum garp_applicant_state	state;
 	u8				type;
-	u8				dlen;
-	unsigned char			data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, dlen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(unsigned char, data);
 };
 
 enum garp_applications {
diff --git a/net/802/garp.c b/net/802/garp.c
index f6012f8e59f0..72743ed00a54 100644
--- a/net/802/garp.c
+++ b/net/802/garp.c
@@ -168,7 +168,7 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app,
 					  const void *data, u8 len, u8 type)
 {
 	struct rb_node *parent = NULL, **p = &app->gid.rb_node;
-	struct garp_attr *attr;
+	struct garp_attr *attr = NULL;
 	int d;
 
 	while (*p) {
@@ -184,13 +184,10 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app,
 			return attr;
 		}
 	}
-	attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
-	if (!attr)
-		return attr;
+	if (mem_to_flex_dup(&attr, data, len, GFP_ATOMIC))
+		return NULL;
 	attr->state = GARP_APPLICANT_VO;
 	attr->type  = type;
-	attr->dlen  = len;
-	memcpy(attr->data, data, len);
 
 	rb_link_node(&attr->node, parent, p);
 	rb_insert_color(&attr->node, &app->gid);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 16/32] 802/mrp: Use mem_to_flex_dup() with struct mrp_attr
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (14 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 15/32] 802/garp: Use mem_to_flex_dup() with struct garp_attr Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 17/32] net/flow_offload: Use mem_to_flex_dup() with struct flow_action_cookie Kees Cook
                   ` (17 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Yang Yingliang, netdev, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Yang Yingliang <yangyingliang@huawei.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/mrp.h | 4 ++--
 net/802/mrp.c     | 9 +++------
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/net/mrp.h b/include/net/mrp.h
index 1c308c034e1a..211670bb46f2 100644
--- a/include/net/mrp.h
+++ b/include/net/mrp.h
@@ -91,8 +91,8 @@ struct mrp_attr {
 	struct rb_node			node;
 	enum mrp_applicant_state	state;
 	u8				type;
-	u8				len;
-	unsigned char			value[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(unsigned char, value);
 };
 
 enum mrp_applications {
diff --git a/net/802/mrp.c b/net/802/mrp.c
index 35e04cc5390c..8b9b2e685a42 100644
--- a/net/802/mrp.c
+++ b/net/802/mrp.c
@@ -257,7 +257,7 @@ static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app,
 					const void *value, u8 len, u8 type)
 {
 	struct rb_node *parent = NULL, **p = &app->mad.rb_node;
-	struct mrp_attr *attr;
+	struct mrp_attr *attr = NULL;
 	int d;
 
 	while (*p) {
@@ -273,13 +273,10 @@ static struct mrp_attr *mrp_attr_create(struct mrp_applicant *app,
 			return attr;
 		}
 	}
-	attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
-	if (!attr)
-		return attr;
+	if (mem_to_flex_dup(&attr, value, len, GFP_ATOMIC))
+		return NULL;
 	attr->state = MRP_APPLICANT_VO;
 	attr->type  = type;
-	attr->len   = len;
-	memcpy(attr->value, value, len);
 
 	rb_link_node(&attr->node, parent, p);
 	rb_insert_color(&attr->node, &app->mad);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 17/32] net/flow_offload: Use mem_to_flex_dup() with struct flow_action_cookie
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (15 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 16/32] 802/mrp: Use mem_to_flex_dup() with struct mrp_attr Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 18/32] firewire: Use __mem_to_flex_dup() with struct iso_interrupt_event Kees Cook
                   ` (16 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Baowen Zheng, Eli Cohen, Louis Peens, Simon Horman,
	netdev, Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Francis Laniel, Frank Rowand, Franky Lin, Greg Kroah-Hartman,
	Gregory Greenman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Stefano Stabellini,
	Stefan Richter, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Baowen Zheng <baowen.zheng@corigine.com>
Cc: Eli Cohen <elic@nvidia.com>
Cc: Louis Peens <louis.peens@corigine.com>
Cc: Simon Horman <simon.horman@corigine.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/flow_offload.h | 4 ++--
 net/core/flow_offload.c    | 7 ++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 021778a7e1af..ca5db457a0bc 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -190,8 +190,8 @@ enum flow_action_hw_stats {
 typedef void (*action_destr)(void *priv);
 
 struct flow_action_cookie {
-	u32 cookie_len;
-	u8 cookie[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, cookie_len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, cookie);
 };
 
 struct flow_action_cookie *flow_action_cookie_create(void *data,
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index 73f68d4625f3..e23c8d05b828 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -199,13 +199,10 @@ struct flow_action_cookie *flow_action_cookie_create(void *data,
 						     unsigned int len,
 						     gfp_t gfp)
 {
-	struct flow_action_cookie *cookie;
+	struct flow_action_cookie *cookie = NULL;
 
-	cookie = kmalloc(sizeof(*cookie) + len, gfp);
-	if (!cookie)
+	if (mem_to_flex_dup(&cookie, data, len, gfp))
 		return NULL;
-	cookie->cookie_len = len;
-	memcpy(cookie->cookie, data, len);
 	return cookie;
 }
 EXPORT_SYMBOL(flow_action_cookie_create);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 18/32] firewire: Use __mem_to_flex_dup() with struct iso_interrupt_event
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (16 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 17/32] net/flow_offload: Use mem_to_flex_dup() with struct flow_action_cookie Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl Kees Cook
                   ` (15 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Stefan Richter, linux1394-devel, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Francis Laniel, Frank Rowand, Franky Lin, Greg Kroah-Hartman,
	Gregory Greenman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, Jakub Kicinski, James E.J. Bottomley,
	James Morris, Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe,
	Jens Axboe, Johan Hedberg, Johannes Berg, Johannes Berg,
	John Keeping, Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Stefan Richter <stefanr@s5r6.in-berlin.de>
Cc: linux1394-devel@lists.sourceforge.net
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/firewire/core-cdev.c       | 7 ++-----
 include/uapi/linux/firewire-cdev.h | 4 ++--
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index c9fe5903725a..7e884c61e12e 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -913,17 +913,14 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle,
 			 size_t header_length, void *header, void *data)
 {
 	struct client *client = data;
-	struct iso_interrupt_event *e;
+	struct iso_interrupt_event *e = NULL;
 
-	e = kmalloc(sizeof(*e) + header_length, GFP_ATOMIC);
-	if (e == NULL)
+	if (__mem_to_flex_dup(&e, .interrupt, header, header_length, GFP_ATOMIC))
 		return;
 
 	e->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
 	e->interrupt.closure   = client->iso_closure;
 	e->interrupt.cycle     = cycle;
-	e->interrupt.header_length = header_length;
-	memcpy(e->interrupt.header, header, header_length);
 	queue_event(client, &e->event, &e->interrupt,
 		    sizeof(e->interrupt) + header_length, NULL, 0);
 }
diff --git a/include/uapi/linux/firewire-cdev.h b/include/uapi/linux/firewire-cdev.h
index 5effa9832802..22c5f59e9dfa 100644
--- a/include/uapi/linux/firewire-cdev.h
+++ b/include/uapi/linux/firewire-cdev.h
@@ -264,8 +264,8 @@ struct fw_cdev_event_iso_interrupt {
 	__u64 closure;
 	__u32 type;
 	__u32 cycle;
-	__u32 header_length;
-	__u32 header[0];
+	__DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u32, header_length);
+	__DECLARE_FLEX_ARRAY_ELEMENTS(__u32, header);
 };
 
 /**
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (17 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 18/32] firewire: Use __mem_to_flex_dup() with struct iso_interrupt_event Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data Kees Cook
                   ` (14 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David Howells, Marc Dionne, linux-afs,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David S. Miller, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: David Howells <dhowells@redhat.com>
Cc: Marc Dionne <marc.dionne@auristor.com>
Cc: linux-afs@lists.infradead.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 fs/afs/internal.h | 4 ++--
 fs/afs/xattr.c    | 7 ++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 7a72e9c60423..83014d20b6b3 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1125,8 +1125,8 @@ extern bool afs_fs_get_capabilities(struct afs_net *, struct afs_server *,
 extern void afs_fs_inline_bulk_status(struct afs_operation *);
 
 struct afs_acl {
-	u32	size;
-	u8	data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, size);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
 };
 
 extern void afs_fs_fetch_acl(struct afs_operation *);
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
index 7751b0b3f81d..77b3af283d49 100644
--- a/fs/afs/xattr.c
+++ b/fs/afs/xattr.c
@@ -73,16 +73,13 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
 static bool afs_make_acl(struct afs_operation *op,
 			 const void *buffer, size_t size)
 {
-	struct afs_acl *acl;
+	struct afs_acl *acl = NULL;
 
-	acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
-	if (!acl) {
+	if (mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL)) {
 		afs_op_nomem(op);
 		return false;
 	}
 
-	acl->size = size;
-	memcpy(acl->data, buffer, size);
 	op->acl = acl;
 	return true;
 }
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (18 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04 15:17   ` Mark Brown
  2022-05-04  1:44 ` [PATCH 21/32] soc: qcom: apr: Use mem_to_flex_dup() with struct apr_rx_buf Kees Cook
                   ` (13 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Lars-Peter Clausen, Nuno Sá,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	alsa-devel, Alexei Starovoitov, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lee Jones, Leon Romanovsky,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Martin K. Petersen, Max Filippov, Mimi Zohar,
	Muchun Song, Nathan Chancellor, netdev, Nick Desaulniers,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: "Nuno Sá" <nuno.sa@analog.com>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: alsa-devel@alsa-project.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 sound/soc/codecs/sigmadsp.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
index b992216aee55..648bdc73c5d9 100644
--- a/sound/soc/codecs/sigmadsp.c
+++ b/sound/soc/codecs/sigmadsp.c
@@ -42,8 +42,8 @@ struct sigmadsp_data {
 	struct list_head head;
 	uint32_t samplerates;
 	unsigned int addr;
-	unsigned int length;
-	uint8_t data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned int, length);
+	DECLARE_FLEX_ARRAY_ELEMENTS(uint8_t, data);
 };
 
 struct sigma_fw_chunk {
@@ -263,7 +263,7 @@ static int sigma_fw_load_data(struct sigmadsp *sigmadsp,
 	const struct sigma_fw_chunk *chunk, unsigned int length)
 {
 	const struct sigma_fw_chunk_data *data_chunk;
-	struct sigmadsp_data *data;
+	struct sigmadsp_data *data = NULL;
 
 	if (length <= sizeof(*data_chunk))
 		return -EINVAL;
@@ -272,14 +272,11 @@ static int sigma_fw_load_data(struct sigmadsp *sigmadsp,
 
 	length -= sizeof(*data_chunk);
 
-	data = kzalloc(sizeof(*data) + length, GFP_KERNEL);
-	if (!data)
+	if (mem_to_flex_dup(&data, data_chunk->data, length, GFP_KERNEL))
 		return -ENOMEM;
 
 	data->addr = le16_to_cpu(data_chunk->addr);
-	data->length = length;
 	data->samplerates = le32_to_cpu(chunk->samplerates);
-	memcpy(data->data, data_chunk->data, length);
 	list_add_tail(&data->head, &sigmadsp->data_list);
 
 	return 0;
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 21/32] soc: qcom: apr: Use mem_to_flex_dup() with struct apr_rx_buf
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (19 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 22/32] atags_proc: Use mem_to_flex_dup() with struct buffer Kees Cook
                   ` (12 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Andy Gross, Bjorn Andersson, linux-arm-msm,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Lavr, Arend van Spriel, Baowen Zheng,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Francis Laniel, Frank Rowand, Franky Lin, Greg Kroah-Hartman,
	Gregory Greenman, Guenter Roeck, Haiyang Zhang, Hante Meuleman,
	Herbert Xu, Hulk Robot, Jakub Kicinski, James E.J. Bottomley,
	James Morris, Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe,
	Jens Axboe, Johan Hedberg, Johannes Berg, Johannes Berg,
	John Keeping, Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Cc: linux-arm-msm@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/soc/qcom/apr.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 3caabd873322..6cf6f6df276e 100644
--- a/drivers/soc/qcom/apr.c
+++ b/drivers/soc/qcom/apr.c
@@ -40,8 +40,8 @@ struct packet_router {
 
 struct apr_rx_buf {
 	struct list_head node;
-	int len;
-	uint8_t buf[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(uint8_t, buf);
 };
 
 /**
@@ -162,7 +162,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf,
 				  int len, void *priv, u32 addr)
 {
 	struct packet_router *apr = dev_get_drvdata(&rpdev->dev);
-	struct apr_rx_buf *abuf;
+	struct apr_rx_buf *abuf = NULL;
 	unsigned long flags;
 
 	if (len <= APR_HDR_SIZE) {
@@ -171,13 +171,9 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf,
 		return -EINVAL;
 	}
 
-	abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC);
-	if (!abuf)
+	if (mem_to_flex_dup(&abuf, buf, len, GFP_ATOMIC))
 		return -ENOMEM;
 
-	abuf->len = len;
-	memcpy(abuf->buf, buf, len);
-
 	spin_lock_irqsave(&apr->rx_lock, flags);
 	list_add_tail(&abuf->node, &apr->rx_list);
 	spin_unlock_irqrestore(&apr->rx_lock, flags);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 22/32] atags_proc: Use mem_to_flex_dup() with struct buffer
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (20 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 21/32] soc: qcom: apr: Use mem_to_flex_dup() with struct apr_rx_buf Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 23/32] Bluetooth: Use mem_to_flex_dup() with struct hci_op_configure_data_path Kees Cook
                   ` (11 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Russell King, Christian Brauner, Andrew Morton,
	Muchun Song, linux-arm-kernel, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Göttsche,
	Christian Lamparter, Chris Zankel, Cong Wang, Daniel Axtens,
	Daniel Vetter, Dan Williams, David Gow, David Howells,
	David S. Miller, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-msm, linux-bluetooth, linux-hardening,
	linux-hyperv, linux-integrity, linux-rdma, linux-scsi,
	linux-security-module, linux-usb, linux-wireless, linux-xtensa,
	llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Nathan Chancellor,
	netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Russell King <linux@armlinux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Muchun Song <songmuchun@bytedance.com>
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/arm/kernel/atags_proc.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c
index 3ec2afe78423..638bbb616daa 100644
--- a/arch/arm/kernel/atags_proc.c
+++ b/arch/arm/kernel/atags_proc.c
@@ -6,8 +6,8 @@
 #include <asm/page.h>
 
 struct buffer {
-	size_t size;
-	char data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, size);
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, data);
 };
 
 static ssize_t atags_read(struct file *file, char __user *buf,
@@ -38,7 +38,7 @@ static int __init init_atags_procfs(void)
 	 */
 	struct proc_dir_entry *tags_entry;
 	struct tag *tag = (struct tag *)atags_copy;
-	struct buffer *b;
+	struct buffer *b = NULL;
 	size_t size;
 
 	if (tag->hdr.tag != ATAG_CORE) {
@@ -54,13 +54,9 @@ static int __init init_atags_procfs(void)
 
 	WARN_ON(tag->hdr.tag != ATAG_NONE);
 
-	b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
-	if (!b)
+	if (mem_to_flex_dup(&b, atags_copy, size, GFP_KERNEL))
 		goto nomem;
 
-	b->size = size;
-	memcpy(b->data, atags_copy, size);
-
 	tags_entry = proc_create_data("atags", 0400, NULL, &atags_proc_ops, b);
 	if (!tags_entry)
 		goto nomem;
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 23/32] Bluetooth: Use mem_to_flex_dup() with struct hci_op_configure_data_path
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (21 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 22/32] atags_proc: Use mem_to_flex_dup() with struct buffer Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 24/32] IB/hfi1: Use mem_to_flex_dup() for struct tid_rb_node Kees Cook
                   ` (10 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Marcel Holtmann, Johan Hedberg,
	Luiz Augusto von Dentz, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-bluetooth, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johannes Berg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Marc Dionne, Mark Brown, Martin K. Petersen,
	Max Filippov, Mimi Zohar, Muchun Song, Nathan Chancellor,
	Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-bluetooth@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/net/bluetooth/hci.h | 4 ++--
 net/bluetooth/hci_request.c | 9 ++-------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 62a9bb022aed..7b398ef0b46d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1321,8 +1321,8 @@ struct hci_rp_read_local_oob_ext_data {
 struct hci_op_configure_data_path {
 	__u8	direction;
 	__u8	data_path_id;
-	__u8	vnd_len;
-	__u8	vnd_data[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u8, vnd_len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(__u8, vnd_data);
 } __packed;
 
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index f4afe482e300..e29be3810b93 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -2435,19 +2435,14 @@ int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec)
 	if (err < 0)
 		goto error;
 
-	cmd = kzalloc(sizeof(*cmd) + vnd_len, GFP_KERNEL);
-	if (!cmd) {
-		err = -ENOMEM;
+	err = mem_to_flex_dup(&cmd, vnd_data, vnd_len, GFP_KERNEL);
+	if (err < 0)
 		goto error;
-	}
 
 	err = hdev->get_data_path_id(hdev, &cmd->data_path_id);
 	if (err < 0)
 		goto error;
 
-	cmd->vnd_len = vnd_len;
-	memcpy(cmd->vnd_data, vnd_data, vnd_len);
-
 	cmd->direction = 0x00;
 	hci_req_add(&req, HCI_CONFIGURE_DATA_PATH, sizeof(*cmd) + vnd_len, cmd);
 
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 24/32] IB/hfi1: Use mem_to_flex_dup() for struct tid_rb_node
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (22 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 23/32] Bluetooth: Use mem_to_flex_dup() with struct hci_op_configure_data_path Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 25/32] Drivers: hv: utils: Use mem_to_flex_dup() with struct cn_msg Kees Cook
                   ` (9 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Dennis Dalessandro, Jason Gunthorpe, Leon Romanovsky,
	linux-rdma, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Liam Girdwood, linux1394-devel, linux-afs,
	linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-scsi,
	linux-security-module, linux-usb, linux-wireless, linux-xtensa,
	llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: linux-rdma@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/infiniband/hw/hfi1/user_exp_rcv.c | 7 ++-----
 drivers/infiniband/hw/hfi1/user_exp_rcv.h | 4 ++--
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
index 186d30291260..f14846662ac9 100644
--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c
+++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
@@ -683,7 +683,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
 {
 	int ret;
 	struct hfi1_ctxtdata *uctxt = fd->uctxt;
-	struct tid_rb_node *node;
+	struct tid_rb_node *node = NULL;
 	struct hfi1_devdata *dd = uctxt->dd;
 	dma_addr_t phys;
 	struct page **pages = tbuf->pages + pageidx;
@@ -692,8 +692,7 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
 	 * Allocate the node first so we can handle a potential
 	 * failure before we've programmed anything.
 	 */
-	node = kzalloc(struct_size(node, pages, npages), GFP_KERNEL);
-	if (!node)
+	if (mem_to_flex_dup(&node, pages, npages, GFP_KERNEL))
 		return -ENOMEM;
 
 	phys = dma_map_single(&dd->pcidev->dev, __va(page_to_phys(pages[0])),
@@ -707,12 +706,10 @@ static int set_rcvarray_entry(struct hfi1_filedata *fd,
 
 	node->fdata = fd;
 	node->phys = page_to_phys(pages[0]);
-	node->npages = npages;
 	node->rcventry = rcventry;
 	node->dma_addr = phys;
 	node->grp = grp;
 	node->freed = false;
-	memcpy(node->pages, pages, flex_array_size(node, pages, npages));
 
 	if (fd->use_mn) {
 		ret = mmu_interval_notifier_insert(
diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.h b/drivers/infiniband/hw/hfi1/user_exp_rcv.h
index 8c53e416bf84..4be3446c4d25 100644
--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.h
+++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.h
@@ -32,8 +32,8 @@ struct tid_rb_node {
 	u32 rcventry;
 	dma_addr_t dma_addr;
 	bool freed;
-	unsigned int npages;
-	struct page *pages[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned int, npages);
+	DECLARE_FLEX_ARRAY_ELEMENTS(struct page *, pages);
 };
 
 static inline int num_user_pages(unsigned long addr,
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 25/32] Drivers: hv: utils: Use mem_to_flex_dup() with struct cn_msg
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (23 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 24/32] IB/hfi1: Use mem_to_flex_dup() for struct tid_rb_node Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 26/32] ima: Use mem_to_flex_dup() with struct modsig Kees Cook
                   ` (8 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
	Wei Liu, Dexuan Cui, linux-hyperv, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dmitry Kasatkin, Eli Cohen,
	Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Francis Laniel, Frank Rowand, Franky Lin, Greg Kroah-Hartman,
	Gregory Greenman, Guenter Roeck, Hante Meuleman, Herbert Xu,
	Hulk Robot, Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, Lars-Peter Clausen, Lee Jones,
	Leon Romanovsky, Liam Girdwood, linux1394-devel, linux-afs,
	linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-integrity, linux-rdma, linux-scsi,
	linux-security-module, linux-usb, linux-wireless, linux-xtensa,
	llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: linux-hyperv@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/hv/hv_utils_transport.c | 7 ++-----
 include/uapi/linux/connector.h  | 4 ++--
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c
index 832885198643..43b4f8893cc0 100644
--- a/drivers/hv/hv_utils_transport.c
+++ b/drivers/hv/hv_utils_transport.c
@@ -217,20 +217,17 @@ static void hvt_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 int hvutil_transport_send(struct hvutil_transport *hvt, void *msg, int len,
 			  void (*on_read_cb)(void))
 {
-	struct cn_msg *cn_msg;
+	struct cn_msg *cn_msg = NULL;
 	int ret = 0;
 
 	if (hvt->mode == HVUTIL_TRANSPORT_INIT ||
 	    hvt->mode == HVUTIL_TRANSPORT_DESTROY) {
 		return -EINVAL;
 	} else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) {
-		cn_msg = kzalloc(sizeof(*cn_msg) + len, GFP_ATOMIC);
-		if (!cn_msg)
+		if (mem_to_flex_dup(&cn_msg, msg, len, GFP_ATOMIC))
 			return -ENOMEM;
 		cn_msg->id.idx = hvt->cn_id.idx;
 		cn_msg->id.val = hvt->cn_id.val;
-		cn_msg->len = len;
-		memcpy(cn_msg->data, msg, len);
 		ret = cn_netlink_send(cn_msg, 0, 0, GFP_ATOMIC);
 		kfree(cn_msg);
 		/*
diff --git a/include/uapi/linux/connector.h b/include/uapi/linux/connector.h
index 3738936149a2..b85bbe753dae 100644
--- a/include/uapi/linux/connector.h
+++ b/include/uapi/linux/connector.h
@@ -73,9 +73,9 @@ struct cn_msg {
 	__u32 seq;
 	__u32 ack;
 
-	__u16 len;		/* Length of the following data */
+	__DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, len);
 	__u16 flags;
-	__u8 data[0];
+	__DECLARE_FLEX_ARRAY_ELEMENTS(__u8, data);
 };
 
 #endif /* _UAPI__CONNECTOR_H */
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 26/32] ima: Use mem_to_flex_dup() with struct modsig
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (24 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 25/32] Drivers: hv: utils: Use mem_to_flex_dup() with struct cn_msg Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 27/32] KEYS: Use mem_to_flex_dup() with struct user_key_payload Kees Cook
                   ` (7 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Mimi Zohar, Dmitry Kasatkin, James Morris,
	Serge E. Hallyn, linux-integrity, linux-security-module,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-rdma, linux-scsi, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Muchun Song, Nathan Chancellor, netdev, Nick Desaulniers,
	Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, SHA-cyfmac-dev-list, Simon Horman, Stefano Stabellini,
	Stefan Richter, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Mimi Zohar <zohar@linux.ibm.com>
Cc: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: linux-integrity@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 security/integrity/ima/ima_modsig.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
index fb25723c65bc..200c080d36de 100644
--- a/security/integrity/ima/ima_modsig.c
+++ b/security/integrity/ima/ima_modsig.c
@@ -28,8 +28,8 @@ struct modsig {
 	 * This is what will go to the measurement list if the template requires
 	 * storing the signature.
 	 */
-	int raw_pkcs7_len;
-	u8 raw_pkcs7[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, raw_pkcs7_len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, raw_pkcs7);
 };
 
 /*
@@ -42,7 +42,7 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
 {
 	const size_t marker_len = strlen(MODULE_SIG_STRING);
 	const struct module_signature *sig;
-	struct modsig *hdr;
+	struct modsig *hdr = NULL;
 	size_t sig_len;
 	const void *p;
 	int rc;
@@ -65,8 +65,7 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
 	buf_len -= sig_len + sizeof(*sig);
 
 	/* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */
-	hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL);
-	if (!hdr)
+	if (mem_to_flex_dup(&hdr, buf + buf_len, sig_len, GFP_KERNEL))
 		return -ENOMEM;
 
 	hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len);
@@ -76,9 +75,6 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
 		return rc;
 	}
 
-	memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len);
-	hdr->raw_pkcs7_len = sig_len;
-
 	/* We don't know the hash algorithm yet. */
 	hdr->hash_algo = HASH_ALGO__LAST;
 
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 27/32] KEYS: Use mem_to_flex_dup() with struct user_key_payload
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (25 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 26/32] ima: Use mem_to_flex_dup() with struct modsig Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab Kees Cook
                   ` (6 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, David Howells, Jarkko Sakkinen, James Morris,
	Serge E. Hallyn, keyrings, linux-security-module,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David S. Miller, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, Jaroslav Kysela,
	Jason Gunthorpe, Jens Axboe, Johan Hedberg, Johannes Berg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-usb, linux-wireless, linux-xtensa,
	llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, SHA-cyfmac-dev-list, Simon Horman, Stefano Stabellini,
	Stefan Richter, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: David Howells <dhowells@redhat.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: keyrings@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/keys/user-type.h     | 4 ++--
 security/keys/user_defined.c | 7 ++-----
 2 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 386c31432789..4e67ff902a32 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -26,8 +26,8 @@
  */
 struct user_key_payload {
 	struct rcu_head	rcu;		/* RCU destructor */
-	unsigned short	datalen;	/* length of this data */
-	char		data[] __aligned(__alignof__(u64)); /* actual data */
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned short, datalen);
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, data) __aligned(__alignof__(u64));
 };
 
 extern struct key_type key_type_user;
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 749e2a4dcb13..2fb84894cdaa 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -58,21 +58,18 @@ EXPORT_SYMBOL_GPL(key_type_logon);
  */
 int user_preparse(struct key_preparsed_payload *prep)
 {
-	struct user_key_payload *upayload;
+	struct user_key_payload *upayload = NULL;
 	size_t datalen = prep->datalen;
 
 	if (datalen <= 0 || datalen > 32767 || !prep->data)
 		return -EINVAL;
 
-	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
-	if (!upayload)
+	if (mem_to_flex_dup(&upayload, prep->data, datalen, GFP_KERNEL))
 		return -ENOMEM;
 
 	/* attach the data */
 	prep->quotalen = datalen;
 	prep->payload.data[0] = upayload;
-	upayload->datalen = datalen;
-	memcpy(upayload->data, prep->data, datalen);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(user_preparse);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (26 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 27/32] KEYS: Use mem_to_flex_dup() with struct user_key_payload Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04 22:57   ` Paul Moore
  2022-05-04  1:44 ` [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property Kees Cook
                   ` (5 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Steffen Klassert, Herbert Xu, David S. Miller,
	Paul Moore, Stephen Smalley, Eric Paris, Nick Desaulniers,
	Xiu Jianfeng, Christian Göttsche, netdev, selinux,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying:

    struct xfrm_sec_ctx
    struct sidtab_str_cache

Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Xiu Jianfeng <xiujianfeng@huawei.com>
Cc: "Christian Göttsche" <cgzones@googlemail.com>
Cc: netdev@vger.kernel.org
Cc: selinux@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 include/uapi/linux/xfrm.h    | 4 ++--
 security/selinux/ss/sidtab.c | 9 +++------
 security/selinux/xfrm.c      | 7 ++-----
 3 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index 65e13a099b1a..4a6fa2beff6a 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -31,9 +31,9 @@ struct xfrm_id {
 struct xfrm_sec_ctx {
 	__u8	ctx_doi;
 	__u8	ctx_alg;
-	__u16	ctx_len;
+	__DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
 	__u32	ctx_sid;
-	char	ctx_str[0];
+	__DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
 };
 
 /* Security Context Domains of Interpretation */
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index a54b8652bfb5..a9d434e8cff7 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -23,8 +23,8 @@ struct sidtab_str_cache {
 	struct rcu_head rcu_member;
 	struct list_head lru_member;
 	struct sidtab_entry *parent;
-	u32 len;
-	char str[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, str);
 };
 
 #define index_to_sid(index) ((index) + SECINITSID_NUM + 1)
@@ -570,8 +570,7 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
 		goto out_unlock;
 	}
 
-	cache = kmalloc(struct_size(cache, str, str_len), GFP_ATOMIC);
-	if (!cache)
+	if (mem_to_flex_dup(&cache, str, str_len, GFP_ATOMIC))
 		goto out_unlock;
 
 	if (s->cache_free_slots == 0) {
@@ -584,8 +583,6 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
 		s->cache_free_slots--;
 	}
 	cache->parent = entry;
-	cache->len = str_len;
-	memcpy(cache->str, str, str_len);
 	list_add(&cache->lru_member, &s->cache_lru_list);
 
 	rcu_assign_pointer(entry->cache, cache);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index c576832febc6..bc7a54bf8f0d 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -345,7 +345,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
 				     struct xfrm_sec_ctx *polsec, u32 secid)
 {
 	int rc;
-	struct xfrm_sec_ctx *ctx;
+	struct xfrm_sec_ctx *ctx = NULL;
 	char *ctx_str = NULL;
 	u32 str_len;
 
@@ -360,8 +360,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
 	if (rc)
 		return rc;
 
-	ctx = kmalloc(struct_size(ctx, ctx_str, str_len), GFP_ATOMIC);
-	if (!ctx) {
+	if (mem_to_flex_dup(&ctx, ctx_str, str_len, GFP_ATOMIC)) {
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -369,8 +368,6 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
 	ctx->ctx_doi = XFRM_SC_DOI_LSM;
 	ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
 	ctx->ctx_sid = secid;
-	ctx->ctx_len = str_len;
-	memcpy(ctx->ctx_str, ctx_str, str_len);
 
 	x->security = ctx;
 	atomic_inc(&selinux_xfrm_refcount);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (27 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04 18:09     ` Rob Herring
  2022-05-04  1:44 ` [PATCH 30/32] usb: gadget: f_fs: Use mem_to_flex_dup() with struct ffs_buffer Kees Cook
                   ` (4 subsequent siblings)
  33 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Chris Zankel, Max Filippov, Rob Herring, Frank Rowand,
	Guenter Roeck, linux-xtensa, devicetree, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Haiyang Zhang,
	Hante Meuleman, Herbert Xu, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Mimi Zohar, Muchun Song, Nathan Chancellor,
	netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Chris Zankel <chris@zankel.net>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Frank Rowand <frowand.list@gmail.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-xtensa@linux-xtensa.org
Cc: devicetree@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 arch/xtensa/platforms/xtfpga/setup.c | 9 +++------
 include/linux/of.h                   | 3 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
index 538e6748e85a..31c1fa4ba4ec 100644
--- a/arch/xtensa/platforms/xtfpga/setup.c
+++ b/arch/xtensa/platforms/xtfpga/setup.c
@@ -102,7 +102,7 @@ CLK_OF_DECLARE(xtfpga_clk, "cdns,xtfpga-clock", xtfpga_clk_setup);
 #define MAC_LEN 6
 static void __init update_local_mac(struct device_node *node)
 {
-	struct property *newmac;
+	struct property *newmac = NULL;
 	const u8* macaddr;
 	int prop_len;
 
@@ -110,19 +110,16 @@ static void __init update_local_mac(struct device_node *node)
 	if (macaddr == NULL || prop_len != MAC_LEN)
 		return;
 
-	newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL);
-	if (newmac == NULL)
+	if (mem_to_flex_dup(&newmac, macaddr, MAC_LEN, GFP_KERNEL))
 		return;
 
-	newmac->value = newmac + 1;
-	newmac->length = MAC_LEN;
+	newmac->value = newmac->contents;
 	newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
 	if (newmac->name == NULL) {
 		kfree(newmac);
 		return;
 	}
 
-	memcpy(newmac->value, macaddr, MAC_LEN);
 	((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f;
 	of_update_property(node, newmac);
 }
diff --git a/include/linux/of.h b/include/linux/of.h
index 17741eee0ca4..efb0f419fd1f 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -30,7 +30,7 @@ typedef u32 ihandle;
 
 struct property {
 	char	*name;
-	int	length;
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, length);
 	void	*value;
 	struct property *next;
 #if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
@@ -42,6 +42,7 @@ struct property {
 #if defined(CONFIG_OF_KOBJ)
 	struct bin_attribute attr;
 #endif
+	DECLARE_FLEX_ARRAY_ELEMENTS(u8, contents);
 };
 
 #if defined(CONFIG_SPARC)
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 30/32] usb: gadget: f_fs: Use mem_to_flex_dup() with struct ffs_buffer
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (28 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 31/32] xenbus: Use mem_to_flex_dup() with struct read_buffer Kees Cook
                   ` (3 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Felipe Balbi, Greg Kroah-Hartman, Eugeniu Rosca,
	John Keeping, Jens Axboe, Udipto Goswami, Andrew Gabbasov,
	linux-usb, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Francis Laniel, Frank Rowand, Franky Lin, Gregory Greenman,
	Guenter Roeck, Haiyang Zhang, Hante Meuleman, Herbert Xu,
	Hulk Robot, Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Johan Hedberg,
	Johannes Berg, Johannes Berg, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Eugeniu Rosca <erosca@de.adit-jv.com>
Cc: John Keeping <john@metanate.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Udipto Goswami <quic_ugoswami@quicinc.com>
Cc: Andrew Gabbasov <andrew_gabbasov@mentor.com>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/usb/gadget/function/f_fs.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 4585ee3a444a..bb0ff41dabd2 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -202,9 +202,9 @@ struct ffs_epfile {
 };
 
 struct ffs_buffer {
-	size_t length;
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, length);
 	char *data;
-	char storage[];
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, storage);
 };
 
 /*  ffs_io_data structure ***************************************************/
@@ -905,7 +905,7 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
 				      void *data, int data_len,
 				      struct iov_iter *iter)
 {
-	struct ffs_buffer *buf;
+	struct ffs_buffer *buf = NULL;
 
 	ssize_t ret = copy_to_iter(data, data_len, iter);
 	if (data_len == ret)
@@ -919,12 +919,9 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
 		data_len, ret);
 
 	data_len -= ret;
-	buf = kmalloc(struct_size(buf, storage, data_len), GFP_KERNEL);
-	if (!buf)
+	if (mem_to_flex_dup(&buf, data + ret, data_len, GFP_KERNEL))
 		return -ENOMEM;
-	buf->length = data_len;
 	buf->data = buf->storage;
-	memcpy(buf->storage, data + ret, flex_array_size(buf, storage, data_len));
 
 	/*
 	 * At this point read_buffer is NULL or READ_BUFFER_DROP (if
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 31/32] xenbus: Use mem_to_flex_dup() with struct read_buffer
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (29 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 30/32] usb: gadget: f_fs: Use mem_to_flex_dup() with struct ffs_buffer Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-04  1:44 ` [PATCH 32/32] esas2r: Use __mem_to_flex() with struct atto_ioctl Kees Cook
                   ` (2 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Boris Ostrovsky, Juergen Gross, Stefano Stabellini,
	xen-devel, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefan Richter, Steffen Klassert, Stephen Hemminger,
	Stephen Smalley, Tadeusz Struk, Takashi Iwai, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying.

Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/xen/xenbus/xenbus_dev_frontend.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c
index 597af455a522..4267aaef33fb 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -81,8 +81,8 @@ struct xenbus_transaction_holder {
 struct read_buffer {
 	struct list_head list;
 	unsigned int cons;
-	unsigned int len;
-	char msg[];
+	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned int, len);
+	DECLARE_FLEX_ARRAY_ELEMENTS(char, msg);
 };
 
 struct xenbus_file_priv {
@@ -188,21 +188,17 @@ static ssize_t xenbus_file_read(struct file *filp,
  */
 static int queue_reply(struct list_head *queue, const void *data, size_t len)
 {
-	struct read_buffer *rb;
+	struct read_buffer *rb = NULL;
 
 	if (len == 0)
 		return 0;
 	if (len > XENSTORE_PAYLOAD_MAX)
 		return -EINVAL;
 
-	rb = kmalloc(sizeof(*rb) + len, GFP_KERNEL);
-	if (rb == NULL)
+	if (mem_to_flex_dup(&rb, data, len, GFP_KERNEL))
 		return -ENOMEM;
 
 	rb->cons = 0;
-	rb->len = len;
-
-	memcpy(rb->msg, data, len);
 
 	list_add_tail(&rb->list, queue);
 	return 0;
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* [PATCH 32/32] esas2r: Use __mem_to_flex() with struct atto_ioctl
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
                   ` (30 preceding siblings ...)
  2022-05-04  1:44 ` [PATCH 31/32] xenbus: Use mem_to_flex_dup() with struct read_buffer Kees Cook
@ 2022-05-04  1:44 ` Kees Cook
  2022-05-12 21:41   ` David Howells
  2022-05-12 21:47   ` David Howells
  33 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  1:44 UTC (permalink / raw)
  To: Gustavo A . R . Silva
  Cc: Kees Cook, Bradley Grove, James E.J. Bottomley,
	Martin K. Petersen, linux-scsi, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James Morris, Jarkko Sakkinen, Jaroslav Kysela,
	Jason Gunthorpe, Jens Axboe, Johan Hedberg, Johannes Berg,
	Johannes Berg, John Keeping, Juergen Gross, Kalle Valo,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Max Filippov, Mimi Zohar,
	Muchun Song, Nathan Chancellor, netdev, Nick Desaulniers,
	Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

As part of the work to perform bounds checking on all memcpy() uses,
replace the open-coded a deserialization of bytes out of memory into a
trailing flexible array by using a flex_array.h helper to perform the
allocation, bounds checking, and copying. This requires adding the
flexible array explicitly.

Cc: Bradley Grove <linuxdrivers@attotech.com>
Cc: "James E.J. Bottomley" <jejb@linux.ibm.com>
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
---
 drivers/scsi/esas2r/atioctl.h      |  1 +
 drivers/scsi/esas2r/esas2r_ioctl.c | 11 +++++++----
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/esas2r/atioctl.h b/drivers/scsi/esas2r/atioctl.h
index ff2ad9b38575..dd3437412ffc 100644
--- a/drivers/scsi/esas2r/atioctl.h
+++ b/drivers/scsi/esas2r/atioctl.h
@@ -831,6 +831,7 @@ struct __packed atto_hba_trace {
 	u32 total_length;
 	u32 trace_mask;
 	u8 reserved2[48];
+	u8 contents[];
 };
 
 #define ATTO_FUNC_SCSI_PASS_THRU     0x04
diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c
index 08f4e43c7d9e..9310b54b1575 100644
--- a/drivers/scsi/esas2r/esas2r_ioctl.c
+++ b/drivers/scsi/esas2r/esas2r_ioctl.c
@@ -947,11 +947,14 @@ static int hba_ioctl_callback(struct esas2r_adapter *a,
 					break;
 				}
 
-				memcpy(trc + 1,
-				       a->fw_coredump_buff + offset,
-				       len);
+				if (__mem_to_flex(hi, data.trace.contents,
+						  data_length,
+						  a->fw_coredump_buff + offset,
+						  len)) {
+					hi->status = ATTO_STS_INV_FUNC;
+					break;
+				}
 
-				hi->data_length = len;
 			} else if (trc->trace_func == ATTO_TRC_TF_RESET) {
 				memset(a->fw_coredump_buff, 0,
 				       ESAS2R_FWCOREDUMP_SZ);
-- 
2.32.0


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 03/32] flex_array: Add Kunit tests
  2022-05-04  1:44 ` [PATCH 03/32] flex_array: Add Kunit tests Kees Cook
@ 2022-05-04  3:00   ` David Gow
  2022-05-04 19:43     ` Kees Cook
  2022-05-04 19:58   ` Daniel Latypov
  1 sibling, 1 reply; 71+ messages in thread
From: David Gow @ 2022-05-04  3:00 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, KUnit Development, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Howells, David S. Miller, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eric Paris, Eugeniu Rosca, Felipe Balbi, Francis Laniel,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Guenter Roeck, Haiyang Zhang, Hante Meuleman, Herbert Xu,
	Hulk Robot, Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, Linux ARM, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Networking, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Wed, May 4, 2022 at 9:47 AM Kees Cook <keescook@chromium.org> wrote:
>
> Add tests for the new flexible array structure helpers. These can be run
> with:
>
>   make ARCH=um mrproper
>   ./tools/testing/kunit/kunit.py config

Nit: it shouldn't be necessary to run kunit.py config separately:
kunit.py run will configure the kernel if necessary.

>   ./tools/testing/kunit/kunit.py run flex_array
>
> Cc: David Gow <davidgow@google.com>
> Cc: kunit-dev@googlegroups.com
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---

This looks pretty good to me: it certainly worked on the different
setups I tried (um, x86_64, x86_64+KASAN).

A few minor nitpicks inline, mostly around minor config-y things, or
things which weren't totally clear on my first read-through.

Hopefully one day, with the various stubbing features or something
similar, we'll be able to check against allocation failures in
flex_dup(), too, but otherwise nothing seems too obviously missing.

Reviewed-by: David Gow <davidgow@google.com>

-- David

>  lib/Kconfig.debug      |  12 +-
>  lib/Makefile           |   1 +
>  lib/flex_array_kunit.c | 523 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 531 insertions(+), 5 deletions(-)
>  create mode 100644 lib/flex_array_kunit.c
>
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 9077bb38bc93..8bae6b169c50 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -2551,11 +2551,6 @@ config OVERFLOW_KUNIT_TEST
>           Builds unit tests for the check_*_overflow(), size_*(), allocation, and
>           related functions.
>
> -         For more information on KUnit and unit tests in general please refer
> -         to the KUnit documentation in Documentation/dev-tools/kunit/.
> -
> -         If unsure, say N.
> -

Nit: while I'm not against removing some of this boilerplate, is it
better suited for a separate commit?

>  config STACKINIT_KUNIT_TEST
>         tristate "Test level of stack variable initialization" if !KUNIT_ALL_TESTS
>         depends on KUNIT
> @@ -2567,6 +2562,13 @@ config STACKINIT_KUNIT_TEST
>           CONFIG_GCC_PLUGIN_STRUCTLEAK, CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF,
>           or CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL.
>
> +config FLEX_ARRAY_KUNIT_TEST
> +       tristate "Test flex_*() family of helper functions at runtime" if !KUNIT_ALL_TESTS
> +       depends on KUNIT
> +       default KUNIT_ALL_TESTS
> +       help
> +         Builds unit tests for flexible array copy helper functions.
> +

Nit: checkpatch warns that the description here may be insufficient:
WARNING: please write a help paragraph that fully describes the config symbol

>  config TEST_UDELAY
>         tristate "udelay test driver"
>         help
> diff --git a/lib/Makefile b/lib/Makefile
> index 6b9ffc1bd1ee..9884318db330 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -366,6 +366,7 @@ obj-$(CONFIG_MEMCPY_KUNIT_TEST) += memcpy_kunit.o
>  obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o
>  CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
>  obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
> +obj-$(CONFIG_FLEX_ARRAY_KUNIT_TEST) += flex_array_kunit.o
>
>  obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
>
> diff --git a/lib/flex_array_kunit.c b/lib/flex_array_kunit.c
> new file mode 100644
> index 000000000000..48bee88945b4
> --- /dev/null
> +++ b/lib/flex_array_kunit.c
> @@ -0,0 +1,523 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Test cases for flex_*() array manipulation helpers.
> + */
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <kunit/test.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/flex_array.h>
> +
> +#define COMPARE_STRUCTS(STRUCT_A, STRUCT_B)    do {                    \
> +       STRUCT_A *ptr_A;                                                \
> +       STRUCT_B *ptr_B;                                                \
> +       int rc;                                                         \
> +       size_t size_A, size_B;                                          \
> +                                                                       \
> +       /* matching types for flex array elements and count */          \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_A), sizeof(*ptr_B));          \
> +       KUNIT_EXPECT_TRUE(test, __same_type(*ptr_A->data,               \
> +               *ptr_B->__flex_array_elements));                        \
> +       KUNIT_EXPECT_TRUE(test, __same_type(ptr_A->datalen,             \
> +               ptr_B->__flex_array_elements_count));                   \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_A->data),                     \
> +                             sizeof(*ptr_B->__flex_array_elements));   \
> +       KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), data),           \
> +                             offsetof(typeof(*ptr_B),                  \
> +                                      __flex_array_elements));         \
> +       KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), datalen),        \
> +                             offsetof(typeof(*ptr_B),                  \
> +                                      __flex_array_elements_count));   \
> +                                                                       \
> +       /* struct_size() vs __fas_bytes() */                            \
> +       size_A = struct_size(ptr_A, data, 13);                          \
> +       rc = __fas_bytes(ptr_B, __flex_array_elements,                  \
> +                        __flex_array_elements_count, 13, &size_B);     \
> +       KUNIT_EXPECT_EQ(test, rc, 0);                                   \
> +       KUNIT_EXPECT_EQ(test, size_A, size_B);                          \
> +                                                                       \
> +       /* flex_array_size() vs __fas_elements_bytes() */               \
> +       size_A = flex_array_size(ptr_A, data, 13);                      \
> +       rc = __fas_elements_bytes(ptr_B, __flex_array_elements,         \
> +                        __flex_array_elements_count, 13, &size_B);     \
> +       KUNIT_EXPECT_EQ(test, rc, 0);                                   \
> +       KUNIT_EXPECT_EQ(test, size_A, size_B);                          \
> +                                                                       \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_A) + size_A,                  \
> +                             offsetof(typeof(*ptr_A), data) +          \
> +                             (sizeof(*ptr_A->data) * 13));             \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_B) + size_B,                  \
> +                             offsetof(typeof(*ptr_B),                  \
> +                                      __flex_array_elements) +         \
> +                             (sizeof(*ptr_B->__flex_array_elements) *  \
> +                              13));                                    \
> +} while (0)
> +
> +struct normal {
> +       size_t  datalen;
> +       u32     data[];
> +};
> +
> +struct decl_normal {
> +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, datalen);
> +       DECLARE_FLEX_ARRAY_ELEMENTS(u32, data);
> +};
> +
> +struct aligned {
> +       unsigned short  datalen;
> +       char            data[] __aligned(__alignof__(u64));
> +};
> +
> +struct decl_aligned {
> +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned short, datalen);
> +       DECLARE_FLEX_ARRAY_ELEMENTS(char, data) __aligned(__alignof__(u64));
> +};
> +
> +static void struct_test(struct kunit *test)
> +{
> +       COMPARE_STRUCTS(struct normal, struct decl_normal);
> +       COMPARE_STRUCTS(struct aligned, struct decl_aligned);
> +}

If I understand it, the purpose of this is to ensure that structs both
with and without the flexible array declaration have the same memory
layout?

If so, any chance of a comment briefly stating that's the purpose (or
renaming this test struct_layout_test())?

Also, would it make sense to do the same with the struct with internal
padding below?
> +
> +/* Flexible array structure with internal padding. */
> +struct flex_cpy_obj {
> +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, count);
> +       unsigned long empty;
> +       char induce_padding;
> +       /* padding ends up here */
> +       unsigned long after_padding;
> +       DECLARE_FLEX_ARRAY_ELEMENTS(u32, flex);
> +};
> +
> +/* Encapsulating flexible array structure. */
> +struct flex_dup_obj {
> +       unsigned long flags;
> +       int junk;
> +       struct flex_cpy_obj fas;
> +};
> +
> +/* Flexible array struct of only bytes. */
> +struct tiny_flex {
> +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u8, count);
> +       DECLARE_FLEX_ARRAY_ELEMENTS(u8, byte_array);
> +};
> +
> +#define CHECK_COPY(ptr)                do {                                            \
> +       typeof(*(ptr)) *_cc_dst = (ptr);                                        \
> +       KUNIT_EXPECT_EQ(test, _cc_dst->induce_padding, 0);                      \
> +       memcpy(&padding, &_cc_dst->induce_padding + sizeof(_cc_dst->induce_padding), \
> +              sizeof(padding));                                                \
> +       /* Padding should be zero too. */                                       \
> +       KUNIT_EXPECT_EQ(test, padding, 0);                                      \
> +       KUNIT_EXPECT_EQ(test, src->count, _cc_dst->count);                      \
> +       KUNIT_EXPECT_EQ(test, _cc_dst->count, TEST_TARGET);                     \
> +       for (i = 0; i < _cc_dst->count - 1; i++) {                              \
> +               /* 'A' is 0x41, and here repeated in a u32. */                  \

Would it be simpler to just note that the magic value is 0x41, rather
than have it be the character 'A'?

> +               KUNIT_EXPECT_EQ(test, _cc_dst->flex[i], 0x41414141);            \
> +       }                                                                       \
> +       /* Last item should be different. */                                    \
> +       KUNIT_EXPECT_EQ(test, _cc_dst->flex[_cc_dst->count - 1], 0x14141414);   \
> +} while (0)
> +
> +/* Test copying from one flexible array struct into another. */
> +static void flex_cpy_test(struct kunit *test)
> +{
> +#define TEST_BOUNDS    13
> +#define TEST_TARGET    12
> +#define TEST_SMALL     10
> +       struct flex_cpy_obj *src, *dst;
> +       unsigned long padding;
> +       int i, rc;
> +
> +       /* Prepare open-coded source. */
> +       src = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);
> +       src->count = TEST_BOUNDS;
> +       memset(src->flex, 'A', flex_array_size(src, flex, TEST_BOUNDS));

As above, it's possibly nicer to just state 0x41 here, rather than
'A', since all we're doing is checking against a hex value.

> +       src->flex[src->count - 2] = 0x14141414;
> +       src->flex[src->count - 1] = 0x24242424;
> +
> +       /* Prepare open-coded destination, alloc only. */
> +       dst = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);
> +       /* Pre-fill with 0xFE marker. */
> +       memset(dst, 0xFE, struct_size(src, flex, TEST_BOUNDS));
> +       /* Pretend we're 1 element smaller. */
> +       dst->count = TEST_TARGET;
> +
> +       /* Pretend to match the target destination size. */
> +       src->count = TEST_TARGET;
> +
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       CHECK_COPY(dst);
> +       /* Item past last copied item is unchanged from initial memset. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
> +
> +       /* Now trip overflow, and verify we didn't clobber beyond end. */
> +       src->count = TEST_BOUNDS;
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Item past last copied item is unchanged from initial memset. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
> +
> +       /* Reset destination contents. */
> +       memset(dst, 0xFD, struct_size(src, flex, TEST_BOUNDS));
> +       dst->count = TEST_TARGET;
> +
> +       /* Copy less than max. */
> +       src->count = TEST_SMALL;
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       /* Verify count was adjusted. */
> +       KUNIT_EXPECT_EQ(test, dst->count, TEST_SMALL);
> +       /* Verify element beyond src size was wiped. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_SMALL], 0);
> +       /* Verify element beyond original dst size was untouched. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_TARGET], 0xFDFDFDFD);
> +
> +       kfree(dst);
> +       kfree(src);
> +#undef TEST_BOUNDS
> +#undef TEST_TARGET
> +#undef TEST_SMALL
> +}
> +
> +static void flex_dup_test(struct kunit *test)
> +{
> +#define TEST_TARGET    12
> +       struct flex_cpy_obj *src, *dst = NULL, **null = NULL;
> +       struct flex_dup_obj *encap = NULL;
> +       unsigned long padding;
> +       int i, rc;
> +
> +       /* Prepare open-coded source. */
> +       src = kzalloc(struct_size(src, flex, TEST_TARGET), GFP_KERNEL);
> +       src->count = TEST_TARGET;
> +       memset(src->flex, 'A', flex_array_size(src, flex, TEST_TARGET));
> +       src->flex[src->count - 1] = 0x14141414;
> +
> +       /* Reject NULL @alloc. */
> +       rc = flex_dup(null, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> +       /* Check good copy. */
> +       rc = flex_dup(&dst, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, dst != NULL);
> +       CHECK_COPY(dst);
> +
> +       /* Reject non-NULL *@alloc. */
> +       rc = flex_dup(&dst, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> +       kfree(dst);
> +
> +       /* Check good encap copy. */
> +       rc = __flex_dup(&encap, .fas, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, dst != NULL);
> +       CHECK_COPY(&encap->fas);
> +       /* Check that items external to "fas" are zero. */
> +       KUNIT_EXPECT_EQ(test, encap->flags, 0);
> +       KUNIT_EXPECT_EQ(test, encap->junk, 0);
> +       kfree(encap);
> +#undef MAGIC_WORD

MAGIC_WORD isn't defined (or used) for flux_dup_test? Is it worth
using it (or something similar) for the 'A' / 0x14141414 and the
CHECK_COPY() macro?

> +#undef TEST_TARGET
> +}
> +
> +static void mem_to_flex_test(struct kunit *test)
> +{
> +#define TEST_TARGET    9
> +#define TEST_MAX       U8_MAX
> +#define MAGIC_WORD     0x03030303
> +       u8 magic_byte = MAGIC_WORD & 0xff;
> +       struct flex_cpy_obj *dst;
> +       size_t big = (size_t)INT_MAX + 1;
> +       char small[] = "Hello";
> +       char *src;
> +       u32 src_len;
> +       int rc;
> +
> +       /* Open coded allocations, 1 larger than actually used. */
> +       src_len = flex_array_size(dst, flex, TEST_MAX + 1);
> +       src = kzalloc(src_len, GFP_KERNEL);
> +       dst = kzalloc(struct_size(dst, flex, TEST_MAX + 1), GFP_KERNEL);
> +       dst->count = TEST_TARGET;
> +
> +       /* Fill source. */
> +       memset(src, magic_byte, src_len);
> +
> +       /* Short copy is fine. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], 0);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +       rc = mem_to_flex(dst, src, 1);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_EXPECT_EQ(test, dst->count, 1);
> +       KUNIT_EXPECT_EQ(test, dst->after_padding, 0);
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +       dst->count = TEST_TARGET;
> +
> +       /* Reject negative elements count. */
> +       rc = mem_to_flex(dst, small, -1);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure dst is unchanged. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +
> +       /* Reject compile-time read overflow. */
> +       rc = mem_to_flex(dst, small, 20);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure dst is unchanged. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +
> +       /* Reject giant buffer source. */
> +       rc = mem_to_flex(dst, small, big);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure dst is unchanged. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +
> +       /* Copy beyond storage size is rejected. */
> +       dst->count = TEST_MAX;
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_MAX - 1], 0);
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_MAX], 0);
> +       rc = mem_to_flex(dst, src, TEST_MAX + 1);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure dst is unchanged. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, dst->flex[1], 0);
> +
> +       kfree(dst);
> +       kfree(src);
> +#undef MAGIC_WORD
> +#undef TEST_MAX
> +#undef TEST_TARGET
> +}
> +
> +static void mem_to_flex_dup_test(struct kunit *test)
> +{
> +#define ELEMENTS_COUNT 259
> +#define MAGIC_WORD     0xABABABAB
> +       u8 magic_byte = MAGIC_WORD & 0xff;
> +       struct flex_dup_obj *obj = NULL;
> +       struct tiny_flex *tiny = NULL, **null = NULL;
> +       size_t src_len, count, big = (size_t)INT_MAX + 1;
> +       char small[] = "Hello";
> +       u8 *src;
> +       int rc;
> +
> +       src_len = struct_size(tiny, byte_array, ELEMENTS_COUNT);
> +       src = kzalloc(src_len, GFP_KERNEL);
> +       KUNIT_ASSERT_TRUE(test, src != NULL);
> +       /* Fill with bytes. */
> +       memset(src, magic_byte, src_len);
> +       KUNIT_EXPECT_EQ(test, src[0], magic_byte);
> +       KUNIT_EXPECT_EQ(test, src[src_len / 2], magic_byte);
> +       KUNIT_EXPECT_EQ(test, src[src_len - 1], magic_byte);
> +
> +       /* Reject storage exceeding elements_count type. */
> +       count = ELEMENTS_COUNT;
> +       rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       KUNIT_EXPECT_TRUE(test, tiny == NULL);
> +
> +       /* Reject negative elements count. */
> +       rc = mem_to_flex_dup(&tiny, src, -1, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       KUNIT_EXPECT_TRUE(test, tiny == NULL);
> +
> +       /* Reject compile-time read overflow. */
> +       rc = mem_to_flex_dup(&tiny, small, 20, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       KUNIT_EXPECT_TRUE(test, tiny == NULL);
> +
> +       /* Reject giant buffer source. */
> +       rc = mem_to_flex_dup(&tiny, small, big, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       KUNIT_EXPECT_TRUE(test, tiny == NULL);
> +
> +       /* Reject NULL @alloc. */
> +       rc = mem_to_flex_dup(null, src, count, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> +       /* Allow reasonable count.*/
> +       count = ELEMENTS_COUNT / 2;
> +       rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, tiny != NULL);
> +       /* Spot check the copy happened. */
> +       KUNIT_EXPECT_EQ(test, tiny->count, count);
> +       KUNIT_EXPECT_EQ(test, tiny->byte_array[0], magic_byte);
> +       KUNIT_EXPECT_EQ(test, tiny->byte_array[count / 2], magic_byte);
> +       KUNIT_EXPECT_EQ(test, tiny->byte_array[count - 1], magic_byte);
> +
> +       /* Reject non-NULL *@alloc. */
> +       rc = mem_to_flex_dup(&tiny, src, count, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +       kfree(tiny);
> +
> +       /* Works with encapsulation too. */
> +       count = ELEMENTS_COUNT / 10;
> +       rc = __mem_to_flex_dup(&obj, .fas, src, count, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, obj != NULL);
> +       /* Spot check the copy happened. */
> +       KUNIT_EXPECT_EQ(test, obj->fas.count, count);
> +       KUNIT_EXPECT_EQ(test, obj->fas.after_padding, 0);
> +       KUNIT_EXPECT_EQ(test, obj->fas.flex[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, obj->fas.flex[count / 2], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, obj->fas.flex[count - 1], MAGIC_WORD);
> +       /* Check members before flexible array struct are zero. */
> +       KUNIT_EXPECT_EQ(test, obj->flags, 0);
> +       KUNIT_EXPECT_EQ(test, obj->junk, 0);
> +       kfree(obj);
> +#undef MAGIC_WORD
> +#undef ELEMENTS_COUNT
> +}
> +
> +static void flex_to_mem_test(struct kunit *test)
> +{
> +#define ELEMENTS_COUNT 200
> +#define MAGIC_WORD     0xF1F2F3F4
> +       struct flex_cpy_obj *src;
> +       typeof(*src->flex) *cast;
> +       size_t src_len = struct_size(src, flex, ELEMENTS_COUNT);
> +       size_t copy_len = flex_array_size(src, flex, ELEMENTS_COUNT);
> +       int i, rc;
> +       size_t bytes = 0;
> +       u8 too_small;
> +       u8 *dst;
> +
> +       /* Create a filled flexible array struct. */
> +       src = kzalloc(src_len, GFP_KERNEL);
> +       KUNIT_ASSERT_TRUE(test, src != NULL);
> +       src->count = ELEMENTS_COUNT;
> +       src->after_padding = 13;
> +       for (i = 0; i < ELEMENTS_COUNT; i++)
> +               src->flex[i] = MAGIC_WORD;
> +
> +       /* Over-allocate space to do past-src_len checking. */
> +       dst = kzalloc(src_len * 2, GFP_KERNEL);
> +       KUNIT_ASSERT_TRUE(test, dst != NULL);
> +       cast = (void *)dst;
> +
> +       /* Fail if dst is too small. */
> +       rc = flex_to_mem(dst, copy_len - 1, src, &bytes);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure nothing was copied. */
> +       KUNIT_EXPECT_EQ(test, bytes, 0);
> +       KUNIT_EXPECT_EQ(test, cast[0], 0);
> +
> +       /* Fail if type too small to hold size of copy. */
> +       KUNIT_EXPECT_GT(test, copy_len, type_max(typeof(too_small)));
> +       rc = flex_to_mem(dst, copy_len, src, &too_small);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Make sure nothing was copied. */
> +       KUNIT_EXPECT_EQ(test, bytes, 0);
> +       KUNIT_EXPECT_EQ(test, cast[0], 0);
> +
> +       /* Check good copy. */
> +       rc = flex_to_mem(dst, copy_len, src, &bytes);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_EXPECT_EQ(test, bytes, copy_len);
> +       /* Spot check the copy */
> +       KUNIT_EXPECT_EQ(test, cast[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT / 2], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT - 1], MAGIC_WORD);
> +       /* Make sure nothing was written after last element. */
> +       KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT], 0);
> +
> +       kfree(dst);
> +       kfree(src);
> +#undef MAGIC_WORD
> +#undef ELEMENTS_COUNT
> +}
> +
> +static void flex_to_mem_dup_test(struct kunit *test)
> +{
> +#define ELEMENTS_COUNT 210
> +#define MAGIC_WORD     0xF0F1F2F3
> +       struct flex_dup_obj *obj, **null = NULL;
> +       struct flex_cpy_obj *src;
> +       typeof(*src->flex) *cast;
> +       size_t obj_len = struct_size(obj, fas.flex, ELEMENTS_COUNT);
> +       size_t src_len = struct_size(src, flex, ELEMENTS_COUNT);
> +       size_t copy_len = flex_array_size(src, flex, ELEMENTS_COUNT);
> +       int i, rc;
> +       size_t bytes = 0;
> +       u8 too_small = 0;
> +       u8 *dst = NULL;
> +
> +       /* Create a filled flexible array struct. */
> +       obj = kzalloc(obj_len, GFP_KERNEL);
> +       KUNIT_ASSERT_TRUE(test, obj != NULL);
> +       obj->fas.count = ELEMENTS_COUNT;
> +       obj->fas.after_padding = 13;
> +       for (i = 0; i < ELEMENTS_COUNT; i++)
> +               obj->fas.flex[i] = MAGIC_WORD;
> +       src = &obj->fas;
> +
> +       /* Fail if type too small to hold size of copy. */
> +       KUNIT_EXPECT_GT(test, src_len, type_max(typeof(too_small)));
> +       rc = flex_to_mem_dup(&dst, &too_small, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       KUNIT_EXPECT_TRUE(test, dst == NULL);
> +       KUNIT_EXPECT_EQ(test, too_small, 0);
> +
> +       /* Fail if @alloc_size is NULL. */
> +       KUNIT_EXPECT_TRUE(test, dst == NULL);
> +       rc = flex_to_mem_dup(&dst, dst, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +       KUNIT_EXPECT_TRUE(test, dst == NULL);
> +
> +       /* Fail if @alloc is NULL. */
> +       rc = flex_to_mem_dup(null, &bytes, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +       KUNIT_EXPECT_TRUE(test, dst == NULL);
> +       KUNIT_EXPECT_EQ(test, bytes, 0);
> +
> +       /* Check good copy. */
> +       rc = flex_to_mem_dup(&dst, &bytes, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_EXPECT_TRUE(test, dst != NULL);
> +       KUNIT_EXPECT_EQ(test, bytes, copy_len);
> +       cast = (void *)dst;
> +       /* Spot check the copy */
> +       KUNIT_EXPECT_EQ(test, cast[0], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT / 2], MAGIC_WORD);
> +       KUNIT_EXPECT_EQ(test, cast[ELEMENTS_COUNT - 1], MAGIC_WORD);
> +
> +       /* Fail if *@alloc is non-NULL. */
> +       bytes = 0;
> +       rc = flex_to_mem_dup(&dst, &bytes, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +       KUNIT_EXPECT_EQ(test, bytes, 0);
> +
> +       kfree(dst);
> +       kfree(obj);
> +#undef MAGIC_WORD
> +#undef ELEMENTS_COUNT
> +}
> +
> +static struct kunit_case flex_array_test_cases[] = {
> +       KUNIT_CASE(struct_test),
> +       KUNIT_CASE(flex_cpy_test),
> +       KUNIT_CASE(flex_dup_test),
> +       KUNIT_CASE(mem_to_flex_test),
> +       KUNIT_CASE(mem_to_flex_dup_test),
> +       KUNIT_CASE(flex_to_mem_test),
> +       KUNIT_CASE(flex_to_mem_dup_test),
> +       {}
> +};
> +
> +static struct kunit_suite flex_array_test_suite = {
> +       .name = "flex_array",
> +       .test_cases = flex_array_test_cases,
> +};
> +
> +kunit_test_suite(flex_array_test_suite);
> +
> +MODULE_LICENSE("GPL");
> --
> 2.32.0
>

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: Introduce flexible array struct memcpy() helpers
  2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
@ 2022-05-04  3:12   ` bluez.test.bot
  2022-05-04  3:31   ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Gustavo A. R. Silva
  1 sibling, 0 replies; 71+ messages in thread
From: bluez.test.bot @ 2022-05-04  3:12 UTC (permalink / raw)
  To: linux-bluetooth, keescook

[-- Attachment #1: Type: text/plain, Size: 9911 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=638153

---Test result---

Test Summary:
CheckPatch                    FAIL      15.45 seconds
GitLint                       FAIL      7.70 seconds
SubjectPrefix                 FAIL      28.23 seconds
BuildKernel                   PASS      36.05 seconds
BuildKernel32                 PASS      34.02 seconds
Incremental Build with patchesPASS      324.75 seconds
TestRunner: Setup             PASS      541.23 seconds
TestRunner: l2cap-tester      PASS      19.53 seconds
TestRunner: bnep-tester       PASS      7.22 seconds
TestRunner: mgmt-tester       PASS      110.30 seconds
TestRunner: rfcomm-tester     PASS      10.98 seconds
TestRunner: sco-tester        PASS      10.26 seconds
TestRunner: smp-tester        PASS      10.29 seconds
TestRunner: userchan-tester   PASS      7.09 seconds

Details
##############################
Test: CheckPatch - FAIL - 15.45 seconds
Run checkpatch.pl script with rule in .checkpatch.conf
[01/32] netlink: Avoid memcpy() across flexible array boundary\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#172: 
memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16)

WARNING:BAD_SIGN_OFF: Non-standard signature: Fixed-by:
#179: 
Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>

total: 0 errors, 2 warnings, 0 checks, 18 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12836836.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[02/32] Introduce flexible array struct memcpy() helpers\Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#300: 
new file mode 100644

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#523: FILE: include/linux/flex_array.h:219:
+	typeof(*(src)) *__fc_src = (src);				\
 	               ^

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#576: FILE: include/linux/flex_array.h:272:
+	typeof(**(alloc)) *__fd_alloc;					\
 	                  ^

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#754: FILE: include/linux/flex_array.h:450:
+	typeof((*__mtfd_alloc)dot_fas_member) *__mtfd_fas;		\
 	                                      ^

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#861: FILE: include/linux/flex_array.h:557:
+	typeof(*(bytes_written)) *__ftm_written = (bytes_written);	\
 	                         ^

ERROR:SPACING: need consistent spacing around '*' (ctx:WxV)
#910: FILE: include/linux/flex_array.h:606:
+	typeof(*(alloc_size)) *__ftmd_alloc_size = (alloc_size);	\
 	                      ^

total: 5 errors, 1 warnings, 662 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12836837.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[03/32] flex_array: Add Kunit tests\Traceback (most recent call last):
  File "scripts/spdxcheck.py", line 6, in <module>
    from ply import lex, yacc
ModuleNotFoundError: No module named 'ply'
WARNING:CONFIG_DESCRIPTION: please write a paragraph that describes the config symbol fully
#205: FILE: lib/Kconfig.debug:2565:
+config FLEX_ARRAY_KUNIT_TEST

WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#228: 
new file mode 100644

total: 0 errors, 2 warnings, 554 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12836839.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[04/32] fortify: Add run-time WARN for cross-field memcpy()\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#178: 
  memcpy: detected field-spanning write (size N) of single field "var->dest" (size M)

total: 0 errors, 1 warnings, 96 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12836838.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.

[07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#176: 
memcpy: detected field-spanning write (size 8) of single field "&res->hdr" (size 4)

total: 0 errors, 1 warnings, 0 checks, 29 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12836846.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL - 7.70 seconds
Run gitlint with rule in .gitlint
[01/32] netlink: Avoid memcpy() across flexible array boundary
7: B1 Line exceeds max length (88>80): "memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16)"
15: B1 Line exceeds max length (90>80): "Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk"

[02/32] Introduce flexible array struct memcpy() helpers
39: B3 Line contains hard tab characters (\t): "        ...		/* arbitrary members */"
40: B3 Line contains hard tab characters (\t): "        u16 part_count;	/* count of elements stored in "parts" below. */"
41: B3 Line contains hard tab characters (\t): "        ...		/* arbitrary members */"
42: B3 Line contains hard tab characters (\t): "        u32 parts[];	/* flexible array with elements of type u32. */"
49: B3 Line contains hard tab characters (\t): "        ...		/* arbitrary members */"
57: B3 Line contains hard tab characters (\t): "        ...		/* arbitrary members */"
58: B3 Line contains hard tab characters (\t): "        u16 part_count;	/* count of elements stored in "parts" below. */"
59: B3 Line contains hard tab characters (\t): "        ...		/* arbitrary members */"
61: B3 Line contains hard tab characters (\t): "            ...		/* other blob members */"

[04/32] fortify: Add run-time WARN for cross-field memcpy()
14: B1 Line exceeds max length (85>80): "  memcpy: detected field-spanning write (size N) of single field "var->dest" (size M)"
38: B3 Line contains hard tab characters (\t): "	void *a;"
39: B3 Line contains hard tab characters (\t): "	int b;"
40: B3 Line contains hard tab characters (\t): "	size_t array_size;"
41: B3 Line contains hard tab characters (\t): "	u32 c;"
42: B3 Line contains hard tab characters (\t): "	u8 flex_array[];"
60: B3 Line contains hard tab characters (\t): "	int foo;"
61: B3 Line contains hard tab characters (\t): "	char bar;"
62: B3 Line contains hard tab characters (\t): "	struct normal_flex_array embedded;"

[07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result
11: B1 Line exceeds max length (83>80): "memcpy: detected field-spanning write (size 8) of single field "&res->hdr" (size 4)"


##############################
Test: SubjectPrefix - FAIL - 28.23 seconds
Check subject contains "Bluetooth" prefix
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject
"Bluetooth: " is not specified in the subject



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary
  2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
  2022-05-04  3:12   ` Introduce flexible array struct memcpy() helpers bluez.test.bot
@ 2022-05-04  3:31   ` Gustavo A. R. Silva
  2022-05-04  3:37     ` Kees Cook
  1 sibling, 1 reply; 71+ messages in thread
From: Gustavo A. R. Silva @ 2022-05-04  3:31 UTC (permalink / raw)
  To: Kees Cook
  Cc: Rasmus Villemoes, David S. Miller, Jakub Kicinski, Rich Felker,
	Eric Dumazet, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Tue, May 03, 2022 at 06:44:10PM -0700, Kees Cook wrote:
> In preparation for run-time memcpy() bounds checking, split the nlmsg
> copying for error messages (which crosses a previous unspecified flexible
> array boundary) in half. Avoids the future run-time warning:
> 
> memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16)
> 
> Creates an explicit flexible array at the end of nlmsghdr for the payload,
> named "nlmsg_payload". There is no impact on UAPI; the sizeof(struct
> nlmsghdr) does not change, but now the compiler can better reason about
> where things are being copied.
> 
> Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
> Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Rich Felker <dalias@aerifal.cx>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: netdev@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  include/uapi/linux/netlink.h | 1 +
>  net/netlink/af_netlink.c     | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
> index 855dffb4c1c3..47f9342d51bc 100644
> --- a/include/uapi/linux/netlink.h
> +++ b/include/uapi/linux/netlink.h
> @@ -47,6 +47,7 @@ struct nlmsghdr {
>  	__u16		nlmsg_flags;	/* Additional flags */
>  	__u32		nlmsg_seq;	/* Sequence number */
>  	__u32		nlmsg_pid;	/* Sending process port ID */
> +	__u8		nlmsg_payload[];/* Contents of message */
>  };
>  
>  /* Flags values */
> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> index 1b5a9c2e1c29..09346aee1022 100644
> --- a/net/netlink/af_netlink.c
> +++ b/net/netlink/af_netlink.c
> @@ -2445,7 +2445,10 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
>  			  NLMSG_ERROR, payload, flags);
>  	errmsg = nlmsg_data(rep);
>  	errmsg->error = err;
> -	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
> +	errmsg->msg = *nlh;
> +	if (payload > sizeof(*errmsg))
> +		memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload,
> +		       nlh->nlmsg_len - sizeof(*nlh));

They have nlmsg_len()[1] for the length of the payload without the header:

/**
 * nlmsg_len - length of message payload
 * @nlh: netlink message header
 */
static inline int nlmsg_len(const struct nlmsghdr *nlh)
{
	return nlh->nlmsg_len - NLMSG_HDRLEN;
}

(would that function use some sanitization, though? what if nlmsg_len is
somehow manipulated to be less than NLMSG_HDRLEN?...)

Also, it seems there is at least one more instance of this same issue:

diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 16ae92054baa..d06184b94af5 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -1723,7 +1723,8 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
                                  nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
                errmsg = nlmsg_data(rep);
                errmsg->error = ret;
-               memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
+               errmsg->msg = *nlh;
+               memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh));
                cmdattr = (void *)&errmsg->msg + min_len;

                ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr,

--
Gustavo

[1] https://elixir.bootlin.com/linux/v5.18-rc5/source/include/net/netlink.h#L577

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary
  2022-05-04  3:31   ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Gustavo A. R. Silva
@ 2022-05-04  3:37     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04  3:37 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Rasmus Villemoes, David S. Miller, Jakub Kicinski, Rich Felker,
	Eric Dumazet, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Tue, May 03, 2022 at 10:31:05PM -0500, Gustavo A. R. Silva wrote:
> On Tue, May 03, 2022 at 06:44:10PM -0700, Kees Cook wrote:
> [...]
> > diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> > index 1b5a9c2e1c29..09346aee1022 100644
> > --- a/net/netlink/af_netlink.c
> > +++ b/net/netlink/af_netlink.c
> > @@ -2445,7 +2445,10 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
> >  			  NLMSG_ERROR, payload, flags);
> >  	errmsg = nlmsg_data(rep);
> >  	errmsg->error = err;
> > -	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
> > +	errmsg->msg = *nlh;
> > +	if (payload > sizeof(*errmsg))
> > +		memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload,
> > +		       nlh->nlmsg_len - sizeof(*nlh));
> 
> They have nlmsg_len()[1] for the length of the payload without the header:
> 
> /**
>  * nlmsg_len - length of message payload
>  * @nlh: netlink message header
>  */
> static inline int nlmsg_len(const struct nlmsghdr *nlh)
> {
> 	return nlh->nlmsg_len - NLMSG_HDRLEN;
> }

Oh, hm, yeah, that would be much cleaner. The relationship between
"payload" and nlmsg_len is confusing in here. :)

So, this should be simpler:

-	memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
+	errmsg->msg = *nlh;
+	memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh));

It's actually this case that triggered my investigation in __bos(1)'s
misbehavior around sub-structs, since this case wasn't getting silenced:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101832

It still feels like it should be possible to get this right without
splitting the memcpy, though. Hmpf.

> (would that function use some sanitization, though? what if nlmsg_len is
> somehow manipulated to be less than NLMSG_HDRLEN?...)

Maybe something like:

static inline int nlmsg_len(const struct nlmsghdr *nlh)
{
	if (WARN_ON(nlh->nlmsg_len < NLMSG_HDRLEN))
		return 0;
	return nlh->nlmsg_len - NLMSG_HDRLEN;
}

> Also, it seems there is at least one more instance of this same issue:
> 
> diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
> index 16ae92054baa..d06184b94af5 100644
> --- a/net/netfilter/ipset/ip_set_core.c
> +++ b/net/netfilter/ipset/ip_set_core.c
> @@ -1723,7 +1723,8 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
>                                   nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
>                 errmsg = nlmsg_data(rep);
>                 errmsg->error = ret;
> -               memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
> +               errmsg->msg = *nlh;
> +               memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh));

Ah, yes, nice catch!

>                 cmdattr = (void *)&errmsg->msg + min_len;
> 
>                 ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr,
> 
> --
> Gustavo
> 
> [1] https://elixir.bootlin.com/linux/v5.18-rc5/source/include/net/netlink.h#L577

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg
  2022-05-04  1:44 ` [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg Kees Cook
@ 2022-05-04  5:42   ` Kalle Valo
  2022-05-04 15:08     ` Kees Cook
  0 siblings, 1 reply; 71+ messages in thread
From: Kalle Valo @ 2022-05-04  5:42 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Loic Poulain, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, wcn36xx,
	linux-wireless, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

Kees Cook <keescook@chromium.org> writes:

> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying.
>
> Cc: Loic Poulain <loic.poulain@linaro.org>
> Cc: Kalle Valo <kvalo@kernel.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: wcn36xx@lists.infradead.org
> Cc: linux-wireless@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>

[...]

> --- a/drivers/net/wireless/ath/wcn36xx/smd.h
> +++ b/drivers/net/wireless/ath/wcn36xx/smd.h
> @@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
>  
>  struct wcn36xx_hal_ind_msg {
>  	struct list_head list;
> -	size_t msg_len;
> -	u8 msg[];
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, msg_len);
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, msg);

This affects readability quite a lot and tbh I don't like it. Isn't
there any simpler way to solve this?

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
@ 2022-05-04  7:25   ` Johannes Berg
  2022-05-04 15:38     ` Kees Cook
  0 siblings, 1 reply; 71+ messages in thread
From: Johannes Berg @ 2022-05-04  7:25 UTC (permalink / raw)
  To: Kees Cook, Gustavo A . R . Silva
  Cc: Keith Packard, Francis Laniel, Daniel Axtens, Dan Williams,
	Vincenzo Frascino, Guenter Roeck, Daniel Vetter, Tadeusz Struk,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang, kvalo

On Tue, 2022-05-03 at 18:44 -0700, Kees Cook wrote:
> 
> For example, using the most complicated helper, mem_to_flex_dup():
> 
>     /* Flexible array struct with members identified. */
>     struct something {
>         int mode;
>         DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, how_many);
>         unsigned long flags;
>         DECLARE_FLEX_ARRAY_ELEMENTS(u32, value);

In many cases, the order of the elements doesn't really matter, so maybe
it'd be nicer to be able to write it as something like

DECLARE_FLEX_STRUCT(something,
	int mode;
	unsigned long flags;
	,
	int, how_many,
	u32, value);

perhaps? OK, that doesn't seem so nice either.

Maybe

struct something {
	int mode;
	unsigned long flags;
	FLEX_ARRAY(
		int, how_many,
		u32, value
	);
};

or so? The long and duplicated DECLARE_FLEX_ARRAY_ELEMENTS_COUNT and
DECLARE_FLEX_ARRAY_ELEMENTS seems a bit tedious to me, at least in cases
where the struct layout is not the most important thing (or it's already
at the end anyway).


>     struct something *instance = NULL;
>     int rc;
> 
>     rc = mem_to_flex_dup(&instance, byte_array, count, GFP_KERNEL);
>     if (rc)
>         return rc;

This seems rather awkward, having to set it to NULL, then checking rc
(and possibly needing a separate variable for it), etc.

But I can understand how you arrived at this:
 - need to pass instance or &instance or such for typeof()
   or offsetof() or such
 - instance = mem_to_flex_dup(instance, ...)
   looks too much like it would actually dup 'instance', rather than
   'byte_array'
 - if you pass &instance anyway, checking for NULL is simple and adds a
   bit of safety

but still, honestly, I don't like it. As APIs go, it feels a bit
cumbersome and awkward to use, and you really need everyone to use this,
and not say "uh what, I'll memcpy() instead".

Maybe there should also be a realloc() version of it?


> +/** __fas_bytes - Calculate potential size of flexible array structure

I think you forgot "\n *" in many cases here after "/**".

johannes

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies
  2022-05-04  1:44 ` [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies Kees Cook
@ 2022-05-04  7:28   ` Johannes Berg
  2022-05-04 15:13     ` Kees Cook
  0 siblings, 1 reply; 71+ messages in thread
From: Johannes Berg @ 2022-05-04  7:28 UTC (permalink / raw)
  To: Kees Cook, Gustavo A . R . Silva
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	linux-wireless, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	John Keeping, Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Tue, 2022-05-03 at 18:44 -0700, Kees Cook wrote:
> 
> @@ -2277,7 +2274,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
>  	size_t ielen = len - offsetof(struct ieee80211_mgmt,
>  				      u.probe_resp.variable);
>  	size_t new_ie_len;
> -	struct cfg80211_bss_ies *new_ies;
> +	struct cfg80211_bss_ies *new_ies = NULL;
>  	const struct cfg80211_bss_ies *old;
>  	u8 cpy_len;
>  
> @@ -2314,8 +2311,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
>  	if (!new_ie)
>  		return;
>  
> -	new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
> -	if (!new_ies)
> +	if (mem_to_flex_dup(&new_ies, new_ie, new_ie_len, GFP_ATOMIC))
>  		goto out_free;
>  
>  	pos = new_ie;
> @@ -2333,10 +2329,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
>  	memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len)));
>  
>  	/* update ie */
> -	new_ies->len = new_ie_len;
>  	new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
>  	new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
> -	memcpy(new_ies->data, new_ie, new_ie_len);

This introduces a bug, "new_ie" is modified between the kzalloc() and
the memcpy(), but you've moved the memcpy() into the allocation. In
fact, new_ie is completely freshly kzalloc()'ed at this point. So you
need to change the ordering here, but since new_ie is freed pretty much
immediately, we can probably just build the stuff directly inside
new_ies->data, though then of course we cannot use your helper anymore?

johannes

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg
  2022-05-04  5:42   ` Kalle Valo
@ 2022-05-04 15:08     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04 15:08 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Gustavo A . R . Silva, Loic Poulain, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, wcn36xx,
	linux-wireless, netdev, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Keith Packard, keyrings, kunit-dev, Kuniyuki Iwashima,
	K. Y. Srinivasan, Lars-Peter Clausen, Lee Jones, Leon Romanovsky,
	Liam Girdwood, linux1394-devel, linux-afs, linux-arm-kernel,
	linux-arm-msm, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-xtensa, llvm, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

On Wed, May 04, 2022 at 08:42:46AM +0300, Kalle Valo wrote:
> Kees Cook <keescook@chromium.org> writes:
> 
> > As part of the work to perform bounds checking on all memcpy() uses,
> > replace the open-coded a deserialization of bytes out of memory into a
> > trailing flexible array by using a flex_array.h helper to perform the
> > allocation, bounds checking, and copying.
> >
> > Cc: Loic Poulain <loic.poulain@linaro.org>
> > Cc: Kalle Valo <kvalo@kernel.org>
> > Cc: "David S. Miller" <davem@davemloft.net>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Cc: Jakub Kicinski <kuba@kernel.org>
> > Cc: Paolo Abeni <pabeni@redhat.com>
> > Cc: wcn36xx@lists.infradead.org
> > Cc: linux-wireless@vger.kernel.org
> > Cc: netdev@vger.kernel.org
> > Signed-off-by: Kees Cook <keescook@chromium.org>
> 
> [...]
> 
> > --- a/drivers/net/wireless/ath/wcn36xx/smd.h
> > +++ b/drivers/net/wireless/ath/wcn36xx/smd.h
> > @@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
> >  
> >  struct wcn36xx_hal_ind_msg {
> >  	struct list_head list;
> > -	size_t msg_len;
> > -	u8 msg[];
> > +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, msg_len);
> > +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, msg);
> 
> This affects readability quite a lot and tbh I don't like it. Isn't
> there any simpler way to solve this?

Similar to how I plumbed member names into __mem_to_flex(), I could do
the same for __mem_to_flex_dup(). That way if the struct member aliases
(DECLARE_FLEX...)  aren't added, the longer form of the helper could
be used. Instead of:

	if (mem_to_flex_dup(&msg_ind, buf, len, GFP_ATOMIC)) {

it would be:

	if (__mem_to_flex_dup(&msg_ind, /* self */, msg,
			      msg_len, buf, len, GFP_ATOMIC)) {

This was how I'd written the helpers in an earlier version, but it
seemed much cleaner to avoid repeating structure layout details at each
call site.

I couldn't find any other way to encode the needed information. It'd be
wonderful if C would let us do:

	struct wcn36xx_hal_ind_msg {
		struct list_head list;
		size_t msg_len;
		u8 msg[msg_len];
	}

And provide some kind of interrogation:

	__builtin_flex_array_member(msg_ind) -> msg_ind->msg
	__builtin_flex_array_count(msg_ind)  -> msg_ind->msg_len

My hope would be to actually use the member aliases to teach things like
-fsanitize=array-bounds about flexible arrays. If it encounters a
structure with the aliases, it could add the instrumentation to do the
bounds checking of things like:

	msg_ind->msg[42]; /* check that 42 is < msg_ind->msg_len */

I also wish I could find a way to make the proposed macros "forward
portable" into proposed C syntax above, but this eluded me as well.
For example:

	struct wcn36xx_hal_ind_msg {
		size_t msg_len;
		struct list_head list;
		BOUNDED_FLEX_ARRAY(u8, msg, msg_len);
	}

	#ifdef CC_HAS_DYNAMIC_ARRAY_LEN
	# define BOUNDED_FLEX_ARRAY(type, name, bounds)	type name[bounds]
	#else
	# define BOUNDED_FLEX_ARRAY(type, name, bounds)			\
		magic_alias_of msg_len __flex_array_elements_count;	\
		union {							\
			type name[];					\
			type __flex_array_elements[];			\
		}
	#endif

But I couldn't sort out the "magic_alias_of" syntax that wouldn't force
structures into having the count member immediately before the flex
array, which would impose more limitations on where this could be
used...

Anyway, I'm open to ideas on how to improve this!

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies
  2022-05-04  7:28   ` Johannes Berg
@ 2022-05-04 15:13     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04 15:13 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Gustavo A . R . Silva, David S. Miller, Jakub Kicinski,
	Paolo Abeni, Eric Dumazet, linux-wireless, netdev,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Paris, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	John Keeping, Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nick Desaulniers, Nuno Sá,
	Paul Moore, Rich Felker, Rob Herring, Russell King, selinux,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Wed, May 04, 2022 at 09:28:46AM +0200, Johannes Berg wrote:
> On Tue, 2022-05-03 at 18:44 -0700, Kees Cook wrote:
> > 
> > @@ -2277,7 +2274,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
> >  	size_t ielen = len - offsetof(struct ieee80211_mgmt,
> >  				      u.probe_resp.variable);
> >  	size_t new_ie_len;
> > -	struct cfg80211_bss_ies *new_ies;
> > +	struct cfg80211_bss_ies *new_ies = NULL;
> >  	const struct cfg80211_bss_ies *old;
> >  	u8 cpy_len;
> >  
> > @@ -2314,8 +2311,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
> >  	if (!new_ie)
> >  		return;
> >  
> > -	new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
> > -	if (!new_ies)
> > +	if (mem_to_flex_dup(&new_ies, new_ie, new_ie_len, GFP_ATOMIC))
> >  		goto out_free;
> >  
> >  	pos = new_ie;
> > @@ -2333,10 +2329,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
> >  	memcpy(pos, mbssid + cpy_len, ((ie + ielen) - (mbssid + cpy_len)));
> >  
> >  	/* update ie */
> > -	new_ies->len = new_ie_len;
> >  	new_ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
> >  	new_ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
> > -	memcpy(new_ies->data, new_ie, new_ie_len);
> 
> This introduces a bug, "new_ie" is modified between the kzalloc() and
> the memcpy(), but you've moved the memcpy() into the allocation. In
> fact, new_ie is completely freshly kzalloc()'ed at this point. So you
> need to change the ordering here, but since new_ie is freed pretty much
> immediately, we can probably just build the stuff directly inside
> new_ies->data, though then of course we cannot use your helper anymore?

Eek, yes, thanks. My attempt to locate the alloc/memcpy pattern failed
to take into account anything touch the source between alloc and memcpy.
I'll double check the other examples.

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data
  2022-05-04  1:44 ` [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data Kees Cook
@ 2022-05-04 15:17   ` Mark Brown
  0 siblings, 0 replies; 71+ messages in thread
From: Mark Brown @ 2022-05-04 15:17 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Lars-Peter Clausen, Nuno Sá,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai, alsa-devel,
	Alexei Starovoitov, Al Viro, Andrew Gabbasov, Andrew Morton,
	Andy Gross, Andy Lavr, Arend van Spriel, Baowen Zheng,
	Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lee Jones, Leon Romanovsky,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Martin K. Petersen, Max Filippov, Mimi Zohar,
	Muchun Song, Nathan Chancellor, netdev, Nick Desaulniers,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Tom Rix,
	Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel,
	Xiu Jianfeng, Yang Yingliang

[-- Attachment #1: Type: text/plain, Size: 363 bytes --]

On Tue, May 03, 2022 at 06:44:29PM -0700, Kees Cook wrote:

> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-04  7:25   ` Johannes Berg
@ 2022-05-04 15:38     ` Kees Cook
  2022-05-04 16:08       ` David Laight
  2022-05-05 13:16       ` Johannes Berg
  0 siblings, 2 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04 15:38 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Gustavo A . R . Silva, Keith Packard, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

On Wed, May 04, 2022 at 09:25:56AM +0200, Johannes Berg wrote:
> On Tue, 2022-05-03 at 18:44 -0700, Kees Cook wrote:
> > 
> > For example, using the most complicated helper, mem_to_flex_dup():
> > 
> >     /* Flexible array struct with members identified. */
> >     struct something {
> >         int mode;
> >         DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, how_many);
> >         unsigned long flags;
> >         DECLARE_FLEX_ARRAY_ELEMENTS(u32, value);
> 
> In many cases, the order of the elements doesn't really matter, so maybe
> it'd be nicer to be able to write it as something like
> 
> DECLARE_FLEX_STRUCT(something,
> 	int mode;
> 	unsigned long flags;
> 	,
> 	int, how_many,
> 	u32, value);
> 
> perhaps? OK, that doesn't seem so nice either.
> 
> Maybe
> 
> struct something {
> 	int mode;
> 	unsigned long flags;
> 	FLEX_ARRAY(
> 		int, how_many,
> 		u32, value
> 	);
> };

Yeah, I mention some of my exploration of this idea in the sibling reply:
https://lore.kernel.org/linux-hardening/202205040730.161645EC@keescook/#t

It seemed like requiring a structure be rearranged to take advantage of
the "automatic layout introspection" wasn't very friendly. On the other
hand, looking at the examples, most of them are already neighboring
members. Hmmm.

> or so? The long and duplicated DECLARE_FLEX_ARRAY_ELEMENTS_COUNT and
> DECLARE_FLEX_ARRAY_ELEMENTS seems a bit tedious to me, at least in cases
> where the struct layout is not the most important thing (or it's already
> at the end anyway).

The names aren't great, but I wanted to distinguish "elements" as the
array not the count. Yay naming.

However, perhaps the solution is to have _both_. i.e using
BOUNDED_FLEX_ARRAY(count_type, count_name, array_type, array_name) for
the "neighboring" case, and the DECLARE...{ELEMENTS,COUNT} for the
"split" case.

And DECLARE_FLEX_ARRAY_ELEMENTS could actually be expanded to include
the count_name too, so both methods could be "forward portable" to a
future where C grew the syntax for bounded flex arrays.

> 
> >     struct something *instance = NULL;
> >     int rc;
> > 
> >     rc = mem_to_flex_dup(&instance, byte_array, count, GFP_KERNEL);
> >     if (rc)
> >         return rc;
> 
> This seems rather awkward, having to set it to NULL, then checking rc
> (and possibly needing a separate variable for it), etc.

I think the errno return is completely required. I had an earlier version
of this that was much more like a drop-in replacement for memcpy that
would just truncate or panic, and when I had it all together, I could
just imagine hearing Linus telling me to start over because it was unsafe
(truncation may be just as bad as overflow) and disruptive ("never BUG"),
and that it should be recoverable. So, I rewrote it all to return a
__must_check errno.

Requiring instance to be NULL is debatable, but I feel pretty strongly
about it because it does handle a class of mistakes (resource leaks),
and it's not much of a burden to require a known-good starting state.

> But I can understand how you arrived at this:
>  - need to pass instance or &instance or such for typeof()
>    or offsetof() or such

Right.

>  - instance = mem_to_flex_dup(instance, ...)
>    looks too much like it would actually dup 'instance', rather than
>    'byte_array'

And I need an errno output to keep imaginary Linus happy. :)

>  - if you pass &instance anyway, checking for NULL is simple and adds a
>    bit of safety

Right.

> but still, honestly, I don't like it. As APIs go, it feels a bit
> cumbersome and awkward to use, and you really need everyone to use this,
> and not say "uh what, I'll memcpy() instead".

Sure, and I have tried to get it down as small as possible. The earlier
"just put all the member names in every call" version was horrid. :P I
realize it's more work to check errno, but the memcpy() API we've all
been trained to use is just plain dangerous. I don't think it's
unreasonable to ask people to retrain themselves to avoid it. All that
said, yes, I want it to be as friendly as possible.

> Maybe there should also be a realloc() version of it?

Sure! Seems reasonable. I'd like to see the code pattern for this
though. Do you have any examples? Most of what I'd been able to find for
the fragile memcpy() usage was just basic serialize/deserialize or
direct copying.

> > +/** __fas_bytes - Calculate potential size of flexible array structure
> 
> I think you forgot "\n *" in many cases here after "/**".

Oops! Yes, thank you. I'll fix these.

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-04 15:38     ` Kees Cook
@ 2022-05-04 16:08       ` David Laight
  2022-05-05 13:16       ` Johannes Berg
  1 sibling, 0 replies; 71+ messages in thread
From: David Laight @ 2022-05-04 16:08 UTC (permalink / raw)
  To: 'Kees Cook', Johannes Berg
  Cc: Gustavo A . R . Silva, Keith Packard, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

From: Kees Cook
> Sent: 04 May 2022 16:38
...
> > >     struct something *instance = NULL;
> > >     int rc;
> > >
> > >     rc = mem_to_flex_dup(&instance, byte_array, count, GFP_KERNEL);
> > >     if (rc)
> > >         return rc;
> >
> > This seems rather awkward, having to set it to NULL, then checking rc
> > (and possibly needing a separate variable for it), etc.
> 
> I think the errno return is completely required. I had an earlier version
> of this that was much more like a drop-in replacement for memcpy that
> would just truncate or panic, and when I had it all together, I could
> just imagine hearing Linus telling me to start over because it was unsafe
> (truncation may be just as bad as overflow) and disruptive ("never BUG"),
> and that it should be recoverable. So, I rewrote it all to return a
> __must_check errno.
> 
> Requiring instance to be NULL is debatable, but I feel pretty strongly
> about it because it does handle a class of mistakes (resource leaks),
> and it's not much of a burden to require a known-good starting state.

Why not make it look like malloc() since it seems to be malloc().
That gives a much better calling convention.
Passing pointers and integers by reference can generate horrid code.
(Mostly because it stops the compiler keeping values in registers.)

If you want the type information inside the 'function'
use a #define so that the use is:

	mem_to_flex_dup(instance, byte_array, count, GFP_KERNEL);
	if (!instance)
		return ...
(or use ERR_PTR() etc).

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property
  2022-05-04  1:44 ` [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property Kees Cook
@ 2022-05-04 18:09     ` Rob Herring
  0 siblings, 0 replies; 71+ messages in thread
From: Rob Herring @ 2022-05-04 18:09 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Chris Zankel, Max Filippov, Frank Rowand,
	Guenter Roeck, linux-xtensa, devicetree, kunit-dev,
	linux-arm-kernel, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-wireless, llvm, netdev, selinux

Gmail won't send this, so I've trimmed the recipients...

On Tue, May 03, 2022 at 06:44:38PM -0700, Kees Cook wrote:
> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying.
> 
> Cc: Chris Zankel <chris@zankel.net>
> Cc: Max Filippov <jcmvbkbc@gmail.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Frank Rowand <frowand.list@gmail.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-xtensa@linux-xtensa.org
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  arch/xtensa/platforms/xtfpga/setup.c | 9 +++------
>  include/linux/of.h                   | 3 ++-
>  2 files changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
> index 538e6748e85a..31c1fa4ba4ec 100644
> --- a/arch/xtensa/platforms/xtfpga/setup.c
> +++ b/arch/xtensa/platforms/xtfpga/setup.c
> @@ -102,7 +102,7 @@ CLK_OF_DECLARE(xtfpga_clk, "cdns,xtfpga-clock", xtfpga_clk_setup);
>  #define MAC_LEN 6
>  static void __init update_local_mac(struct device_node *node)
>  {
> -	struct property *newmac;
> +	struct property *newmac = NULL;
>  	const u8* macaddr;
>  	int prop_len;
>  
> @@ -110,19 +110,16 @@ static void __init update_local_mac(struct device_node *node)
>  	if (macaddr == NULL || prop_len != MAC_LEN)
>  		return;
>  
> -	newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL);
> -	if (newmac == NULL)
> +	if (mem_to_flex_dup(&newmac, macaddr, MAC_LEN, GFP_KERNEL))
>  		return;
>  
> -	newmac->value = newmac + 1;
> -	newmac->length = MAC_LEN;
> +	newmac->value = newmac->contents;
>  	newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
>  	if (newmac->name == NULL) {
>  		kfree(newmac);
>  		return;
>  	}
>  
> -	memcpy(newmac->value, macaddr, MAC_LEN);
>  	((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f;
>  	of_update_property(node, newmac);
>  }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 17741eee0ca4..efb0f419fd1f 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -30,7 +30,7 @@ typedef u32 ihandle;
>  
>  struct property {
>  	char	*name;
> -	int	length;
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, length);
>  	void	*value;
>  	struct property *next;
>  #if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
> @@ -42,6 +42,7 @@ struct property {
>  #if defined(CONFIG_OF_KOBJ)
>  	struct bin_attribute attr;
>  #endif
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, contents);

99.9% of the time, this is not where the property value is stored as it 
points into an FDT blob. I suppose that is okay, but just want to make 
sure.

The DT API for creating new nodes and properties is horrible as it is 
multiple allocs and strdups which makes for tricky error paths. A better 
API to centralize it would be welcome, but if this is the only case you 
came across it's certainly not a requirement.

Rob

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property
@ 2022-05-04 18:09     ` Rob Herring
  0 siblings, 0 replies; 71+ messages in thread
From: Rob Herring @ 2022-05-04 18:09 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Chris Zankel, Max Filippov, Frank Rowand,
	Guenter Roeck, linux-xtensa, devicetree, kunit-dev,
	linux-arm-kernel, linux-bluetooth, linux-hardening, linux-hyperv,
	linux-integrity, linux-rdma, linux-scsi, linux-security-module,
	linux-usb, linux-wireless, llvm, netdev, selinux

Gmail won't send this, so I've trimmed the recipients...

On Tue, May 03, 2022 at 06:44:38PM -0700, Kees Cook wrote:
> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying.
> 
> Cc: Chris Zankel <chris@zankel.net>
> Cc: Max Filippov <jcmvbkbc@gmail.com>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Frank Rowand <frowand.list@gmail.com>
> Cc: Guenter Roeck <linux@roeck-us.net>
> Cc: linux-xtensa@linux-xtensa.org
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  arch/xtensa/platforms/xtfpga/setup.c | 9 +++------
>  include/linux/of.h                   | 3 ++-
>  2 files changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c
> index 538e6748e85a..31c1fa4ba4ec 100644
> --- a/arch/xtensa/platforms/xtfpga/setup.c
> +++ b/arch/xtensa/platforms/xtfpga/setup.c
> @@ -102,7 +102,7 @@ CLK_OF_DECLARE(xtfpga_clk, "cdns,xtfpga-clock", xtfpga_clk_setup);
>  #define MAC_LEN 6
>  static void __init update_local_mac(struct device_node *node)
>  {
> -	struct property *newmac;
> +	struct property *newmac = NULL;
>  	const u8* macaddr;
>  	int prop_len;
>  
> @@ -110,19 +110,16 @@ static void __init update_local_mac(struct device_node *node)
>  	if (macaddr == NULL || prop_len != MAC_LEN)
>  		return;
>  
> -	newmac = kzalloc(sizeof(*newmac) + MAC_LEN, GFP_KERNEL);
> -	if (newmac == NULL)
> +	if (mem_to_flex_dup(&newmac, macaddr, MAC_LEN, GFP_KERNEL))
>  		return;
>  
> -	newmac->value = newmac + 1;
> -	newmac->length = MAC_LEN;
> +	newmac->value = newmac->contents;
>  	newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
>  	if (newmac->name == NULL) {
>  		kfree(newmac);
>  		return;
>  	}
>  
> -	memcpy(newmac->value, macaddr, MAC_LEN);
>  	((u8*)newmac->value)[5] = (*(u32*)DIP_SWITCHES_VADDR) & 0x3f;
>  	of_update_property(node, newmac);
>  }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 17741eee0ca4..efb0f419fd1f 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -30,7 +30,7 @@ typedef u32 ihandle;
>  
>  struct property {
>  	char	*name;
> -	int	length;
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(int, length);
>  	void	*value;
>  	struct property *next;
>  #if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
> @@ -42,6 +42,7 @@ struct property {
>  #if defined(CONFIG_OF_KOBJ)
>  	struct bin_attribute attr;
>  #endif
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, contents);

99.9% of the time, this is not where the property value is stored as it 
points into an FDT blob. I suppose that is okay, but just want to make 
sure.

The DT API for creating new nodes and properties is horrible as it is 
multiple allocs and strdups which makes for tricky error paths. A better 
API to centralize it would be welcome, but if this is the only case you 
came across it's certainly not a requirement.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 03/32] flex_array: Add Kunit tests
  2022-05-04  3:00   ` David Gow
@ 2022-05-04 19:43     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-04 19:43 UTC (permalink / raw)
  To: David Gow
  Cc: Gustavo A . R . Silva, KUnit Development, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Howells, David S. Miller, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eric Paris, Eugeniu Rosca, Felipe Balbi, Francis Laniel,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Guenter Roeck, Haiyang Zhang, Hante Meuleman, Herbert Xu,
	Hulk Robot, Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, Linux ARM, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Networking, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Wed, May 04, 2022 at 11:00:38AM +0800, David Gow wrote:
> On Wed, May 4, 2022 at 9:47 AM Kees Cook <keescook@chromium.org> wrote:
> >
> > Add tests for the new flexible array structure helpers. These can be run
> > with:
> >
> >   make ARCH=um mrproper
> >   ./tools/testing/kunit/kunit.py config
> 
> Nit: it shouldn't be necessary to run kunit.py config separately:
> kunit.py run will configure the kernel if necessary.

Ah yes, I think you mentioned this before. I'll adjust the commit log.

> 
> >   ./tools/testing/kunit/kunit.py run flex_array
> >
> > Cc: David Gow <davidgow@google.com>
> > Cc: kunit-dev@googlegroups.com
> > Signed-off-by: Kees Cook <keescook@chromium.org>
> > ---
> 
> This looks pretty good to me: it certainly worked on the different
> setups I tried (um, x86_64, x86_64+KASAN).
> 
> A few minor nitpicks inline, mostly around minor config-y things, or
> things which weren't totally clear on my first read-through.
> 
> Hopefully one day, with the various stubbing features or something
> similar, we'll be able to check against allocation failures in
> flex_dup(), too, but otherwise nothing seems too obviously missing.
> 
> Reviewed-by: David Gow <davidgow@google.com>

Great; thanks for the review and testing!

> 
> -- David
> 
> >  lib/Kconfig.debug      |  12 +-
> >  lib/Makefile           |   1 +
> >  lib/flex_array_kunit.c | 523 +++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 531 insertions(+), 5 deletions(-)
> >  create mode 100644 lib/flex_array_kunit.c
> >
> > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> > index 9077bb38bc93..8bae6b169c50 100644
> > --- a/lib/Kconfig.debug
> > +++ b/lib/Kconfig.debug
> > @@ -2551,11 +2551,6 @@ config OVERFLOW_KUNIT_TEST
> >           Builds unit tests for the check_*_overflow(), size_*(), allocation, and
> >           related functions.
> >
> > -         For more information on KUnit and unit tests in general please refer
> > -         to the KUnit documentation in Documentation/dev-tools/kunit/.
> > -
> > -         If unsure, say N.
> > -
> 
> Nit: while I'm not against removing some of this boilerplate, is it
> better suited for a separate commit?

Make sense, yes. I'll drop this for now.

> 
> >  config STACKINIT_KUNIT_TEST
> >         tristate "Test level of stack variable initialization" if !KUNIT_ALL_TESTS
> >         depends on KUNIT
> > @@ -2567,6 +2562,13 @@ config STACKINIT_KUNIT_TEST
> >           CONFIG_GCC_PLUGIN_STRUCTLEAK, CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF,
> >           or CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL.
> >
> > +config FLEX_ARRAY_KUNIT_TEST
> > +       tristate "Test flex_*() family of helper functions at runtime" if !KUNIT_ALL_TESTS
> > +       depends on KUNIT
> > +       default KUNIT_ALL_TESTS
> > +       help
> > +         Builds unit tests for flexible array copy helper functions.
> > +
> 
> Nit: checkpatch warns that the description here may be insufficient:
> WARNING: please write a help paragraph that fully describes the config symbol

Yeah, I don't know anything to put here that isn't just more
boilerplate, so I'm choosing to ignore this for now. :)

> > [...]
> > +struct normal {
> > +       size_t  datalen;
> > +       u32     data[];
> > +};
> > +
> > +struct decl_normal {
> > +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(size_t, datalen);
> > +       DECLARE_FLEX_ARRAY_ELEMENTS(u32, data);
> > +};
> > +
> > +struct aligned {
> > +       unsigned short  datalen;
> > +       char            data[] __aligned(__alignof__(u64));
> > +};
> > +
> > +struct decl_aligned {
> > +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(unsigned short, datalen);
> > +       DECLARE_FLEX_ARRAY_ELEMENTS(char, data) __aligned(__alignof__(u64));
> > +};
> > +
> > +static void struct_test(struct kunit *test)
> > +{
> > +       COMPARE_STRUCTS(struct normal, struct decl_normal);
> > +       COMPARE_STRUCTS(struct aligned, struct decl_aligned);
> > +}
> 
> If I understand it, the purpose of this is to ensure that structs both
> with and without the flexible array declaration have the same memory
> layout?
> 
> If so, any chance of a comment briefly stating that's the purpose (or
> renaming this test struct_layout_test())?

Yeah, good idea; I'll improve the naming.

> 
> Also, would it make sense to do the same with the struct with internal
> padding below?

Heh, yes, good point! :)

> [...]
> > +#define CHECK_COPY(ptr)                do {                                            \
> > +       typeof(*(ptr)) *_cc_dst = (ptr);                                        \
> > +       KUNIT_EXPECT_EQ(test, _cc_dst->induce_padding, 0);                      \
> > +       memcpy(&padding, &_cc_dst->induce_padding + sizeof(_cc_dst->induce_padding), \
> > +              sizeof(padding));                                                \
> > +       /* Padding should be zero too. */                                       \
> > +       KUNIT_EXPECT_EQ(test, padding, 0);                                      \
> > +       KUNIT_EXPECT_EQ(test, src->count, _cc_dst->count);                      \
> > +       KUNIT_EXPECT_EQ(test, _cc_dst->count, TEST_TARGET);                     \
> > +       for (i = 0; i < _cc_dst->count - 1; i++) {                              \
> > +               /* 'A' is 0x41, and here repeated in a u32. */                  \
> 
> Would it be simpler to just note that the magic value is 0x41, rather
> than have it be the character 'A'?

Yeah, now fixed.

> [...]
> > +       CHECK_COPY(&encap->fas);
> > +       /* Check that items external to "fas" are zero. */
> > +       KUNIT_EXPECT_EQ(test, encap->flags, 0);
> > +       KUNIT_EXPECT_EQ(test, encap->junk, 0);
> > +       kfree(encap);
> > +#undef MAGIC_WORD
> 
> MAGIC_WORD isn't defined (or used) for flux_dup_test? Is it worth
> using it (or something similar) for the 'A' / 0x14141414 and the
> CHECK_COPY() macro?

Oops, yes. Fixed.

Thanks again!

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 03/32] flex_array: Add Kunit tests
  2022-05-04  1:44 ` [PATCH 03/32] flex_array: Add Kunit tests Kees Cook
  2022-05-04  3:00   ` David Gow
@ 2022-05-04 19:58   ` Daniel Latypov
  1 sibling, 0 replies; 71+ messages in thread
From: Daniel Latypov @ 2022-05-04 19:58 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, David Gow, kunit-dev, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Göttsche, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Howells, David S. Miller, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eric Paris, Eugeniu Rosca, Felipe Balbi, Francis Laniel,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Guenter Roeck, Haiyang Zhang, Hante Meuleman, Herbert Xu,
	Hulk Robot, Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Tue, May 3, 2022 at 8:47 PM Kees Cook <keescook@chromium.org> wrote:
> +#define COMPARE_STRUCTS(STRUCT_A, STRUCT_B)    do {                    \
> +       STRUCT_A *ptr_A;                                                \
> +       STRUCT_B *ptr_B;                                                \
> +       int rc;                                                         \
> +       size_t size_A, size_B;                                          \
> +                                                                       \
> +       /* matching types for flex array elements and count */          \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_A), sizeof(*ptr_B));          \
> +       KUNIT_EXPECT_TRUE(test, __same_type(*ptr_A->data,               \
> +               *ptr_B->__flex_array_elements));                        \

Leaving some minor suggestions to go along with David's comments.

Should we make these KUNIT_ASSERT_.* instead?
I assume if we have a type-mismatch, then we should bail out instead
of continuing to produce more error messages.

> +       KUNIT_EXPECT_TRUE(test, __same_type(ptr_A->datalen,             \
> +               ptr_B->__flex_array_elements_count));                   \
> +       KUNIT_EXPECT_EQ(test, sizeof(*ptr_A->data),                     \
> +                             sizeof(*ptr_B->__flex_array_elements));   \
> +       KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), data),           \
> +                             offsetof(typeof(*ptr_B),                  \
> +                                      __flex_array_elements));         \
> +       KUNIT_EXPECT_EQ(test, offsetof(typeof(*ptr_A), datalen),        \
> +                             offsetof(typeof(*ptr_B),                  \
> +                                      __flex_array_elements_count));   \
> +                                                                       \
> +       /* struct_size() vs __fas_bytes() */                            \
> +       size_A = struct_size(ptr_A, data, 13);                          \
> +       rc = __fas_bytes(ptr_B, __flex_array_elements,                  \
> +                        __flex_array_elements_count, 13, &size_B);     \
> +       KUNIT_EXPECT_EQ(test, rc, 0);                                   \

Hmm, what do you think about inlining the call/dropping rc?

i.e. something like
KUNIT_EXPECT_EQ(test, 0, __fas_bytes(ptr_B, __flex_array_elements, \
                        __flex_array_elements_count, 13, &size_B));

That would give a slightly clearer error message on failure.
Otherwise the user only really gets a line number to try and start to
understand what went wrong.

> +
> +#define CHECK_COPY(ptr)                do {                                            \
> +       typeof(*(ptr)) *_cc_dst = (ptr);                                        \
> +       KUNIT_EXPECT_EQ(test, _cc_dst->induce_padding, 0);                      \
> +       memcpy(&padding, &_cc_dst->induce_padding + sizeof(_cc_dst->induce_padding), \
> +              sizeof(padding));                                                \
> +       /* Padding should be zero too. */                                       \
> +       KUNIT_EXPECT_EQ(test, padding, 0);                                      \
> +       KUNIT_EXPECT_EQ(test, src->count, _cc_dst->count);                      \

This also seems like a good place to use ASSERT instead of EXPECT.


> +       KUNIT_EXPECT_EQ(test, _cc_dst->count, TEST_TARGET);                     \
> +       for (i = 0; i < _cc_dst->count - 1; i++) {                              \
> +               /* 'A' is 0x41, and here repeated in a u32. */                  \
> +               KUNIT_EXPECT_EQ(test, _cc_dst->flex[i], 0x41414141);            \
> +       }                                                                       \
> +       /* Last item should be different. */                                    \
> +       KUNIT_EXPECT_EQ(test, _cc_dst->flex[_cc_dst->count - 1], 0x14141414);   \
> +} while (0)
> +
> +/* Test copying from one flexible array struct into another. */
> +static void flex_cpy_test(struct kunit *test)
> +{
> +#define TEST_BOUNDS    13
> +#define TEST_TARGET    12
> +#define TEST_SMALL     10
> +       struct flex_cpy_obj *src, *dst;
> +       unsigned long padding;
> +       int i, rc;
> +
> +       /* Prepare open-coded source. */
> +       src = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);

Looks like we could use kunit_kzalloc() here and avoid needing the
manual call to kfree?
This also holds for the other test cases where they don't have early
calls to kfree().

Doing so would also let you use KUNIT_ASSERT's without fear of leaking
these allocations.

> +       src->count = TEST_BOUNDS;
> +       memset(src->flex, 'A', flex_array_size(src, flex, TEST_BOUNDS));
> +       src->flex[src->count - 2] = 0x14141414;
> +       src->flex[src->count - 1] = 0x24242424;
> +
> +       /* Prepare open-coded destination, alloc only. */
> +       dst = kzalloc(struct_size(src, flex, TEST_BOUNDS), GFP_KERNEL);
> +       /* Pre-fill with 0xFE marker. */
> +       memset(dst, 0xFE, struct_size(src, flex, TEST_BOUNDS));
> +       /* Pretend we're 1 element smaller. */
> +       dst->count = TEST_TARGET;
> +
> +       /* Pretend to match the target destination size. */
> +       src->count = TEST_TARGET;
> +
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       CHECK_COPY(dst);
> +       /* Item past last copied item is unchanged from initial memset. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
> +
> +       /* Now trip overflow, and verify we didn't clobber beyond end. */
> +       src->count = TEST_BOUNDS;
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, -E2BIG);
> +       /* Item past last copied item is unchanged from initial memset. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[dst->count], 0xFEFEFEFE);
> +
> +       /* Reset destination contents. */
> +       memset(dst, 0xFD, struct_size(src, flex, TEST_BOUNDS));
> +       dst->count = TEST_TARGET;
> +
> +       /* Copy less than max. */
> +       src->count = TEST_SMALL;
> +       rc = flex_cpy(dst, src);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       /* Verify count was adjusted. */
> +       KUNIT_EXPECT_EQ(test, dst->count, TEST_SMALL);

Just an FYI, macros get evaluated before the expect macros can stringify them.
So the error message would look something like
  Expected dest->count == 10
     but dest->count = 9

Not a big concern, but just noting that "TEST_SMALL" won't be visible at all.
Could opt for

KUNIT_EXPECT_EQ_MSG(test, dst->count, TEST_SMALL, "my custom extra message");

if you think it'd be usable to make the test more grokkable.

> +       /* Verify element beyond src size was wiped. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_SMALL], 0);
> +       /* Verify element beyond original dst size was untouched. */
> +       KUNIT_EXPECT_EQ(test, dst->flex[TEST_TARGET], 0xFDFDFDFD);
> +
> +       kfree(dst);
> +       kfree(src);
> +#undef TEST_BOUNDS
> +#undef TEST_TARGET
> +#undef TEST_SMALL
> +}
> +
> +static void flex_dup_test(struct kunit *test)
> +{
> +#define TEST_TARGET    12
> +       struct flex_cpy_obj *src, *dst = NULL, **null = NULL;
> +       struct flex_dup_obj *encap = NULL;
> +       unsigned long padding;
> +       int i, rc;
> +
> +       /* Prepare open-coded source. */
> +       src = kzalloc(struct_size(src, flex, TEST_TARGET), GFP_KERNEL);
> +       src->count = TEST_TARGET;
> +       memset(src->flex, 'A', flex_array_size(src, flex, TEST_TARGET));
> +       src->flex[src->count - 1] = 0x14141414;
> +
> +       /* Reject NULL @alloc. */
> +       rc = flex_dup(null, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> +       /* Check good copy. */
> +       rc = flex_dup(&dst, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, dst != NULL);
> +       CHECK_COPY(dst);
> +
> +       /* Reject non-NULL *@alloc. */
> +       rc = flex_dup(&dst, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, -EINVAL);
> +
> +       kfree(dst);
> +
> +       /* Check good encap copy. */
> +       rc = __flex_dup(&encap, .fas, src, GFP_KERNEL);
> +       KUNIT_EXPECT_EQ(test, rc, 0);
> +       KUNIT_ASSERT_TRUE(test, dst != NULL);

FYI, there's a new KUNIT_ASSERT_NOT_NULL() macro in the
-kselftest/kunit branch,
https://patchwork.kernel.org/project/linux-kselftest/patch/20220211164246.410079-1-ribalda@chromium.org/

But that's not planned for inclusion into mainline until 5.19, so
leaving this as-is is better for now.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-04  1:44 ` [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab Kees Cook
@ 2022-05-04 22:57   ` Paul Moore
  2022-05-04 23:43     ` Gustavo A. R. Silva
  0 siblings, 1 reply; 71+ messages in thread
From: Paul Moore @ 2022-05-04 22:57 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Steffen Klassert, Herbert Xu,
	David S. Miller, Stephen Smalley, Eric Paris, Nick Desaulniers,
	Xiu Jianfeng, Christian Göttsche, netdev, selinux,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:
>
> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying:
>
>     struct xfrm_sec_ctx
>     struct sidtab_str_cache
>
> Cc: Steffen Klassert <steffen.klassert@secunet.com>
> Cc: Herbert Xu <herbert@gondor.apana.org.au>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
> Cc: Eric Paris <eparis@parisplace.org>
> Cc: Nick Desaulniers <ndesaulniers@google.com>
> Cc: Xiu Jianfeng <xiujianfeng@huawei.com>
> Cc: "Christian Göttsche" <cgzones@googlemail.com>
> Cc: netdev@vger.kernel.org
> Cc: selinux@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>  include/uapi/linux/xfrm.h    | 4 ++--
>  security/selinux/ss/sidtab.c | 9 +++------
>  security/selinux/xfrm.c      | 7 ++-----
>  3 files changed, 7 insertions(+), 13 deletions(-)
>
> diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
> index 65e13a099b1a..4a6fa2beff6a 100644
> --- a/include/uapi/linux/xfrm.h
> +++ b/include/uapi/linux/xfrm.h
> @@ -31,9 +31,9 @@ struct xfrm_id {
>  struct xfrm_sec_ctx {
>         __u8    ctx_doi;
>         __u8    ctx_alg;
> -       __u16   ctx_len;
> +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
>         __u32   ctx_sid;
> -       char    ctx_str[0];
> +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
>  };

While I like the idea of this in principle, I'd like to hear about the
testing you've done on these patches.  A previous flex array
conversion in the audit uapi headers ended up causing a problem with
GCC12 and SWIG; while it was a SWIG problem and not a kernel header
problem that was thin consolation for those with broken builds.

> diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
> index a54b8652bfb5..a9d434e8cff7 100644
> --- a/security/selinux/ss/sidtab.c
> +++ b/security/selinux/ss/sidtab.c
> @@ -23,8 +23,8 @@ struct sidtab_str_cache {
>         struct rcu_head rcu_member;
>         struct list_head lru_member;
>         struct sidtab_entry *parent;
> -       u32 len;
> -       char str[];
> +       DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, len);
> +       DECLARE_FLEX_ARRAY_ELEMENTS(char, str);
>  };
>
>  #define index_to_sid(index) ((index) + SECINITSID_NUM + 1)

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-04 22:57   ` Paul Moore
@ 2022-05-04 23:43     ` Gustavo A. R. Silva
  2022-05-05  3:14       ` Paul Moore
  0 siblings, 1 reply; 71+ messages in thread
From: Gustavo A. R. Silva @ 2022-05-04 23:43 UTC (permalink / raw)
  To: Paul Moore
  Cc: Kees Cook, Steffen Klassert, Herbert Xu, David S. Miller,
	Stephen Smalley, Eric Paris, Nick Desaulniers, Xiu Jianfeng,
	Christian Göttsche, netdev, selinux, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Lamparter, Chris Zankel, Cong Wang,
	Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

Hi Paul,

On Wed, May 04, 2022 at 06:57:28PM -0400, Paul Moore wrote:
> On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:

[..]

> > +++ b/include/uapi/linux/xfrm.h
> > @@ -31,9 +31,9 @@ struct xfrm_id {
> >  struct xfrm_sec_ctx {
> >         __u8    ctx_doi;
> >         __u8    ctx_alg;
> > -       __u16   ctx_len;
> > +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
> >         __u32   ctx_sid;
> > -       char    ctx_str[0];
> > +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
> >  };
> 
> While I like the idea of this in principle, I'd like to hear about the
> testing you've done on these patches.  A previous flex array
> conversion in the audit uapi headers ended up causing a problem with

I'm curious about which commit caused those problems...?

Thanks
--
Gustavo

> GCC12 and SWIG; while it was a SWIG problem and not a kernel header
> problem that was thin consolation for those with broken builds.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-04 23:43     ` Gustavo A. R. Silva
@ 2022-05-05  3:14       ` Paul Moore
  2022-05-05 18:39         ` Kees Cook
  0 siblings, 1 reply; 71+ messages in thread
From: Paul Moore @ 2022-05-05  3:14 UTC (permalink / raw)
  To: Gustavo A. R. Silva
  Cc: Kees Cook, Steffen Klassert, Herbert Xu, David S. Miller,
	Stephen Smalley, Eric Paris, Nick Desaulniers, Xiu Jianfeng,
	Christian Göttsche, netdev, selinux, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Lamparter, Chris Zankel, Cong Wang,
	Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

On Wed, May 4, 2022 at 7:34 PM Gustavo A. R. Silva
<gustavoars@kernel.org> wrote:
>
> Hi Paul,
>
> On Wed, May 04, 2022 at 06:57:28PM -0400, Paul Moore wrote:
> > On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:
>
> [..]
>
> > > +++ b/include/uapi/linux/xfrm.h
> > > @@ -31,9 +31,9 @@ struct xfrm_id {
> > >  struct xfrm_sec_ctx {
> > >         __u8    ctx_doi;
> > >         __u8    ctx_alg;
> > > -       __u16   ctx_len;
> > > +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
> > >         __u32   ctx_sid;
> > > -       char    ctx_str[0];
> > > +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
> > >  };
> >
> > While I like the idea of this in principle, I'd like to hear about the
> > testing you've done on these patches.  A previous flex array
> > conversion in the audit uapi headers ended up causing a problem with
>
> I'm curious about which commit caused those problems...?

Commit ed98ea2128b6 ("audit: replace zero-length array with
flexible-array member"), however, as I said earlier, the problem was
actually with SWIG, it just happened to be triggered by the kernel
commit.  There was a brief fedora-devel mail thread about the problem,
see the link below:

* https://www.spinics.net/lists/fedora-devel/msg297991.html

To reiterate, I'm supportive of changes like this, but I would like to
hear how it was tested to ensure there are no unexpected problems with
userspace.  If there are userspace problems it doesn't mean we can't
make changes like this, it just means we need to ensure that the
userspace issues are resolved first.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-04 15:38     ` Kees Cook
  2022-05-04 16:08       ` David Laight
@ 2022-05-05 13:16       ` Johannes Berg
  2022-05-05 15:16         ` Keith Packard
  2022-05-05 19:27         ` Kees Cook
  1 sibling, 2 replies; 71+ messages in thread
From: Johannes Berg @ 2022-05-05 13:16 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, Keith Packard, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

On Wed, 2022-05-04 at 08:38 -0700, Kees Cook wrote:
> 
> It seemed like requiring a structure be rearranged to take advantage of
> the "automatic layout introspection" wasn't very friendly. On the other
> hand, looking at the examples, most of them are already neighboring
> members. Hmmm.

A lot of them are, and many could be, though not all.

> > or so? The long and duplicated DECLARE_FLEX_ARRAY_ELEMENTS_COUNT and
> > DECLARE_FLEX_ARRAY_ELEMENTS seems a bit tedious to me, at least in cases
> > where the struct layout is not the most important thing (or it's already
> > at the end anyway).
> 
> The names aren't great, but I wanted to distinguish "elements" as the
> array not the count. Yay naming.

:-)

> However, perhaps the solution is to have _both_. i.e using
> BOUNDED_FLEX_ARRAY(count_type, count_name, array_type, array_name) for
> the "neighboring" case, and the DECLARE...{ELEMENTS,COUNT} for the
> "split" case.

Seems reasonable to me.

> And DECLARE_FLEX_ARRAY_ELEMENTS could actually be expanded to include
> the count_name too, so both methods could be "forward portable" to a
> future where C grew the syntax for bounded flex arrays.

I guess I don't see that happening :)

> > This seems rather awkward, having to set it to NULL, then checking rc
> > (and possibly needing a separate variable for it), etc.
> 
> I think the errno return is completely required. I had an earlier version
> of this that was much more like a drop-in replacement for memcpy that
> would just truncate or panic, 
> 

Oh, I didn't mean to imply it should truncate or panic or such - but if
it returns a pointer it can still be an ERR_PTR() or NULL instead of
having this separate indication, which even often confuses static type
checkers since they don't always see the "errno == 0 <=> ptr != NULL"
relation.

So not saying you shouldn't have any error return - clearly you need
that, just saying that I'm not sure that having the two separated is
great.


> Requiring instance to be NULL is debatable, but I feel pretty strongly
> about it because it does handle a class of mistakes (resource leaks),
> and it's not much of a burden to require a known-good starting state.

Yeah, dunno, I guess I'm slightly more on the side of not requiring it,
since we don't do the same for kmalloc() etc. and probably really
wouldn't want to add kmalloc_s() that does it ;-)

I mean, you _could_ go there:

int kmalloc_s(void **ptr, size_t size, gfp_t gfp)
{
  void *ret;

  if (*ptr)
    return -EINVAL;

  ret = kmalloc(size, gfp);
  if (!ret)
    return -ENOMEM;
  *ptr = ret;
  return 0;  
}

right? But we don't really do that, and I'm not sure it'd be a win if
done over the whole code base.

So I'm not really sure why this aspect here should need to be different,
except of course that you already need the input argument for the magic.

But we could still have (this prototype is theoretical, of course, it
cannot be implemented in C):

void *mem_to_flex_dup(void *ptr, const void *data, size_t elements,
                      gfp_t gfp);


which isn't really that much better though.

And btw, while I was writing it down I was looking to see if it should
be "size_t elements" or "size_t len" (like memcpy), it took me some time
to figure out, and I was looking at the examples:

 1) most of them actually use __u8 or some variant thereof, so you
    could probably add an even simpler macro like
       BOUNDED_FLEX_DATA(int, bytes, data)
    which has the u8 type internally.

 2) Unless I'm confusing myself, you got the firewire change wrong,
    because __mem_to_flex_dup takes the "elements_count", but the
    memcpy() there wasn't multiplied by the sizeof(element)? Or maybe
    the fact that it was declared as __u32 header[0] is wrong, and it
    should be __u8, but it's all very confusing, and I'm really not
    sure about this at all.



One "perhaps you'll laugh me out of the room" suggestion might be to
actually be able to initialize the whole thing too?


mydata = flex_struct_alloc(mydata, GFP_KERNEL,
                           variable_data, variable_len,
                           .member = 1,
                           .another = 2);

(the ordering can't really be otherwise since you have to use
__VA_ARGS__).

That might reduce some more code too, though I guess it's quite some
additional magic ... :)


> > but still, honestly, I don't like it. As APIs go, it feels a bit
> > cumbersome and awkward to use, and you really need everyone to use this,
> > and not say "uh what, I'll memcpy() instead".
> 
> Sure, and I have tried to get it down as small as possible. The earlier
> "just put all the member names in every call" version was horrid. :P

:-D

> I
> realize it's more work to check errno, but the memcpy() API we've all
> been trained to use is just plain dangerous. I don't think it's
> unreasonable to ask people to retrain themselves to avoid it. All that
> said, yes, I want it to be as friendly as possible.
> 
> > Maybe there should also be a realloc() version of it?
> 
> Sure! Seems reasonable. I'd like to see the code pattern for this
> though. Do you have any examples?

I was going to point to struct cfg80211_bss_ies, but I realize now
they're RCU-managed, so we never resize them anyway ... So maybe it's
less common than I thought it might be.

I suppose you know better since you converted a lot of stuff already :-)

johannes

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 13:16       ` Johannes Berg
@ 2022-05-05 15:16         ` Keith Packard
  2022-05-05 19:32           ` Kees Cook
  2022-05-05 19:27         ` Kees Cook
  1 sibling, 1 reply; 71+ messages in thread
From: Keith Packard @ 2022-05-05 15:16 UTC (permalink / raw)
  To: Johannes Berg, Kees Cook
  Cc: Gustavo A . R . Silva, Francis Laniel, Daniel Axtens,
	Dan Williams, Vincenzo Frascino, Guenter Roeck, Daniel Vetter,
	Tadeusz Struk, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

[-- Attachment #1: Type: text/plain, Size: 714 bytes --]

Johannes Berg <johannes@sipsolutions.net> writes:

> Yeah, dunno, I guess I'm slightly more on the side of not requiring it,
> since we don't do the same for kmalloc() etc. and probably really
> wouldn't want to add kmalloc_s() that does it ;-)

I suspect the number of bugs this catches will be small, but they'll be
in places where the flow of control is complicated. What we want is to
know that there's no "real" value already present. I'd love it if we
could make the macro declare a new name (yeah, I know, mixing
declarations and code).

Of course, we could also end up with people writing a wrapping macro
that sets the variable to NULL before invoking the underlying macro...

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-05  3:14       ` Paul Moore
@ 2022-05-05 18:39         ` Kees Cook
  2022-05-05 23:16           ` Paul Moore
  0 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-05 18:39 UTC (permalink / raw)
  To: Paul Moore
  Cc: Gustavo A. R. Silva, Steffen Klassert, Herbert Xu,
	David S. Miller, Stephen Smalley, Eric Paris, Nick Desaulniers,
	Xiu Jianfeng, Christian Göttsche, netdev, selinux,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

On Wed, May 04, 2022 at 11:14:42PM -0400, Paul Moore wrote:
> On Wed, May 4, 2022 at 7:34 PM Gustavo A. R. Silva
> <gustavoars@kernel.org> wrote:
> >
> > Hi Paul,
> >
> > On Wed, May 04, 2022 at 06:57:28PM -0400, Paul Moore wrote:
> > > On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:
> >
> > [..]
> >
> > > > +++ b/include/uapi/linux/xfrm.h
> > > > @@ -31,9 +31,9 @@ struct xfrm_id {
> > > >  struct xfrm_sec_ctx {
> > > >         __u8    ctx_doi;
> > > >         __u8    ctx_alg;
> > > > -       __u16   ctx_len;
> > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
> > > >         __u32   ctx_sid;
> > > > -       char    ctx_str[0];
> > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
> > > >  };
> > >
> > > While I like the idea of this in principle, I'd like to hear about the
> > > testing you've done on these patches.  A previous flex array
> > > conversion in the audit uapi headers ended up causing a problem with
> >
> > I'm curious about which commit caused those problems...?
> 
> Commit ed98ea2128b6 ("audit: replace zero-length array with
> flexible-array member"), however, as I said earlier, the problem was
> actually with SWIG, it just happened to be triggered by the kernel
> commit.  There was a brief fedora-devel mail thread about the problem,
> see the link below:
> 
> * https://www.spinics.net/lists/fedora-devel/msg297991.html

Wow, that's pretty weird -- it looks like SWIG was scraping the headers
to build its conversions? I assume SWIG has been fixed now?

> To reiterate, I'm supportive of changes like this, but I would like to
> hear how it was tested to ensure there are no unexpected problems with
> userspace.  If there are userspace problems it doesn't mean we can't
> make changes like this, it just means we need to ensure that the
> userspace issues are resolved first.

Well, as this is the first and only report of any problems with [0] -> []
conversions (in UAPI or anywhere) that I remember seeing, and they've
been underway since at least v5.9, I hadn't been doing any new testing.

So, for this case, I guess I should ask what tests you think would be
meaningful here? Anything using #include should be fine:
https://codesearch.debian.net/search?q=linux%2Fxfrm.h&literal=1&perpkg=1
Which leaves just this, which may be doing something weird:

libabigail_2.0-1/tests/data/test-diff-filter/test-PR27569-v0.abi
        </data-member>
        <data-member access="public" layout-offset-in-bits="128">
          <var-decl name="seq_hi" type-id="3f1a6b60" visibility="default" filepath="include/uapi/linux/xfrm.h" line="97" column="1"/>
        </data-member>
        <data-member access="public" layout-offset-in-bits="160">

But I see that SWIG doesn't show up in a search for linux/audit.h:
https://codesearch.debian.net/search?q=linux%2Faudit.h&literal=1&perpkg=1

So this may not be a sufficient analysis...

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 13:16       ` Johannes Berg
  2022-05-05 15:16         ` Keith Packard
@ 2022-05-05 19:27         ` Kees Cook
  1 sibling, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-05 19:27 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Gustavo A . R . Silva, Keith Packard, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

On Thu, May 05, 2022 at 03:16:19PM +0200, Johannes Berg wrote:
> On Wed, 2022-05-04 at 08:38 -0700, Kees Cook wrote:
> > 
> > It seemed like requiring a structure be rearranged to take advantage of
> > the "automatic layout introspection" wasn't very friendly. On the other
> > hand, looking at the examples, most of them are already neighboring
> > members. Hmmm.
> 
> A lot of them are, and many could be, though not all.

Yeah, I did a pass through them for the coming v2. Only a few have the
struct order as part of an apparent hardware interface.

> > And DECLARE_FLEX_ARRAY_ELEMENTS could actually be expanded to include
> > the count_name too, so both methods could be "forward portable" to a
> > future where C grew the syntax for bounded flex arrays.
> 
> I guess I don't see that happening :)

Well ... it's on my roadmap. ;) I want it for -fsanitize=array-bounds so
that dynamic array indexing can be checked too. (Right now we can do
constant-sized array index bounds checking at runtime, but the much
harder to find problems tend to come from flex arrays.)

> > Requiring instance to be NULL is debatable, but I feel pretty strongly
> > about it because it does handle a class of mistakes (resource leaks),
> > and it's not much of a burden to require a known-good starting state.
> 
> Yeah, dunno, I guess I'm slightly more on the side of not requiring it,
> since we don't do the same for kmalloc() etc. and probably really
> wouldn't want to add kmalloc_s() that does it ;-)

Well, I dislike all the *alloc APIs. :P

> I mean, you _could_ go there:
> 
> int kmalloc_s(void **ptr, size_t size, gfp_t gfp)

Oh, and I really do (though as a macro, not a "real" function), since
having type introspection would be _extremely_ useful. Though maybe it
needs to be through some kind of type-of-lvalue thing...

https://github.com/KSPP/linux/issues/189
https://github.com/KSPP/linux/issues/87

> So I'm not really sure why this aspect here should need to be different,
> except of course that you already need the input argument for the magic.

Right, and trying to move the kernel code closer to a form where the
compiler can take more of the burden of handling code safety.

> And btw, while I was writing it down I was looking to see if it should
> be "size_t elements" or "size_t len" (like memcpy), it took me some time
> to figure out, and I was looking at the examples:
> 
>  1) most of them actually use __u8 or some variant thereof, so you
>     could probably add an even simpler macro like
>        BOUNDED_FLEX_DATA(int, bytes, data)
>     which has the u8 type internally.

I didn't want these helpers to be "opinionated" about their types (just
their API), so while it's true u8 is usually "good enough", I don't
think it's common enough to make a special case for.

>  2) Unless I'm confusing myself, you got the firewire change wrong,
>     because __mem_to_flex_dup takes the "elements_count", but the
>     memcpy() there wasn't multiplied by the sizeof(element)? Or maybe
>     the fact that it was declared as __u32 header[0] is wrong, and it
>     should be __u8, but it's all very confusing, and I'm really not
>     sure about this at all.

Yes indeed; thanks for catching that. In fact, it's not a strict flex
array struct, since, as you say, it's measuring bytes, not elements.
Yeah, I'll see if that needs to be adjusted/dropped, etc.

> One "perhaps you'll laugh me out of the room" suggestion might be to
> actually be able to initialize the whole thing too?
> 
> mydata = flex_struct_alloc(mydata, GFP_KERNEL,
>                            variable_data, variable_len,
>                            .member = 1,
>                            .another = 2);
> 
> (the ordering can't really be otherwise since you have to use
> __VA_ARGS__).

Oooh, that's a cool idea for the API. Hmmmm.

> That might reduce some more code too, though I guess it's quite some
> additional magic ... :)

Yay preprocessor magic!

> I was going to point to struct cfg80211_bss_ies, but I realize now
> they're RCU-managed, so we never resize them anyway ... So maybe it's
> less common than I thought it might be.
> 
> I suppose you know better since you converted a lot of stuff already :-)

Well, I've seen a lot of fragile code (usually in the form of
exploitable flaws around flex arrays) and they do mostly look the same.
Not everything fits perfectly into the forms this API tries to address,
but my goal is to get it fitting well enough, and the weird stuff can be
more carefully examined -- they're easier to find and audit if all the
others are nicely wrapped up in some fancy flex*() API.

Thanks for your thoughts on all of this! I'll continue to work on a v2...

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 15:16         ` Keith Packard
@ 2022-05-05 19:32           ` Kees Cook
  2022-05-05 20:08             ` Keith Packard
  0 siblings, 1 reply; 71+ messages in thread
From: Kees Cook @ 2022-05-05 19:32 UTC (permalink / raw)
  To: Keith Packard
  Cc: Johannes Berg, Gustavo A . R . Silva, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

On Thu, May 05, 2022 at 08:16:11AM -0700, Keith Packard wrote:
> Johannes Berg <johannes@sipsolutions.net> writes:
> 
> > Yeah, dunno, I guess I'm slightly more on the side of not requiring it,
> > since we don't do the same for kmalloc() etc. and probably really
> > wouldn't want to add kmalloc_s() that does it ;-)
> 
> I suspect the number of bugs this catches will be small, but they'll be
> in places where the flow of control is complicated. What we want is to
> know that there's no "real" value already present. I'd love it if we
> could make the macro declare a new name (yeah, I know, mixing
> declarations and code).

I don't think I can do a declaration and an expression statement at the
same time with different scopes, but that would be kind of cool. We did
just move to c11 to gain the in-loop iterator declarations...

> Of course, we could also end up with people writing a wrapping macro
> that sets the variable to NULL before invoking the underlying macro...

I hope it won't come to that! :)

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 19:32           ` Kees Cook
@ 2022-05-05 20:08             ` Keith Packard
  2022-05-05 20:12               ` Johannes Berg
  0 siblings, 1 reply; 71+ messages in thread
From: Keith Packard @ 2022-05-05 20:08 UTC (permalink / raw)
  To: Kees Cook
  Cc: Johannes Berg, Gustavo A . R . Silva, Francis Laniel,
	Daniel Axtens, Dan Williams, Vincenzo Frascino, Guenter Roeck,
	Daniel Vetter, Tadeusz Struk, Alexei Starovoitov, alsa-devel,
	Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

[-- Attachment #1: Type: text/plain, Size: 1081 bytes --]

Kees Cook <keescook@chromium.org> writes:

> I don't think I can do a declaration and an expression statement at the
> same time with different scopes, but that would be kind of cool. We did
> just move to c11 to gain the in-loop iterator declarations...

Yeah, you'd end up creating a statement-level macro, and I think that
would have poor syntax:

        mem_to_flex_dup(struct something *instance, rc, byte_array,
                        count, GFP_KERNEL);
        if (rc)
           return rc;

I bet you've already considered the simpler form:

        struct something *instance = mem_to_flex_dup(byte_array, count, GFP_KERNEL);
        if (IS_ERR(instance))
            return PTR_ERR(instance);

This doesn't allow you to require a new name, so you effectively lose
the check you're trying to insist upon.

Some way to ask the compiler 'is this reference dead?' would be nice --
it knows if a valid pointer was passed to free, or if a variable has not
been initialized, after all; we just need that exposed at the source
level.

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 20:08             ` Keith Packard
@ 2022-05-05 20:12               ` Johannes Berg
  2022-05-06 11:15                   ` David Laight
  0 siblings, 1 reply; 71+ messages in thread
From: Johannes Berg @ 2022-05-05 20:12 UTC (permalink / raw)
  To: Keith Packard, Kees Cook
  Cc: Gustavo A . R . Silva, Francis Laniel, Daniel Axtens,
	Dan Williams, Vincenzo Frascino, Guenter Roeck, Daniel Vetter,
	Tadeusz Struk, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

On Thu, 2022-05-05 at 13:08 -0700, Keith Packard wrote:


> I bet you've already considered the simpler form:
> 
>         struct something *instance = mem_to_flex_dup(byte_array, count, GFP_KERNEL);
>         if (IS_ERR(instance))
>             return PTR_ERR(instance);
> 

Sadly, this doesn't work in any way because mem_to_flex_dup() needs to
know at least the type, hence passing 'instance', which is simpler than
passing 'struct something'.

johannes

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-05 18:39         ` Kees Cook
@ 2022-05-05 23:16           ` Paul Moore
  2022-05-06  1:08             ` Gustavo A. R. Silva
  0 siblings, 1 reply; 71+ messages in thread
From: Paul Moore @ 2022-05-05 23:16 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A. R. Silva, Steffen Klassert, Herbert Xu,
	David S. Miller, Stephen Smalley, Eric Paris, Nick Desaulniers,
	Xiu Jianfeng, Christian Göttsche, netdev, selinux,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner, Christian Lamparter,
	Chris Zankel, Cong Wang, Daniel Axtens, Daniel Vetter,
	Dan Williams, David Gow, David Howells, Dennis Dalessandro,
	devicetree, Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

On Thu, May 5, 2022 at 2:39 PM Kees Cook <keescook@chromium.org> wrote:
> On Wed, May 04, 2022 at 11:14:42PM -0400, Paul Moore wrote:
> > On Wed, May 4, 2022 at 7:34 PM Gustavo A. R. Silva
> > <gustavoars@kernel.org> wrote:
> > >
> > > Hi Paul,
> > >
> > > On Wed, May 04, 2022 at 06:57:28PM -0400, Paul Moore wrote:
> > > > On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:
> > >
> > > [..]
> > >
> > > > > +++ b/include/uapi/linux/xfrm.h
> > > > > @@ -31,9 +31,9 @@ struct xfrm_id {
> > > > >  struct xfrm_sec_ctx {
> > > > >         __u8    ctx_doi;
> > > > >         __u8    ctx_alg;
> > > > > -       __u16   ctx_len;
> > > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
> > > > >         __u32   ctx_sid;
> > > > > -       char    ctx_str[0];
> > > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
> > > > >  };
> > > >
> > > > While I like the idea of this in principle, I'd like to hear about the
> > > > testing you've done on these patches.  A previous flex array
> > > > conversion in the audit uapi headers ended up causing a problem with
> > >
> > > I'm curious about which commit caused those problems...?
> >
> > Commit ed98ea2128b6 ("audit: replace zero-length array with
> > flexible-array member"), however, as I said earlier, the problem was
> > actually with SWIG, it just happened to be triggered by the kernel
> > commit.  There was a brief fedora-devel mail thread about the problem,
> > see the link below:
> >
> > * https://www.spinics.net/lists/fedora-devel/msg297991.html
>
> Wow, that's pretty weird -- it looks like SWIG was scraping the headers
> to build its conversions? I assume SWIG has been fixed now?

I honestly don't know, the audit userspace was hacking around it with
some header file duplication/munging last I heard, but I try to avoid
having to touch Steve's audit userspace code.

> > To reiterate, I'm supportive of changes like this, but I would like to
> > hear how it was tested to ensure there are no unexpected problems with
> > userspace.  If there are userspace problems it doesn't mean we can't
> > make changes like this, it just means we need to ensure that the
> > userspace issues are resolved first.
>
> Well, as this is the first and only report of any problems with [0] -> []
> conversions (in UAPI or anywhere) that I remember seeing, and they've
> been underway since at least v5.9, I hadn't been doing any new testing.

... and for whatever it is worth, I wasn't expecting it to be a
problem either.  Surprise :)

> So, for this case, I guess I should ask what tests you think would be
> meaningful here? Anything using #include should be fine:
> https://codesearch.debian.net/search?q=linux%2Fxfrm.h&literal=1&perpkg=1
> Which leaves just this, which may be doing something weird:
>
> libabigail_2.0-1/tests/data/test-diff-filter/test-PR27569-v0.abi
>         </data-member>
>         <data-member access="public" layout-offset-in-bits="128">
>           <var-decl name="seq_hi" type-id="3f1a6b60" visibility="default" filepath="include/uapi/linux/xfrm.h" line="97" column="1"/>
>         </data-member>
>         <data-member access="public" layout-offset-in-bits="160">
>
> But I see that SWIG doesn't show up in a search for linux/audit.h:
> https://codesearch.debian.net/search?q=linux%2Faudit.h&literal=1&perpkg=1
>
> So this may not be a sufficient analysis...

I think from a practical perspective ensuring that the major IPsec/IKE
tools, e.g. the various *SWANs, that know about labeled IPSec still
build and can set/get the SA/SPD labels correctly would be sufficient.
I seriously doubt there would be any problems, but who knows.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab
  2022-05-05 23:16           ` Paul Moore
@ 2022-05-06  1:08             ` Gustavo A. R. Silva
  0 siblings, 0 replies; 71+ messages in thread
From: Gustavo A. R. Silva @ 2022-05-06  1:08 UTC (permalink / raw)
  To: Paul Moore
  Cc: Kees Cook, Steffen Klassert, Herbert Xu, David S. Miller,
	Stephen Smalley, Eric Paris, Nick Desaulniers, Xiu Jianfeng,
	Christian Göttsche, netdev, selinux, Alexei Starovoitov,
	alsa-devel, Al Viro, Andrew Gabbasov, Andrew Morton, Andy Gross,
	Andy Lavr, Arend van Spriel, Baowen Zheng, Bjorn Andersson,
	Boris Ostrovsky, Bradley Grove, brcm80211-dev-list.pdl,
	Christian Brauner, Christian Lamparter, Chris Zankel, Cong Wang,
	Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eugeniu Rosca,
	Felipe Balbi, Francis Laniel, Frank Rowand, Franky Lin,
	Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Hulk Robot, Jakub Kicinski,
	James E.J. Bottomley, James Morris, Jarkko Sakkinen,
	Jaroslav Kysela, Jason Gunthorpe, Jens Axboe, Johan Hedberg,
	Johannes Berg, Johannes Berg, John Keeping, Juergen Gross,
	Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, Nuno Sá,
	Paolo Abeni, Rich Felker, Rob Herring, Russell King,
	Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Stephen Hemminger,
	Tadeusz Struk, Takashi Iwai, Tom Rix, Udipto Goswami,
	Vincenzo Frascino, wcn36xx, Wei Liu, xen-devel, Yang Yingliang

On Thu, May 05, 2022 at 07:16:18PM -0400, Paul Moore wrote:
> On Thu, May 5, 2022 at 2:39 PM Kees Cook <keescook@chromium.org> wrote:
> > On Wed, May 04, 2022 at 11:14:42PM -0400, Paul Moore wrote:
> > > On Wed, May 4, 2022 at 7:34 PM Gustavo A. R. Silva
> > > <gustavoars@kernel.org> wrote:
> > > >
> > > > Hi Paul,
> > > >
> > > > On Wed, May 04, 2022 at 06:57:28PM -0400, Paul Moore wrote:
> > > > > On Tue, May 3, 2022 at 9:57 PM Kees Cook <keescook@chromium.org> wrote:
> > > >
> > > > [..]
> > > >
> > > > > > +++ b/include/uapi/linux/xfrm.h
> > > > > > @@ -31,9 +31,9 @@ struct xfrm_id {
> > > > > >  struct xfrm_sec_ctx {
> > > > > >         __u8    ctx_doi;
> > > > > >         __u8    ctx_alg;
> > > > > > -       __u16   ctx_len;
> > > > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(__u16, ctx_len);
> > > > > >         __u32   ctx_sid;
> > > > > > -       char    ctx_str[0];
> > > > > > +       __DECLARE_FLEX_ARRAY_ELEMENTS(char, ctx_str);
> > > > > >  };
> > > > >
> > > > > While I like the idea of this in principle, I'd like to hear about the
> > > > > testing you've done on these patches.  A previous flex array
> > > > > conversion in the audit uapi headers ended up causing a problem with
> > > >
> > > > I'm curious about which commit caused those problems...?
> > >
> > > Commit ed98ea2128b6 ("audit: replace zero-length array with
> > > flexible-array member"), however, as I said earlier, the problem was
> > > actually with SWIG, it just happened to be triggered by the kernel
> > > commit.  There was a brief fedora-devel mail thread about the problem,
> > > see the link below:
> > >
> > > * https://www.spinics.net/lists/fedora-devel/msg297991.html
> >
> > Wow, that's pretty weird -- it looks like SWIG was scraping the headers
> > to build its conversions? I assume SWIG has been fixed now?
> 
> I honestly don't know, the audit userspace was hacking around it with
> some header file duplication/munging last I heard, but I try to avoid
> having to touch Steve's audit userspace code.
> 
> > > To reiterate, I'm supportive of changes like this, but I would like to
> > > hear how it was tested to ensure there are no unexpected problems with
> > > userspace.  If there are userspace problems it doesn't mean we can't
> > > make changes like this, it just means we need to ensure that the
> > > userspace issues are resolved first.
> >
> > Well, as this is the first and only report of any problems with [0] -> []
> > conversions (in UAPI or anywhere) that I remember seeing, and they've
> > been underway since at least v5.9, I hadn't been doing any new testing.
> 
> ... and for whatever it is worth, I wasn't expecting it to be a
> problem either.  Surprise :)
> 
> > So, for this case, I guess I should ask what tests you think would be
> > meaningful here? Anything using #include should be fine:
> > https://codesearch.debian.net/search?q=linux%2Fxfrm.h&literal=1&perpkg=1
> > Which leaves just this, which may be doing something weird:
> >
> > libabigail_2.0-1/tests/data/test-diff-filter/test-PR27569-v0.abi
> >         </data-member>
> >         <data-member access="public" layout-offset-in-bits="128">
> >           <var-decl name="seq_hi" type-id="3f1a6b60" visibility="default" filepath="include/uapi/linux/xfrm.h" line="97" column="1"/>
> >         </data-member>
> >         <data-member access="public" layout-offset-in-bits="160">
> >
> > But I see that SWIG doesn't show up in a search for linux/audit.h:
> > https://codesearch.debian.net/search?q=linux%2Faudit.h&literal=1&perpkg=1
> >
> > So this may not be a sufficient analysis...
> 
> I think from a practical perspective ensuring that the major IPsec/IKE
> tools, e.g. the various *SWANs, that know about labeled IPSec still
> build and can set/get the SA/SPD labels correctly would be sufficient.
> I seriously doubt there would be any problems, but who knows.

There are certainly some cases in which the transformation of
zero-length arrays into flexible-array members can bring some issues
to the surface[1][2]. This is the first time that we know of one of
them in user-space. However, we haven't transformed the arrays in
UAPI yet (with the exception of a couple of cases[3][4]). But that
is something that we are planning to try soon[5].

--
Gustavo

[1] https://github.com/KSPP/linux/issues?q=invalid+use+of+flexible+array
[2] https://github.com/KSPP/linux/issues?q=invalid+application+of+%E2%80%98sizeof%E2%80%99+to+incomplete+type
[3] https://git.kernel.org/linus/db243b796439c0caba47865564d8acd18a301d18
[4] https://git.kernel.org/linus/d6cdad870358128c1e753e6258e295ab8a5a2429
[5] https://git.kernel.org/pub/scm/linux/kernel/git/gustavoars/linux.git/commit/?h=for-next/kspp-fam0-uapi

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
  2022-05-05 20:12               ` Johannes Berg
@ 2022-05-06 11:15                   ` David Laight
  0 siblings, 0 replies; 71+ messages in thread
From: David Laight @ 2022-05-06 11:15 UTC (permalink / raw)
  To: 'Johannes Berg', Keith Packard, Kees Cook
  Cc: Gustavo A . R . Silva, Francis Laniel, Daniel Axtens,
	Dan Williams, Vincenzo Frascino, Guenter Roeck, Daniel Vetter,
	Tadeusz Struk, Alexei Starovoitov, alsa-devel, Al Viro,
	Andrew Gabbasov, Andrew Morton, Andy Gross, Andy Lavr,
	Arend van Spriel, Baowen Zheng, Bjorn Andersson, Boris Ostrovsky,
	Bradley Grove, brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, David Gow, David Howells, David S. Miller,
	Dennis Dalessandro, devicetree, Dexuan Cui, Dmitry Kasatkin,
	Eli Cohen, Eric Dumazet, Eric Paris, Eugeniu Rosca, Felipe Balbi,
	Frank Rowand, Franky Lin, Greg Kroah-Hartman, Gregory Greenman,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, John Keeping, Juergen Gross, Kalle Valo, keyrings,
	kunit-dev, Kuniyuki Iwashima, K. Y. Srinivasan,
	Lars-Peter Clausen, Lee Jones, Leon Romanovsky, Liam Girdwood,
	linux1394-devel, linux-afs, linux-arm-kernel, linux-arm-msm,
	linux-bluetooth, linux-hardening, linux-hyperv, linux-integrity,
	linux-rdma, linux-scsi, linux-security-module, linux-usb,
	linux-wireless, linux-xtensa, llvm, Loic Poulain, Louis Peens,
	Luca Coelho, Luiz Augusto von Dentz, Marc Dionne,
	Marcel Holtmann, Mark Brown, Martin K. Petersen, Max Filippov,
	Mimi Zohar, Muchun Song, Nathan Chancellor, netdev,
	Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Takashi Iwai, Tom Rix,
	Udipto Goswami, wcn36xx, Wei Liu, xen-devel, Xiu Jianfeng,
	Yang Yingliang

From: Johannes Berg
> Sent: 05 May 2022 21:13
> On Thu, 2022-05-05 at 13:08 -0700, Keith Packard wrote:
> 
> 
> > I bet you've already considered the simpler form:
> >
> >         struct something *instance = mem_to_flex_dup(byte_array, count, GFP_KERNEL);
> >         if (IS_ERR(instance))
> >             return PTR_ERR(instance);
> >
> 
> Sadly, this doesn't work in any way because mem_to_flex_dup() needs to
> know at least the type, hence passing 'instance', which is simpler than
> passing 'struct something'.

You can use:
         struct something *instance;
         mem_to_flex_dup(instance, byte_array, count, GFP_KERNEL);
         if (IS_ERR(instance))
             return PTR_ERR(instance);
and have mem_to_flex_dup() (which must be a #define) update 'instance'.
(You can require &instance - and just precede all the uses with
an extra '*' to make it more obvious the variable is updated.
But there is little point requiring it be NULL.)

If you really want to define the variable mid-block you can use:
         mem_to_flex_dup(struct something *, instance, byte_array, count, GFP_KERNEL);

but I really hate having declarations anywhere other than the top of
a function because it makes them hard for the 'mk1 eyeball' to spot.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: [PATCH 02/32] Introduce flexible array struct memcpy() helpers
@ 2022-05-06 11:15                   ` David Laight
  0 siblings, 0 replies; 71+ messages in thread
From: David Laight @ 2022-05-06 11:15 UTC (permalink / raw)
  To: 'Johannes Berg', Keith Packard, Kees Cook
  Cc: Christian Lamparter, Eli Cohen, K. Y. Srinivasan, Louis Peens,
	Wei Liu, Hulk Robot, Eugeniu Rosca, James Morris, xen-devel,
	Guenter Roeck, Marcel Holtmann, Al Viro, Kuniyuki Iwashima,
	Christian Brauner, Dmitry Kasatkin, Stephen Smalley, linux-usb,
	linux-wireless, John Keeping, Stefano Stabellini,
	Greg Kroah-Hartman, Andrew Morton, alsa-devel, Nick Desaulniers,
	Mimi Zohar, Max Filippov, Eric Dumazet, keyrings,
	Gregory Greenman, Francis Laniel, Lars-Peter Clausen,
	Stephen Hemminger, Bradley Grove, Leon Romanovsky,
	Udipto Goswami, linux-xtensa, Baowen Zheng, selinux,
	linux-arm-msm, Muchun Song, Boris Ostrovsky, linux-arm-kernel,
	Daniel Axtens, Chris Zankel, Gustavo A . R . Silva,
	Jarkko Sakkinen, linux-integrity, Cong Wang, David Gow, Tom Rix,
	Alexei Starovoitov, Nuno Sá,
	Luca Coelho, linux-hardening, Marc Dionne, Frank Rowand,
	linux-afs, Andrew Gabbasov, Dennis Dalessandro, linux-rdma,
	Dexuan Cui, Simon Horman, Paolo Abeni, Serge E. Hallyn,
	Jens Axboe, Xiu Jianfeng, James E.J. Bottomley, Yang Yingliang,
	Hante Meuleman, Nathan Chancellor, Paul Moore, Mark Brown,
	Eric Paris, Dan Williams, Tadeusz Struk, Christian Göttsche,
	Franky Lin, Felipe Balbi, Arend van Spriel, Martin K. Petersen,
	Liam Girdwood, Stefan Richter, David S. Miller, Daniel Vetter,
	llvm, Bjorn Andersson, David Howells, wcn36xx, Vincenzo Frascino,
	Lee Jones, Steffen Klassert, linux1394-devel, Herbert Xu,
	linux-scsi, Russell King, Jason Gunthorpe, SHA-cyfmac-dev-list,
	Andy Gross, Jakub Kicinski, Andy Lavr, Haiyang Zhang, devicetree,
	Johan Hedberg, linux-hyperv, Kalle Valo, Rich Felker,
	Rob Herring, Luiz Augusto von Dentz, kunit-dev, Juergen Gross,
	brcm80211-dev-list.pdl, Loic Poulain, netdev, Takashi Iwai,
	linux-bluetooth, linux-security-module

From: Johannes Berg
> Sent: 05 May 2022 21:13
> On Thu, 2022-05-05 at 13:08 -0700, Keith Packard wrote:
> 
> 
> > I bet you've already considered the simpler form:
> >
> >         struct something *instance = mem_to_flex_dup(byte_array, count, GFP_KERNEL);
> >         if (IS_ERR(instance))
> >             return PTR_ERR(instance);
> >
> 
> Sadly, this doesn't work in any way because mem_to_flex_dup() needs to
> know at least the type, hence passing 'instance', which is simpler than
> passing 'struct something'.

You can use:
         struct something *instance;
         mem_to_flex_dup(instance, byte_array, count, GFP_KERNEL);
         if (IS_ERR(instance))
             return PTR_ERR(instance);
and have mem_to_flex_dup() (which must be a #define) update 'instance'.
(You can require &instance - and just precede all the uses with
an extra '*' to make it more obvious the variable is updated.
But there is little point requiring it be NULL.)

If you really want to define the variable mid-block you can use:
         mem_to_flex_dup(struct something *, instance, byte_array, count, GFP_KERNEL);

but I really hate having declarations anywhere other than the top of
a function because it makes them hard for the 'mk1 eyeball' to spot.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
@ 2022-05-12 21:41   ` David Howells
  2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: David Howells @ 2022-05-12 21:41 UTC (permalink / raw)
  To: Kees Cook
  Cc: Gustavo A . R . Silva, David Howells, Marc Dionne, linux-afs,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David S. Miller, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang


Kees Cook <keescook@chromium.org> wrote:

>  struct afs_acl {
> -	u32	size;
> -	u8	data[];
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, size);
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
>  };

Oof...  That's really quite unpleasant syntax.  Is it not possible to have
mem_to_flex_dup() and friends work without that?  You are telling them the
fields they have to fill in.

> +	struct afs_acl *acl = NULL;
>  
> -	acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
> -	if (!acl) {
> +	if (mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL)) {

Please don't do that.  Either do:

	acl = mem_to_flex_dup(buffer, size, GFP_KERNEL);
	if (!acl)

or:

	acl = mem_to_flex_dup(buffer, size, GFP_KERNEL);
	if (IS_ERR(acl))

Please especially don't make it that an apparent 'true' return indicates an
error.  If you absolutely must return the acl pointer through the argument
list (presumably because it's actually a macro), make it return false on
failure:

	if (!mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL))

or return and explicitly check for an error code:

	if (mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL) < 0)

or:

	ret = mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL);
	if (ret < 0)

(or use != 0 rather than < 0)

David


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl
@ 2022-05-12 21:41   ` David Howells
  0 siblings, 0 replies; 71+ messages in thread
From: David Howells @ 2022-05-12 21:41 UTC (permalink / raw)
  To: Kees Cook
  Cc: Vincenzo Frascino, Christian Lamparter, Eli Cohen,
	K. Y. Srinivasan, Louis Peens, Wei Liu, Hulk Robot, James Morris,
	xen-devel, Guenter Roeck, Marcel Holtmann, Arend van Spriel,
	Al Viro, Kuniyuki Iwashima, Christian Brauner, Dmitry Kasatkin,
	Stephen Smalley, linux-usb, linux-wireless, John Keeping,
	Stefano Stabellini, Greg Kroah-Hartman, Andrew Morton,
	alsa-devel, Nick Desaulniers, Mimi Zohar, Max Filippov,
	Eric Dumazet, keyrings, Gregory Greenman, Francis Laniel,
	Lars-Peter Clausen, Stephen Hemminger, Bradley Grove,
	Leon Romanovsky, Udipto Goswami, linux-xtensa, Baowen Zheng,
	Johannes Berg, selinux, linux-arm-msm, Muchun Song,
	Boris Ostrovsky, linux-arm-kernel, Daniel Axtens, Chris Zankel,
	Gustavo A . R . Silva, Jarkko Sakkinen, linux-integrity,
	Cong Wang, David Gow, Tom Rix, Alexei Starovoitov, Nuno Sá,
	Luca Coelho, linux-hardening, Marc Dionne, Frank Rowand,
	linux-afs, Andrew Gabbasov, Dennis Dalessandro, linux-rdma,
	Dexuan Cui, Simon Horman, Paolo Abeni, Serge E. Hallyn,
	Jens Axboe, Xiu Jianfeng, James E.J. Bottomley, Yang Yingliang,
	Hante Meuleman, Nathan Chancellor, Paul Moore, Mark Brown,
	Eric Paris, Dan Williams, Tadeusz Struk, Christian Göttsche,
	Franky Lin, Felipe Balbi, Keith Packard, Martin K. Petersen,
	Liam Girdwood, Stefan Richter, David S. Miller, Daniel Vetter,
	llvm, Bjorn Andersson, David Howells, wcn36xx, Eugeniu Rosca,
	Lee Jones, Steffen Klassert, linux1394-devel, Herbert Xu,
	linux-scsi, Russell King, Jason Gunthorpe, SHA-cyfmac-dev-list,
	Andy Gross, Jakub Kicinski, Andy Lavr, Haiyang Zhang, devicetree,
	Johan Hedberg, linux-hyperv, Kalle Valo, Rich Felker,
	Rob Herring, Luiz Augusto von Dentz, kunit-dev, Juergen Gross,
	brcm80211-dev-list.pdl, Loic Poulain, netdev, Takashi Iwai,
	linux-bluetooth, linux-security-module, Johannes Berg


Kees Cook <keescook@chromium.org> wrote:

>  struct afs_acl {
> -	u32	size;
> -	u8	data[];
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, size);
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
>  };

Oof...  That's really quite unpleasant syntax.  Is it not possible to have
mem_to_flex_dup() and friends work without that?  You are telling them the
fields they have to fill in.

> +	struct afs_acl *acl = NULL;
>  
> -	acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
> -	if (!acl) {
> +	if (mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL)) {

Please don't do that.  Either do:

	acl = mem_to_flex_dup(buffer, size, GFP_KERNEL);
	if (!acl)

or:

	acl = mem_to_flex_dup(buffer, size, GFP_KERNEL);
	if (IS_ERR(acl))

Please especially don't make it that an apparent 'true' return indicates an
error.  If you absolutely must return the acl pointer through the argument
list (presumably because it's actually a macro), make it return false on
failure:

	if (!mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL))

or return and explicitly check for an error code:

	if (mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL) < 0)

or:

	ret = mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL);
	if (ret < 0)

(or use != 0 rather than < 0)

David


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 00/32] Introduce flexible array struct memcpy() helpers
  2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
@ 2022-05-12 21:47   ` David Howells
  2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
                     ` (32 subsequent siblings)
  33 siblings, 0 replies; 71+ messages in thread
From: David Howells @ 2022-05-12 21:47 UTC (permalink / raw)
  To: Kees Cook
  Cc: Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David Howells, David S. Miller, Dennis Dalessandro, devicetree,
	Dexuan Cui, Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-afs, linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marc Dionne, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang


Kees Cook <keescook@chromium.org> wrote:

> I'm happy to also point out that the conversions (patches 5+) are actually
> a net reduction in lines of code:
>  49 files changed, 154 insertions(+), 244 deletions(-)

That doesn't mean that it's actually code that's clearer to read.  I would say
that it's actually less clear.  In a bunch of places, you've done something
like:

-	e = kmalloc(...);
-	if (!e)
+	if (__mem_to_flex_dup(&e, ...))

The problem is that, to me at least, it looks like:

-	e = kmalloc(...);
-	if (kmalloc failed)
+	if (__mem_to_flex_dup(&e, ...) succeeded)

David


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 00/32] Introduce flexible array struct memcpy() helpers
@ 2022-05-12 21:47   ` David Howells
  0 siblings, 0 replies; 71+ messages in thread
From: David Howells @ 2022-05-12 21:47 UTC (permalink / raw)
  To: Kees Cook
  Cc: Vincenzo Frascino, Christian Lamparter, Eli Cohen,
	K. Y. Srinivasan, Louis Peens, Wei Liu, Hulk Robot, James Morris,
	xen-devel, Guenter Roeck, Marcel Holtmann, Arend van Spriel,
	Al Viro, Kuniyuki Iwashima, Christian Brauner, Dmitry Kasatkin,
	Stephen Smalley, linux-usb, linux-wireless, John Keeping,
	Stefano Stabellini, Greg Kroah-Hartman, Andrew Morton,
	alsa-devel, Nick Desaulniers, Mimi Zohar, Max Filippov,
	Eric Dumazet, keyrings, Gregory Greenman, Francis Laniel,
	Lars-Peter Clausen, Stephen Hemminger, Bradley Grove,
	Leon Romanovsky, Udipto Goswami, linux-xtensa, Baowen Zheng,
	Johannes Berg, selinux, linux-arm-msm, Muchun Song,
	Boris Ostrovsky, linux-arm-kernel, Daniel Axtens, Chris Zankel,
	Jarkko Sakkinen, linux-integrity, Cong Wang, David Gow, Tom Rix,
	Alexei Starovoitov, Nuno Sá,
	Luca Coelho, linux-hardening, Marc Dionne, Frank Rowand,
	linux-afs, Andrew Gabbasov, Dennis Dalessandro, linux-rdma,
	Dexuan Cui, Simon Horman, Paolo Abeni, Serge E. Hallyn,
	Jens Axboe, Xiu Jianfeng, James E.J. Bottomley, Yang Yingliang,
	Hante Meuleman, Nathan Chancellor, Paul Moore, Mark Brown,
	Eric Paris, Dan Williams, Tadeusz Struk, Christian Göttsche,
	Franky Lin, Felipe Balbi, Keith Packard, Martin K. Petersen,
	Liam Girdwood, Stefan Richter, David S. Miller, Daniel Vetter,
	llvm, Bjorn Andersson, David Howells, wcn36xx, Eugeniu Rosca,
	Lee Jones, Steffen Klassert, linux1394-devel, Herbert Xu,
	linux-scsi, Russell King, Jason Gunthorpe, SHA-cyfmac-dev-list,
	Andy Gross, Jakub Kicinski, Andy Lavr, Haiyang Zhang, devicetree,
	Johan Hedberg, linux-hyperv, Kalle Valo, Rich Felker,
	Rob Herring, Luiz Augusto von Dentz, kunit-dev, Juergen Gross,
	brcm80211-dev-list.pdl, Loic Poulain, netdev, Takashi Iwai,
	linux-bluetooth, linux-security-module, Johannes Berg


Kees Cook <keescook@chromium.org> wrote:

> I'm happy to also point out that the conversions (patches 5+) are actually
> a net reduction in lines of code:
>  49 files changed, 154 insertions(+), 244 deletions(-)

That doesn't mean that it's actually code that's clearer to read.  I would say
that it's actually less clear.  In a bunch of places, you've done something
like:

-	e = kmalloc(...);
-	if (!e)
+	if (__mem_to_flex_dup(&e, ...))

The problem is that, to me at least, it looks like:

-	e = kmalloc(...);
-	if (kmalloc failed)
+	if (__mem_to_flex_dup(&e, ...) succeeded)

David


^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl
  2022-05-12 21:41   ` David Howells
@ 2022-05-13 15:44     ` Kees Cook
  -1 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-13 15:44 UTC (permalink / raw)
  To: David Howells
  Cc: Gustavo A . R . Silva, Marc Dionne, linux-afs,
	Alexei Starovoitov, alsa-devel, Al Viro, Andrew Gabbasov,
	Andrew Morton, Andy Gross, Andy Lavr, Arend van Spriel,
	Baowen Zheng, Bjorn Andersson, Boris Ostrovsky, Bradley Grove,
	brcm80211-dev-list.pdl, Christian Brauner,
	Christian Göttsche, Christian Lamparter, Chris Zankel,
	Cong Wang, Daniel Axtens, Daniel Vetter, Dan Williams, David Gow,
	David S. Miller, Dennis Dalessandro, devicetree, Dexuan Cui,
	Dmitry Kasatkin, Eli Cohen, Eric Dumazet, Eric Paris,
	Eugeniu Rosca, Felipe Balbi, Francis Laniel, Frank Rowand,
	Franky Lin, Greg Kroah-Hartman, Gregory Greenman, Guenter Roeck,
	Haiyang Zhang, Hante Meuleman, Herbert Xu, Hulk Robot,
	Jakub Kicinski, James E.J. Bottomley, James Morris,
	Jarkko Sakkinen, Jaroslav Kysela, Jason Gunthorpe, Jens Axboe,
	Johan Hedberg, Johannes Berg, Johannes Berg, John Keeping,
	Juergen Gross, Kalle Valo, Keith Packard, keyrings, kunit-dev,
	Kuniyuki Iwashima, K. Y. Srinivasan, Lars-Peter Clausen,
	Lee Jones, Leon Romanovsky, Liam Girdwood, linux1394-devel,
	linux-arm-kernel, linux-arm-msm, linux-bluetooth,
	linux-hardening, linux-hyperv, linux-integrity, linux-rdma,
	linux-scsi, linux-security-module, linux-usb, linux-wireless,
	linux-xtensa, llvm, Loic Poulain, Louis Peens, Luca Coelho,
	Luiz Augusto von Dentz, Marcel Holtmann, Mark Brown,
	Martin K. Petersen, Max Filippov, Mimi Zohar, Muchun Song,
	Nathan Chancellor, netdev, Nick Desaulniers, Nuno Sá,
	Paolo Abeni, Paul Moore, Rich Felker, Rob Herring, Russell King,
	selinux, Serge E. Hallyn, SHA-cyfmac-dev-list, Simon Horman,
	Stefano Stabellini, Stefan Richter, Steffen Klassert,
	Stephen Hemminger, Stephen Smalley, Tadeusz Struk, Takashi Iwai,
	Tom Rix, Udipto Goswami, Vincenzo Frascino, wcn36xx, Wei Liu,
	xen-devel, Xiu Jianfeng, Yang Yingliang

On Thu, May 12, 2022 at 10:41:05PM +0100, David Howells wrote:
> 
> Kees Cook <keescook@chromium.org> wrote:
> 
> >  struct afs_acl {
> > -	u32	size;
> > -	u8	data[];
> > +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, size);
> > +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
> >  };
> 
> Oof...  That's really quite unpleasant syntax.  Is it not possible to have
> mem_to_flex_dup() and friends work without that?  You are telling them the
> fields they have to fill in.

Other threads discussed this too. I'm hoping to have something more
flexible (pardon the pun) in v2.

> [...]
> or:
> 
> 	ret = mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL);
> 	if (ret < 0)
> 
> (or use != 0 rather than < 0)

Sure, I can make the tests more explicit. The kerndoc, etc all shows it's
using < 0 for errors.

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl
@ 2022-05-13 15:44     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-13 15:44 UTC (permalink / raw)
  To: David Howells
  Cc: Vincenzo Frascino, Christian Lamparter, Eli Cohen,
	K. Y. Srinivasan, Louis Peens, Wei Liu, Hulk Robot, James Morris,
	xen-devel, Guenter Roeck, Arend van Spriel, Al Viro,
	Kuniyuki Iwashima, Christian Brauner, Dmitry Kasatkin,
	Stephen Smalley, linux-usb, linux-wireless, John Keeping,
	Stefano Stabellini, Greg Kroah-Hartman, Andrew Morton,
	alsa-devel, Nick Desaulniers, Mimi Zohar, Max Filippov,
	Eric Dumazet, keyrings, Gregory Greenman, Francis Laniel,
	Lars-Peter Clausen, Stephen Hemminger, Bradley Grove,
	Leon Romanovsky, Udipto Goswami, linux-xtensa, Baowen Zheng,
	Johannes Berg, selinux, linux-arm-msm, Muchun Song,
	Boris Ostrovsky, linux-arm-kernel, Daniel Axtens, Chris Zankel,
	Gustavo A . R . Silva, Jarkko Sakkinen, linux-integrity,
	Cong Wang, David Gow, Tom Rix, Alexei Starovoitov, Nuno Sá,
	Luca Coelho, linux-hardening, Marc Dionne, Frank Rowand,
	linux-afs, Andrew Gabbasov, Dennis Dalessandro, linux-rdma,
	Dexuan Cui, Simon Horman, Paolo Abeni, Serge E. Hallyn,
	Jens Axboe, Xiu Jianfeng, Marcel Holtmann, Yang Yingliang,
	Hante Meuleman, Nathan Chancellor, Paul Moore, Mark Brown,
	Eric Paris, Dan Williams, Tadeusz Struk, Christian Göttsche,
	Franky Lin, Felipe Balbi, Keith Packard, Martin K. Petersen,
	Haiyang Zhang, Liam Girdwood, Stefan Richter, David S. Miller,
	Daniel Vetter, llvm, Bjorn Andersson, wcn36xx, Eugeniu Rosca,
	Lee Jones, Steffen Klassert, linux1394-devel, Herbert Xu,
	linux-scsi, Russell King, Jason Gunthorpe, SHA-cyfmac-dev-list,
	Andy Gross, Jakub Kicinski, Andy Lavr, James E.J. Bottomley,
	devicetree, Johan Hedberg, linux-hyperv, Kalle Valo, Rich Felker,
	Rob Herring, Luiz Augusto von Dentz, kunit-dev, Juergen Gross,
	brcm80211-dev-list.pdl, Loic Poulain, netdev, Takashi Iwai,
	linux-bluetooth, linux-security-module, Johannes Berg

On Thu, May 12, 2022 at 10:41:05PM +0100, David Howells wrote:
> 
> Kees Cook <keescook@chromium.org> wrote:
> 
> >  struct afs_acl {
> > -	u32	size;
> > -	u8	data[];
> > +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, size);
> > +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
> >  };
> 
> Oof...  That's really quite unpleasant syntax.  Is it not possible to have
> mem_to_flex_dup() and friends work without that?  You are telling them the
> fields they have to fill in.

Other threads discussed this too. I'm hoping to have something more
flexible (pardon the pun) in v2.

> [...]
> or:
> 
> 	ret = mem_to_flex_dup(&acl, buffer, size, GFP_KERNEL);
> 	if (ret < 0)
> 
> (or use != 0 rather than < 0)

Sure, I can make the tests more explicit. The kerndoc, etc all shows it's
using < 0 for errors.

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item
  2022-05-04  1:44 ` [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item Kees Cook
@ 2022-05-16 12:49   ` Arend van Spriel
  2022-05-17  3:57     ` Kees Cook
  0 siblings, 1 reply; 71+ messages in thread
From: Arend van Spriel @ 2022-05-16 12:49 UTC (permalink / raw)
  To: Kees Cook, Gustavo A . R . Silva
  Cc: linux-wireless, Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 2603 bytes --]

On 5/4/2022 3:44 AM, Kees Cook wrote:
> As part of the work to perform bounds checking on all memcpy() uses,
> replace the open-coded a deserialization of bytes out of memory into a
> trailing flexible array by using a flex_array.h helper to perform the
> allocation, bounds checking, and copying.
> 
Reviewed-by: Arend van Spriel <aspriel@gmail.com>
> Cc: Franky Lin <franky.lin@broadcom.com>
> Cc: Hante Meuleman <hante.meuleman@broadcom.com>
> Cc: Kalle Valo <kvalo@kernel.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Paolo Abeni <pabeni@redhat.com>
> Cc: linux-wireless@vger.kernel.org
> Cc: brcm80211-dev-list.pdl@broadcom.com
> Cc: SHA-cyfmac-dev-list@infineon.com
> Cc: netdev@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>   .../net/wireless/broadcom/brcm80211/brcmfmac/fweh.c   | 11 ++++-------
>   1 file changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> index bc3f4e4edcdf..bea798ca6466 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> @@ -32,8 +32,8 @@ struct brcmf_fweh_queue_item {
>   	u8 ifidx;
>   	u8 ifaddr[ETH_ALEN];
>   	struct brcmf_event_msg_be emsg;
> -	u32 datalen;
> -	u8 data[];
> +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, datalen);
> +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
>   };
>   
>   /*
> @@ -395,7 +395,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
>   {
>   	enum brcmf_fweh_event_code code;
>   	struct brcmf_fweh_info *fweh = &drvr->fweh;
> -	struct brcmf_fweh_queue_item *event;
> +	struct brcmf_fweh_queue_item *event = NULL;
>   	void *data;
>   	u32 datalen;
>   
> @@ -414,8 +414,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
>   	    datalen + sizeof(*event_packet) > packet_len)
>   		return;
>   
> -	event = kzalloc(sizeof(*event) + datalen, gfp);
> -	if (!event)
> +	if (mem_to_flex_dup(&event, data, datalen, gfp))
>   		return;
>   
>   	event->code = code;
> @@ -423,8 +422,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
>   
>   	/* use memcpy to get aligned event message */
>   	memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
> -	memcpy(event->data, data, datalen);
> -	event->datalen = datalen;

So does mem_to_flex_dup() store event->datalen?

Don't have the entire thread so missing bits and pieces, but at least 
this raises questions for me.

Thanks,
Arend

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4219 bytes --]

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item
  2022-05-16 12:49   ` Arend van Spriel
@ 2022-05-17  3:57     ` Kees Cook
  0 siblings, 0 replies; 71+ messages in thread
From: Kees Cook @ 2022-05-17  3:57 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: Gustavo A . R . Silva, linux-wireless, Linux Kernel Mailing List

On Mon, May 16, 2022 at 02:49:21PM +0200, Arend van Spriel wrote:
> On 5/4/2022 3:44 AM, Kees Cook wrote:
> > As part of the work to perform bounds checking on all memcpy() uses,
> > replace the open-coded a deserialization of bytes out of memory into a
> > trailing flexible array by using a flex_array.h helper to perform the
> > allocation, bounds checking, and copying.
> > 
> Reviewed-by: Arend van Spriel <aspriel@gmail.com>

Thanks!

> > [...]
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> > index bc3f4e4edcdf..bea798ca6466 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
> > @@ -32,8 +32,8 @@ struct brcmf_fweh_queue_item {
> >   	u8 ifidx;
> >   	u8 ifaddr[ETH_ALEN];
> >   	struct brcmf_event_msg_be emsg;
> > -	u32 datalen;
> > -	u8 data[];
> > +	DECLARE_FLEX_ARRAY_ELEMENTS_COUNT(u32, datalen);
> > +	DECLARE_FLEX_ARRAY_ELEMENTS(u8, data);
> >   };
> > [...]
> > @@ -414,8 +414,7 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
> >   	    datalen + sizeof(*event_packet) > packet_len)
> >   		return;
> > -	event = kzalloc(sizeof(*event) + datalen, gfp);
> > -	if (!event)
> > +	if (mem_to_flex_dup(&event, data, datalen, gfp))
> >   		return;
> >   	event->code = code;
> > @@ -423,8 +422,6 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr,
> >   	/* use memcpy to get aligned event message */
> >   	memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
> > -	memcpy(event->data, data, datalen);
> > -	event->datalen = datalen;
> 
> So does mem_to_flex_dup() store event->datalen?
> 
> Don't have the entire thread so missing bits and pieces, but at least this
> raises questions for me.

Yes, that's part of the internal workings here -- the flex array counter
is declared and will be set as part of the copy.

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2022-05-17  3:57 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-04  1:44 [PATCH 00/32] Introduce flexible array struct memcpy() helpers Kees Cook
2022-05-04  1:44 ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Kees Cook
2022-05-04  3:12   ` Introduce flexible array struct memcpy() helpers bluez.test.bot
2022-05-04  3:31   ` [PATCH 01/32] netlink: Avoid memcpy() across flexible array boundary Gustavo A. R. Silva
2022-05-04  3:37     ` Kees Cook
2022-05-04  1:44 ` [PATCH 02/32] Introduce flexible array struct memcpy() helpers Kees Cook
2022-05-04  7:25   ` Johannes Berg
2022-05-04 15:38     ` Kees Cook
2022-05-04 16:08       ` David Laight
2022-05-05 13:16       ` Johannes Berg
2022-05-05 15:16         ` Keith Packard
2022-05-05 19:32           ` Kees Cook
2022-05-05 20:08             ` Keith Packard
2022-05-05 20:12               ` Johannes Berg
2022-05-06 11:15                 ` David Laight
2022-05-06 11:15                   ` David Laight
2022-05-05 19:27         ` Kees Cook
2022-05-04  1:44 ` [PATCH 03/32] flex_array: Add Kunit tests Kees Cook
2022-05-04  3:00   ` David Gow
2022-05-04 19:43     ` Kees Cook
2022-05-04 19:58   ` Daniel Latypov
2022-05-04  1:44 ` [PATCH 04/32] fortify: Add run-time WARN for cross-field memcpy() Kees Cook
2022-05-04  1:44 ` [PATCH 05/32] brcmfmac: Use mem_to_flex_dup() with struct brcmf_fweh_queue_item Kees Cook
2022-05-16 12:49   ` Arend van Spriel
2022-05-17  3:57     ` Kees Cook
2022-05-04  1:44 ` [PATCH 06/32] iwlwifi: calib: Prepare to use mem_to_flex_dup() Kees Cook
2022-05-04  1:44 ` [PATCH 07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result Kees Cook
2022-05-04  1:44 ` [PATCH 08/32] iwlwifi: mvm: Use mem_to_flex_dup() with struct ieee80211_key_conf Kees Cook
2022-05-04  1:44 ` [PATCH 09/32] p54: Use mem_to_flex_dup() with struct p54_cal_database Kees Cook
2022-05-04  1:44 ` [PATCH 10/32] wcn36xx: Use mem_to_flex_dup() with struct wcn36xx_hal_ind_msg Kees Cook
2022-05-04  5:42   ` Kalle Valo
2022-05-04 15:08     ` Kees Cook
2022-05-04  1:44 ` [PATCH 11/32] nl80211: Use mem_to_flex_dup() with struct cfg80211_cqm_config Kees Cook
2022-05-04  1:44 ` [PATCH 12/32] cfg80211: Use mem_to_flex_dup() with struct cfg80211_bss_ies Kees Cook
2022-05-04  7:28   ` Johannes Berg
2022-05-04 15:13     ` Kees Cook
2022-05-04  1:44 ` [PATCH 13/32] mac80211: Use mem_to_flex_dup() with several structs Kees Cook
2022-05-04  1:44 ` [PATCH 14/32] af_unix: Use mem_to_flex_dup() with struct unix_address Kees Cook
2022-05-04  1:44 ` [PATCH 15/32] 802/garp: Use mem_to_flex_dup() with struct garp_attr Kees Cook
2022-05-04  1:44 ` [PATCH 16/32] 802/mrp: Use mem_to_flex_dup() with struct mrp_attr Kees Cook
2022-05-04  1:44 ` [PATCH 17/32] net/flow_offload: Use mem_to_flex_dup() with struct flow_action_cookie Kees Cook
2022-05-04  1:44 ` [PATCH 18/32] firewire: Use __mem_to_flex_dup() with struct iso_interrupt_event Kees Cook
2022-05-04  1:44 ` [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl Kees Cook
2022-05-04  1:44 ` [PATCH 20/32] ASoC: sigmadsp: Use mem_to_flex_dup() with struct sigmadsp_data Kees Cook
2022-05-04 15:17   ` Mark Brown
2022-05-04  1:44 ` [PATCH 21/32] soc: qcom: apr: Use mem_to_flex_dup() with struct apr_rx_buf Kees Cook
2022-05-04  1:44 ` [PATCH 22/32] atags_proc: Use mem_to_flex_dup() with struct buffer Kees Cook
2022-05-04  1:44 ` [PATCH 23/32] Bluetooth: Use mem_to_flex_dup() with struct hci_op_configure_data_path Kees Cook
2022-05-04  1:44 ` [PATCH 24/32] IB/hfi1: Use mem_to_flex_dup() for struct tid_rb_node Kees Cook
2022-05-04  1:44 ` [PATCH 25/32] Drivers: hv: utils: Use mem_to_flex_dup() with struct cn_msg Kees Cook
2022-05-04  1:44 ` [PATCH 26/32] ima: Use mem_to_flex_dup() with struct modsig Kees Cook
2022-05-04  1:44 ` [PATCH 27/32] KEYS: Use mem_to_flex_dup() with struct user_key_payload Kees Cook
2022-05-04  1:44 ` [PATCH 28/32] selinux: Use mem_to_flex_dup() with xfrm and sidtab Kees Cook
2022-05-04 22:57   ` Paul Moore
2022-05-04 23:43     ` Gustavo A. R. Silva
2022-05-05  3:14       ` Paul Moore
2022-05-05 18:39         ` Kees Cook
2022-05-05 23:16           ` Paul Moore
2022-05-06  1:08             ` Gustavo A. R. Silva
2022-05-04  1:44 ` [PATCH 29/32] xtensa: Use mem_to_flex_dup() with struct property Kees Cook
2022-05-04 18:09   ` Rob Herring
2022-05-04 18:09     ` Rob Herring
2022-05-04  1:44 ` [PATCH 30/32] usb: gadget: f_fs: Use mem_to_flex_dup() with struct ffs_buffer Kees Cook
2022-05-04  1:44 ` [PATCH 31/32] xenbus: Use mem_to_flex_dup() with struct read_buffer Kees Cook
2022-05-04  1:44 ` [PATCH 32/32] esas2r: Use __mem_to_flex() with struct atto_ioctl Kees Cook
2022-05-12 21:41 ` [PATCH 19/32] afs: Use mem_to_flex_dup() with struct afs_acl David Howells
2022-05-12 21:41   ` David Howells
2022-05-13 15:44   ` Kees Cook
2022-05-13 15:44     ` Kees Cook
2022-05-12 21:47 ` [PATCH 00/32] Introduce flexible array struct memcpy() helpers David Howells
2022-05-12 21:47   ` David Howells

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.