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  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <BYAPR21MB16884DCA8A74DB851930AD71D7239@BYAPR21MB1688.namprd21.prod.outlook.com>
Date:   Tue, 11 Oct 2022 21:24:38 +0000
From:   "Michael Kelley (LINUX)" <mikelley@...rosoft.com>
To:     Cezar Bulinaru <cbulinaru@...il.com>,
        KY Srinivasan <kys@...rosoft.com>,
        Haiyang Zhang <haiyangz@...rosoft.com>,
        "wei.liu@...nel.org" <wei.liu@...nel.org>,
        Dexuan Cui <decui@...rosoft.com>,
        "davem@...emloft.net" <davem@...emloft.net>,
        "edumazet@...gle.com" <edumazet@...gle.com>,
        "kuba@...nel.org" <kuba@...nel.org>,
        "linux-hyperv@...r.kernel.org" <linux-hyperv@...r.kernel.org>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>
Subject: RE: [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter

From: Cezar Bulinaru <cbulinaru@...il.com> Sent: Tuesday, October 11, 2022 12:26 PM
> 
> A bugcheck is trigered when the response message len exceeds
> the size of rndis_message. Inside the rndis_request structure
> these fields are however followed by a RNDIS_EXT_LEN padding
> so it is safe to use unsafe_memcpy.
> 
> memcpy: detected field-spanning write (size 168) of single field "(void *)&request-
> >response_msg + (sizeof(struct rndis_message) - sizeof(union
> rndis_message_container)) + sizeof(*req_id)" at drivers/net/hyperv/rndis_filter.c:338
> (size 40)
> RSP: 0018:ffffc90000144de0 EFLAGS: 00010282
> RAX: 0000000000000000 RBX: ffff8881766b4000 RCX: 0000000000000000
> RDX: 0000000000000102 RSI: 0000000000009ffb RDI: 00000000ffffffff
> RBP: ffffc90000144e38 R08: 0000000000000000 R09: 00000000ffffdfff
> R10: ffffc90000144c48 R11: ffffffff82f56ac8 R12: ffff8881766b403c
> R13: 00000000000000a8 R14: ffff888100b75000 R15: ffff888179301d00
> FS:  0000000000000000(0000) GS:ffff8884d6280000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 000055f8b024c418 CR3: 0000000176548001 CR4: 00000000003706e0
> Call Trace:
>  <IRQ>
>  ? _raw_spin_unlock_irqrestore+0x27/0x50
>  netvsc_poll+0x556/0x940 [hv_netvsc]
>  __napi_poll+0x2e/0x170
>  net_rx_action+0x299/0x2f0
>  __do_softirq+0xed/0x2ef
>  __irq_exit_rcu+0x9f/0x110
>  irq_exit_rcu+0xe/0x20
>  sysvec_hyperv_callback+0xb0/0xd0
>  </IRQ>
>  <TASK>
>  asm_sysvec_hyperv_callback+0x1b/0x20
> RIP: 0010:native_safe_halt+0xb/0x10
> 
> Signed-off-by: Cezar Bulinaru <cbulinaru@...il.com>
> ---
>  drivers/net/hyperv/rndis_filter.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
> index 11f767a20444..eea777ec2541 100644
> --- a/drivers/net/hyperv/rndis_filter.c
> +++ b/drivers/net/hyperv/rndis_filter.c
> @@ -20,6 +20,7 @@
>  #include <linux/vmalloc.h>
>  #include <linux/rtnetlink.h>
>  #include <linux/ucs2_string.h>
> +#include <linux/string.h>
> 
>  #include "hyperv_net.h"
>  #include "netvsc_trace.h"
> @@ -335,9 +336,10 @@ static void rndis_filter_receive_response(struct net_device
> *ndev,
>                 if (resp->msg_len <=
>                     sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
>                         memcpy(&request->response_msg, resp, RNDIS_HEADER_SIZE + sizeof(*req_id));
> -                       memcpy((void *)&request->response_msg + RNDIS_HEADER_SIZE + sizeof(*req_id),
> +                       unsafe_memcpy((void *)&request->response_msg + RNDIS_HEADER_SIZE + sizeof(*req_id),
>                                data + RNDIS_HEADER_SIZE + sizeof(*req_id),
> -                              resp->msg_len - RNDIS_HEADER_SIZE - sizeof(*req_id));
> +                              resp->msg_len - RNDIS_HEADER_SIZE - sizeof(*req_id),
> +                              "request->response_msg is followed by a padding of RNDIS_EXT_LEN inside rndis_request");
>                         if (request->request_msg.ndis_msg_type ==
>                             RNDIS_MSG_QUERY && request->request_msg.msg.
>                             query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
> --
> 2.37.1

Thanks for fixing this.  I had it on my list of things to look at this week, but
I probably would have beat my head against the wall trying to get memcpy()
to work without generating the warning.  I can see now that the way the
RNDIS_EXT_LEN padding is set up, using the unsafe version is the only choice.
Maybe there's a better way to embed the struct rndis_message and padding
inside the struct rndis_request, but that better way isn't obvious.  Any change
would have ripple effects through code that is carefully crafted to reject
malformed and potentially malicious messages, so it's best to leave it as is.

Reviewed-by: Michael Kelley <mikelley@...rosoft.com>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ