From: Cezar Bulinaru <cbulinaru@xxxxxxxxx> 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@xxxxxxxxx> > --- > 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@xxxxxxxxxxxxx>