Skip to content

Commit 4437b0b

Browse files
Dongli Zhanggregkh
Dongli Zhang
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 <[email protected]> Reviewed-by: Juergen Gross <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 04e6fa0 commit 4437b0b

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

drivers/net/xen-netfront.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -887,9 +887,9 @@ static int xennet_set_skb_gso(struct sk_buff *skb,
887887
return 0;
888888
}
889889

890-
static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
891-
struct sk_buff *skb,
892-
struct sk_buff_head *list)
890+
static int xennet_fill_frags(struct netfront_queue *queue,
891+
struct sk_buff *skb,
892+
struct sk_buff_head *list)
893893
{
894894
RING_IDX cons = queue->rx.rsp_cons;
895895
struct sk_buff *nskb;
@@ -908,7 +908,7 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
908908
if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
909909
queue->rx.rsp_cons = ++cons + skb_queue_len(list);
910910
kfree_skb(nskb);
911-
return ~0U;
911+
return -ENOENT;
912912
}
913913

914914
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
@@ -919,7 +919,9 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue,
919919
kfree_skb(nskb);
920920
}
921921

922-
return cons;
922+
queue->rx.rsp_cons = cons;
923+
924+
return 0;
923925
}
924926

925927
static int checksum_setup(struct net_device *dev, struct sk_buff *skb)
@@ -1045,8 +1047,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
10451047
skb->data_len = rx->status;
10461048
skb->len += rx->status;
10471049

1048-
i = xennet_fill_frags(queue, skb, &tmpq);
1049-
if (unlikely(i == ~0U))
1050+
if (unlikely(xennet_fill_frags(queue, skb, &tmpq)))
10501051
goto err;
10511052

10521053
if (rx->flags & XEN_NETRXF_csum_blank)
@@ -1056,7 +1057,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
10561057

10571058
__skb_queue_tail(&rxq, skb);
10581059

1059-
queue->rx.rsp_cons = ++i;
1060+
i = ++queue->rx.rsp_cons;
10601061
work_done++;
10611062
}
10621063

0 commit comments

Comments
 (0)