lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Wed, 26 Jan 2022 13:28:25 -0800
From:   Saeed Mahameed <saeedm@...dia.com>
To:     Kees Cook <keescook@...omium.org>
Cc:     Leon Romanovsky <leon@...nel.org>,
        "David S. Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>,
        Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        Jesper Dangaard Brouer <hawk@...nel.org>,
        John Fastabend <john.fastabend@...il.com>,
        netdev@...r.kernel.org, linux-rdma@...r.kernel.org,
        bpf@...r.kernel.org, Andrii Nakryiko <andrii@...nel.org>,
        Martin KaFai Lau <kafai@...com>,
        Song Liu <songliubraving@...com>, Yonghong Song <yhs@...com>,
        KP Singh <kpsingh@...nel.org>, linux-kernel@...r.kernel.org,
        linux-hardening@...r.kernel.org
Subject: Re: [PATCH v2 RESEND] net/mlx5e: Avoid field-overflowing memcpy()

On 24 Jan 09:20, Kees Cook wrote:
>In preparation for FORTIFY_SOURCE performing compile-time and run-time
>field bounds checking for memcpy(), memmove(), and memset(), avoid
>intentionally writing across neighboring fields.
>
>Use flexible arrays instead of zero-element arrays (which look like they
>are always overflowing) and split the cross-field memcpy() into two halves
>that can be appropriately bounds-checked by the compiler.
>
>We were doing:
>
>	#define ETH_HLEN  14
>	#define VLAN_HLEN  4
>	...
>	#define MLX5E_XDP_MIN_INLINE (ETH_HLEN + VLAN_HLEN)
>	...
>        struct mlx5e_tx_wqe      *wqe  = mlx5_wq_cyc_get_wqe(wq, pi);
>	...
>        struct mlx5_wqe_eth_seg  *eseg = &wqe->eth;
>        struct mlx5_wqe_data_seg *dseg = wqe->data;
>	...
>	memcpy(eseg->inline_hdr.start, xdptxd->data, MLX5E_XDP_MIN_INLINE);
>
>target is wqe->eth.inline_hdr.start (which the compiler sees as being
>2 bytes in size), but copying 18, intending to write across start
>(really vlan_tci, 2 bytes). The remaining 16 bytes get written into
>wqe->data[0], covering byte_count (4 bytes), lkey (4 bytes), and addr
>(8 bytes).
>
>struct mlx5e_tx_wqe {
>        struct mlx5_wqe_ctrl_seg   ctrl;                 /*     0    16 */
>        struct mlx5_wqe_eth_seg    eth;                  /*    16    16 */
>        struct mlx5_wqe_data_seg   data[];               /*    32     0 */
>
>        /* size: 32, cachelines: 1, members: 3 */
>        /* last cacheline: 32 bytes */
>};
>
>struct mlx5_wqe_eth_seg {
>        u8                         swp_outer_l4_offset;  /*     0     1 */
>        u8                         swp_outer_l3_offset;  /*     1     1 */
>        u8                         swp_inner_l4_offset;  /*     2     1 */
>        u8                         swp_inner_l3_offset;  /*     3     1 */
>        u8                         cs_flags;             /*     4     1 */
>        u8                         swp_flags;            /*     5     1 */
>        __be16                     mss;                  /*     6     2 */
>        __be32                     flow_table_metadata;  /*     8     4 */
>        union {
>                struct {
>                        __be16     sz;                   /*    12     2 */
>                        u8         start[2];             /*    14     2 */
>                } inline_hdr;                            /*    12     4 */
>                struct {
>                        __be16     type;                 /*    12     2 */
>                        __be16     vlan_tci;             /*    14     2 */
>                } insert;                                /*    12     4 */
>                __be32             trailer;              /*    12     4 */
>        };                                               /*    12     4 */
>
>        /* size: 16, cachelines: 1, members: 9 */
>        /* last cacheline: 16 bytes */
>};
>
>struct mlx5_wqe_data_seg {
>        __be32                     byte_count;           /*     0     4 */
>        __be32                     lkey;                 /*     4     4 */
>        __be64                     addr;                 /*     8     8 */
>
>        /* size: 16, cachelines: 1, members: 3 */
>        /* last cacheline: 16 bytes */
>};
>
>So, split the memcpy() so the compiler can reason about the buffer
>sizes.
>
>"pahole" shows no size nor member offset changes to struct mlx5e_tx_wqe
>nor struct mlx5e_umr_wqe. "objdump -d" shows no meaningful object
>code changes (i.e. only source line number induced differences and
>optimizations).
>
>Cc: Saeed Mahameed <saeedm@...dia.com>
>Cc: Leon Romanovsky <leon@...nel.org>
>Cc: "David S. Miller" <davem@...emloft.net>
>Cc: Jakub Kicinski <kuba@...nel.org>
>Cc: Alexei Starovoitov <ast@...nel.org>
>Cc: Daniel Borkmann <daniel@...earbox.net>
>Cc: Jesper Dangaard Brouer <hawk@...nel.org>
>Cc: John Fastabend <john.fastabend@...il.com>
>Cc: netdev@...r.kernel.org
>Cc: linux-rdma@...r.kernel.org
>Cc: bpf@...r.kernel.org
>Signed-off-by: Kees Cook <keescook@...omium.org>
>---
>Since this results in no binary differences, I will carry this in my tree
>unless someone else wants to pick it up. It's one of the last remaining
>clean-ups needed for the next step in memcpy() hardening.

applied to net-next-mlx5.

Thanks,
Saeed

Powered by blists - more mailing lists