Skip to content

Commit a1afd82

Browse files
Dongli Zhanggregkh
authored andcommitted
xen-netfront: do not use ~0U as error return value for xennet_fill_frags()
[ Upstream commit a761129 ] xennet_fill_frags() uses ~0U as return value when the sk_buff is not able to cache extra fragments. This is incorrect because the return type of xennet_fill_frags() is RING_IDX and 0xffffffff is an expected value for ring buffer index. In the situation when the rsp_cons is approaching 0xffffffff, the return value of xennet_fill_frags() may become 0xffffffff which xennet_poll() (the caller) would regard as error. As a result, queue->rx.rsp_cons is set incorrectly because it is updated only when there is error. If there is no error, xennet_poll() would be responsible to update queue->rx.rsp_cons. Finally, queue->rx.rsp_cons would point to the rx ring buffer entries whose queue->rx_skbs[i] and queue->grant_rx_ref[i] are already cleared to NULL. This leads to NULL pointer access in the next iteration to process rx ring buffer entries. The symptom is similar to the one fixed in commit 00b3685 ("xen-netfront: do not assume sk_buff_head list is empty in error handling"). This patch changes the return type of xennet_fill_frags() to indicate whether it is successful or failed. The queue->rx.rsp_cons will be always updated inside this function. Fixes: ad4f15d ("xen/netfront: don't bug in case of too many frags") Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com> Reviewed-by: Juergen Gross <jgross@suse.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 36a4043 commit a1afd82

1 file changed

Lines changed: 9 additions & 8 deletions

File tree

drivers/net/xen-netfront.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,9 @@ static int xennet_set_skb_gso(struct sk_buff *skb,
890890
return 0;
891891
}
892892

893-
static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
894-
struct sk_buff *skb,
895-
struct sk_buff_head *list)
893+
static int xennet_fill_frags(struct netfront_queue *queue,
894+
struct sk_buff *skb,
895+
struct sk_buff_head *list)
896896
{
897897
RING_IDX cons = queue->rx.rsp_cons;
898898
struct sk_buff *nskb;
@@ -911,7 +911,7 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
911911
if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
912912
queue->rx.rsp_cons = ++cons + skb_queue_len(list);
913913
kfree_skb(nskb);
914-
return ~0U;
914+
return -ENOENT;
915915
}
916916

917917
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
@@ -922,7 +922,9 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
922922
kfree_skb(nskb);
923923
}
924924

925-
return cons;
925+
queue->rx.rsp_cons = cons;
926+
927+
return 0;
926928
}
927929

928930
static int checksum_setup(struct net_device *dev, struct sk_buff *skb)
@@ -1048,8 +1050,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
10481050
skb->data_len = rx->status;
10491051
skb->len += rx->status;
10501052

1051-
i = xennet_fill_frags(queue, skb, &tmpq);
1052-
if (unlikely(i == ~0U))
1053+
if (unlikely(xennet_fill_frags(queue, skb, &tmpq)))
10531054
goto err;
10541055

10551056
if (rx->flags & XEN_NETRXF_csum_blank)
@@ -1059,7 +1060,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
10591060

10601061
__skb_queue_tail(&rxq, skb);
10611062

1062-
queue->rx.rsp_cons = ++i;
1063+
i = ++queue->rx.rsp_cons;
10631064
work_done++;
10641065
}
10651066

0 commit comments

Comments
 (0)