Skip to content

Commit 4491001

Browse files
roygerjgross1
authored andcommitted
xen/netfront: force data bouncing when backend is untrusted
Bounce all data on the skbs to be transmitted into zeroed pages if the backend is untrusted. This avoids leaking data present in the pages shared with the backend but not part of the skb fragments. This requires introducing a new helper in order to allocate skbs with a size multiple of XEN_PAGE_SIZE so we don't leak contiguous data on the granted pages. Reporting whether the backend is to be trusted can be done using a module parameter, or from the xenstore frontend path as set by the toolstack when adding the device. This is CVE-2022-33741, part of XSA-403. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Juergen Gross <jgross@suse.com> Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent 307c8de commit 4491001

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

drivers/net/xen-netfront.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644);
6666
MODULE_PARM_DESC(max_queues,
6767
"Maximum number of queues per virtual interface");
6868

69+
static bool __read_mostly xennet_trusted = true;
70+
module_param_named(trusted, xennet_trusted, bool, 0644);
71+
MODULE_PARM_DESC(trusted, "Is the backend trusted");
72+
6973
#define XENNET_TIMEOUT (5 * HZ)
7074

7175
static const struct ethtool_ops xennet_ethtool_ops;
@@ -173,6 +177,9 @@ struct netfront_info {
173177
/* Is device behaving sane? */
174178
bool broken;
175179

180+
/* Should skbs be bounced into a zeroed buffer? */
181+
bool bounce;
182+
176183
atomic_t rx_gso_checksum_fixup;
177184
};
178185

@@ -666,6 +673,33 @@ static int xennet_xdp_xmit(struct net_device *dev, int n,
666673
return nxmit;
667674
}
668675

676+
struct sk_buff *bounce_skb(const struct sk_buff *skb)
677+
{
678+
unsigned int headerlen = skb_headroom(skb);
679+
/* Align size to allocate full pages and avoid contiguous data leaks */
680+
unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
681+
XEN_PAGE_SIZE);
682+
struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
683+
684+
if (!n)
685+
return NULL;
686+
687+
if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
688+
WARN_ONCE(1, "misaligned skb allocated\n");
689+
kfree_skb(n);
690+
return NULL;
691+
}
692+
693+
/* Set the data pointer */
694+
skb_reserve(n, headerlen);
695+
/* Set the tail pointer and length */
696+
skb_put(n, skb->len);
697+
698+
BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
699+
700+
skb_copy_header(n, skb);
701+
return n;
702+
}
669703

670704
#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
671705

@@ -719,9 +753,13 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
719753

720754
/* The first req should be at least ETH_HLEN size or the packet will be
721755
* dropped by netback.
756+
*
757+
* If the backend is not trusted bounce all data to zeroed pages to
758+
* avoid exposing contiguous data on the granted page not belonging to
759+
* the skb.
722760
*/
723-
if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
724-
nskb = skb_copy(skb, GFP_ATOMIC);
761+
if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
762+
nskb = bounce_skb(skb);
725763
if (!nskb)
726764
goto drop;
727765
dev_consume_skb_any(skb);
@@ -2215,6 +2253,10 @@ static int talk_to_netback(struct xenbus_device *dev,
22152253

22162254
info->netdev->irq = 0;
22172255

2256+
/* Check if backend is trusted. */
2257+
info->bounce = !xennet_trusted ||
2258+
!xenbus_read_unsigned(dev->nodename, "trusted", 1);
2259+
22182260
/* Check if backend supports multiple queues */
22192261
max_queues = xenbus_read_unsigned(info->xbdev->otherend,
22202262
"multi-queue-max-queues", 1);
@@ -2382,6 +2424,9 @@ static int xennet_connect(struct net_device *dev)
23822424
return err;
23832425
if (np->netback_has_xdp_headroom)
23842426
pr_info("backend supports XDP headroom\n");
2427+
if (np->bounce)
2428+
dev_info(&np->xbdev->dev,
2429+
"bouncing transmitted data to zeroed pages\n");
23852430

23862431
/* talk_to_netback() sets the correct number of queues */
23872432
num_queues = dev->real_num_tx_queues;

0 commit comments

Comments
 (0)