netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter
@ 2022-10-11 19:25 Cezar Bulinaru
  2022-10-11 21:24 ` Michael Kelley (LINUX)
  2022-10-11 23:27 ` Dexuan Cui
  0 siblings, 2 replies; 3+ messages in thread
From: Cezar Bulinaru @ 2022-10-11 19:25 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, davem, edumazet, kuba,
	linux-hyperv, netdev
  Cc: cbulinaru

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@gmail.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


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

* RE: [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter
  2022-10-11 19:25 [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter Cezar Bulinaru
@ 2022-10-11 21:24 ` Michael Kelley (LINUX)
  2022-10-11 23:27 ` Dexuan Cui
  1 sibling, 0 replies; 3+ messages in thread
From: Michael Kelley (LINUX) @ 2022-10-11 21:24 UTC (permalink / raw)
  To: Cezar Bulinaru, KY Srinivasan, Haiyang Zhang, wei.liu@kernel.org,
	Dexuan Cui, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, linux-hyperv@vger.kernel.org,
	netdev@vger.kernel.org

From: Cezar Bulinaru <cbulinaru@gmail.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@gmail.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@microsoft.com>

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

* RE: [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter
  2022-10-11 19:25 [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter Cezar Bulinaru
  2022-10-11 21:24 ` Michael Kelley (LINUX)
@ 2022-10-11 23:27 ` Dexuan Cui
  1 sibling, 0 replies; 3+ messages in thread
From: Dexuan Cui @ 2022-10-11 23:27 UTC (permalink / raw)
  To: Cezar Bulinaru, KY Srinivasan, Haiyang Zhang, wei.liu@kernel.org,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	linux-hyperv@vger.kernel.org, netdev@vger.kernel.org

> From: Cezar Bulinaru <cbulinaru@gmail.com>
> Sent: Tuesday, October 11, 2022 12:26 PM
> Subject: [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter

A better subject line is:
[PATCH] hv_netvsc: Fix a warning triggered by memcpy in rndis_filter

(please refer to "git log drivers/net/hyperv/rndis_filter.c", and there was
a typo in your subject: s/trigered/triggered )

> A bugcheck is trigered when the response message len exceeds
s/bugcheck/warning

I think a bugcheck is a crash in Windows's terminology.
Here it's just a harmless warning rather than a crash.

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

end of thread, other threads:[~2022-10-11 23:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-11 19:25 [PATCH] net: hyperv: bugcheck trigered by memcpy in rndis_filter Cezar Bulinaru
2022-10-11 21:24 ` Michael Kelley (LINUX)
2022-10-11 23:27 ` Dexuan Cui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).