mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
hv_netvsc: Use vmbus_requestor to generate transaction IDs for VMBus hardening
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> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Acked-by: Jakub Kicinski <kuba@kernel.org> Reviewed-by: Wei Liu <wei.liu@kernel.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Jakub Kicinski <kuba@kernel.org> Cc: netdev@vger.kernel.org Link: https://lore.kernel.org/r/20201109100402.8946-4-parri.andrea@gmail.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
This commit is contained in:
parent
453de21c2b
commit
4d18fcc95f
@ -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;
|
||||
}
|
||||
|
||||
#define NETVSC_XFER_HEADER_SIZE(rng_cnt) \
|
||||
(offsetof(struct vmtransfer_page_packet_header, ranges) + \
|
||||
(rng_cnt) * sizeof(struct vmtransfer_page_range))
|
||||
|
@ -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;
|
||||
@ -557,7 +557,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;
|
||||
@ -614,7 +614,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;
|
||||
@ -695,10 +695,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 net_device_context *ndev_ctx = netdev_priv(ndev);
|
||||
struct sk_buff *skb;
|
||||
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)) {
|
||||
@ -1520,6 +1529,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);
|
||||
|
@ -1172,6 +1172,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);
|
||||
|
@ -779,6 +779,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;
|
||||
|
Loading…
Reference in New Issue
Block a user