Netdev Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v7 0/3] Drivers: hv: vmbus: vmbus_requestor data structure for VMBus hardening
@ 2020-09-07 16:19 Andrea Parri (Microsoft)
2020-09-07 16:19 ` [PATCH v7 3/3] hv_netvsc: Use vmbus_requestor to generate transaction IDs " Andrea Parri (Microsoft)
0 siblings, 1 reply; 3+ messages in thread
From: Andrea Parri (Microsoft) @ 2020-09-07 16:19 UTC (permalink / raw)
To: linux-kernel
Cc: K . Y . Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu,
linux-hyperv, Andres Beltran, Michael Kelley, Saruhan Karademir,
Juan Vazquez, Andrea Parri (Microsoft),
James E . J . Bottomley, Martin K . Petersen, David S. Miller,
Jakub Kicinski, linux-scsi, netdev
Currently, VMbus drivers use pointers into guest memory as request IDs
for interactions with Hyper-V. To be more robust in the face of errors
or malicious behavior from a compromised Hyper-V, avoid exposing
guest memory addresses to Hyper-V. Also avoid Hyper-V giving back a
bad request ID that is then treated as the address of a guest data
structure with no validation. Instead, encapsulate these memory
addresses and provide small integers as request IDs.
The first patch creates the definitions for the data structure, provides
helper methods to generate new IDs and retrieve data, and
allocates/frees the memory needed for vmbus_requestor.
The second and third patches make use of vmbus_requestor to send request
IDs to Hyper-V in storvsc and netvsc respectively.
This version of the series moves the allocation of the requst ID after
the data has been copied into the ring buffer in hv_ringbuffer_write()
to address a race with the request completion path pointed out by Juan.
Andrea
Cc: James E.J. Bottomley <jejb@linux.ibm.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-scsi@vger.kernel.org
Cc: netdev@vger.kernel.org
Andres Beltran (3):
Drivers: hv: vmbus: Add vmbus_requestor data structure for VMBus
hardening
scsi: storvsc: Use vmbus_requestor to generate transaction IDs for
VMBus hardening
hv_netvsc: Use vmbus_requestor to generate transaction IDs for VMBus
hardening
drivers/hv/channel.c | 174 ++++++++++++++++++++++++++++--
drivers/hv/hyperv_vmbus.h | 3 +-
drivers/hv/ring_buffer.c | 28 ++++-
drivers/net/hyperv/hyperv_net.h | 13 +++
drivers/net/hyperv/netvsc.c | 22 ++--
drivers/net/hyperv/rndis_filter.c | 1 +
drivers/scsi/storvsc_drv.c | 26 ++++-
include/linux/hyperv.h | 23 ++++
8 files changed, 272 insertions(+), 18 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v7 3/3] hv_netvsc: Use vmbus_requestor to generate transaction IDs for VMBus hardening
2020-09-07 16:19 [PATCH v7 0/3] Drivers: hv: vmbus: vmbus_requestor data structure for VMBus hardening Andrea Parri (Microsoft)
@ 2020-09-07 16:19 ` Andrea Parri (Microsoft)
2020-09-07 22:02 ` Michael Kelley
0 siblings, 1 reply; 3+ messages in thread
From: Andrea Parri (Microsoft) @ 2020-09-07 16:19 UTC (permalink / raw)
To: linux-kernel
Cc: K . Y . Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu,
linux-hyperv, Andres Beltran, Michael Kelley, Saruhan Karademir,
Juan Vazquez, Andrea Parri, David S. Miller, Jakub Kicinski,
netdev
From: Andres Beltran <lkmlabelt@gmail.com>
Currently, pointers to guest memory are passed to Hyper-V as
transaction IDs in netvsc. In the face of errors or malicious
behavior in Hyper-V, netvsc should not expose or trust the transaction
IDs returned by Hyper-V to be valid guest memory addresses. Instead,
use small integers generated by vmbus_requestor as requests
(transaction) IDs.
Signed-off-by: Andres Beltran <lkmlabelt@gmail.com>
Co-developed-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org
---
Changes in v7:
- Move the allocation of the request ID after the data has been
copied into the ring buffer (cf. 1/3).
Changes in v2:
- Add casts to unsigned long to fix warnings on 32bit.
- Use an inline function to get the requestor size.
drivers/net/hyperv/hyperv_net.h | 13 +++++++++++++
drivers/net/hyperv/netvsc.c | 22 ++++++++++++++++------
drivers/net/hyperv/rndis_filter.c | 1 +
include/linux/hyperv.h | 1 +
4 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 2181d4538ab70..4d2b2d48ff2a1 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -847,6 +847,19 @@ struct nvsp_message {
#define NETVSC_XDP_HDRM 256
+#define NETVSC_MIN_OUT_MSG_SIZE (sizeof(struct vmpacket_descriptor) + \
+ sizeof(struct nvsp_message))
+#define NETVSC_MIN_IN_MSG_SIZE sizeof(struct vmpacket_descriptor)
+
+/* Estimated requestor size:
+ * out_ring_size/min_out_msg_size + in_ring_size/min_in_msg_size
+ */
+static inline u32 netvsc_rqstor_size(unsigned long ringbytes)
+{
+ return ringbytes / NETVSC_MIN_OUT_MSG_SIZE +
+ ringbytes / NETVSC_MIN_IN_MSG_SIZE;
+}
+
struct multi_send_data {
struct sk_buff *skb; /* skb containing the pkt */
struct hv_netvsc_packet *pkt; /* netvsc pkt pending */
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 41f5cf0bb9971..03e93e3ddbad8 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -50,7 +50,7 @@ void netvsc_switch_datapath(struct net_device *ndev, bool vf)
vmbus_sendpacket(dev->channel, init_pkt,
sizeof(struct nvsp_message),
- (unsigned long)init_pkt,
+ VMBUS_RQST_ID_NO_RESPONSE,
VM_PKT_DATA_INBAND, 0);
}
@@ -163,7 +163,7 @@ static void netvsc_revoke_recv_buf(struct hv_device *device,
ret = vmbus_sendpacket(device->channel,
revoke_packet,
sizeof(struct nvsp_message),
- (unsigned long)revoke_packet,
+ VMBUS_RQST_ID_NO_RESPONSE,
VM_PKT_DATA_INBAND, 0);
/* If the failure is because the channel is rescinded;
* ignore the failure since we cannot send on a rescinded
@@ -213,7 +213,7 @@ static void netvsc_revoke_send_buf(struct hv_device *device,
ret = vmbus_sendpacket(device->channel,
revoke_packet,
sizeof(struct nvsp_message),
- (unsigned long)revoke_packet,
+ VMBUS_RQST_ID_NO_RESPONSE,
VM_PKT_DATA_INBAND, 0);
/* If the failure is because the channel is rescinded;
@@ -542,7 +542,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
ret = vmbus_sendpacket(device->channel, init_packet,
sizeof(struct nvsp_message),
- (unsigned long)init_packet,
+ VMBUS_RQST_ID_NO_RESPONSE,
VM_PKT_DATA_INBAND, 0);
return ret;
@@ -599,7 +599,7 @@ static int netvsc_connect_vsp(struct hv_device *device,
/* Send the init request */
ret = vmbus_sendpacket(device->channel, init_packet,
sizeof(struct nvsp_message),
- (unsigned long)init_packet,
+ VMBUS_RQST_ID_NO_RESPONSE,
VM_PKT_DATA_INBAND, 0);
if (ret != 0)
goto cleanup;
@@ -680,10 +680,19 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
const struct vmpacket_descriptor *desc,
int budget)
{
- struct sk_buff *skb = (struct sk_buff *)(unsigned long)desc->trans_id;
+ struct sk_buff *skb;
struct net_device_context *ndev_ctx = netdev_priv(ndev);
u16 q_idx = 0;
int queue_sends;
+ u64 cmd_rqst;
+
+ cmd_rqst = vmbus_request_addr(&channel->requestor, (u64)desc->trans_id);
+ if (cmd_rqst == VMBUS_RQST_ERROR) {
+ netdev_err(ndev, "Incorrect transaction id\n");
+ return;
+ }
+
+ skb = (struct sk_buff *)(unsigned long)cmd_rqst;
/* Notify the layer above us */
if (likely(skb)) {
@@ -1422,6 +1431,7 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
netvsc_poll, NAPI_POLL_WEIGHT);
/* Open the channel */
+ device->channel->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes);
ret = vmbus_open(device->channel, netvsc_ring_bytes,
netvsc_ring_bytes, NULL, 0,
netvsc_channel_cb, net_device->chan_table);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index b81ceba38218c..10489ba44a090 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1114,6 +1114,7 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
/* Set the channel before opening.*/
nvchan->channel = new_sc;
+ new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes);
ret = vmbus_open(new_sc, netvsc_ring_bytes,
netvsc_ring_bytes, NULL, 0,
netvsc_channel_cb, nvchan);
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 45c7831ba0ef1..32c03643577b4 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -731,6 +731,7 @@ struct vmbus_requestor {
#define VMBUS_NO_RQSTOR U64_MAX
#define VMBUS_RQST_ERROR (U64_MAX - 1)
+#define VMBUS_RQST_ID_NO_RESPONSE (U64_MAX - 2)
struct vmbus_device {
u16 dev_type;
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH v7 3/3] hv_netvsc: Use vmbus_requestor to generate transaction IDs for VMBus hardening
2020-09-07 16:19 ` [PATCH v7 3/3] hv_netvsc: Use vmbus_requestor to generate transaction IDs " Andrea Parri (Microsoft)
@ 2020-09-07 22:02 ` Michael Kelley
0 siblings, 0 replies; 3+ messages in thread
From: Michael Kelley @ 2020-09-07 22:02 UTC (permalink / raw)
To: Andrea Parri (Microsoft), linux-kernel
Cc: KY Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu,
linux-hyperv, Andres Beltran, Saruhan Karademir, Juan Vazquez,
David S. Miller, Jakub Kicinski, netdev
From: Andrea Parri (Microsoft) <parri.andrea@gmail.com> Sent: Monday, September 7, 2020 9:19 AM
>
> From: Andres Beltran <lkmlabelt@gmail.com>
>
> Currently, pointers to guest memory are passed to Hyper-V as
> transaction IDs in netvsc. In the face of errors or malicious
> behavior in Hyper-V, netvsc should not expose or trust the transaction
> IDs returned by Hyper-V to be valid guest memory addresses. Instead,
> use small integers generated by vmbus_requestor as requests
> (transaction) IDs.
>
> Signed-off-by: Andres Beltran <lkmlabelt@gmail.com>
> Co-developed-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
> Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: netdev@vger.kernel.org
> ---
> Changes in v7:
> - Move the allocation of the request ID after the data has been
> copied into the ring buffer (cf. 1/3).
> Changes in v2:
> - Add casts to unsigned long to fix warnings on 32bit.
> - Use an inline function to get the requestor size.
>
> drivers/net/hyperv/hyperv_net.h | 13 +++++++++++++
> drivers/net/hyperv/netvsc.c | 22 ++++++++++++++++------
> drivers/net/hyperv/rndis_filter.c | 1 +
> include/linux/hyperv.h | 1 +
> 4 files changed, 31 insertions(+), 6 deletions(-)
>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-09-07 22:02 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-07 16:19 [PATCH v7 0/3] Drivers: hv: vmbus: vmbus_requestor data structure for VMBus hardening Andrea Parri (Microsoft)
2020-09-07 16:19 ` [PATCH v7 3/3] hv_netvsc: Use vmbus_requestor to generate transaction IDs " Andrea Parri (Microsoft)
2020-09-07 22:02 ` Michael Kelley
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).