# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID dcee7eca71afd3525543388d4aa22ec95564cdc1
# Parent af1aa35265eb0d2566e14ed530e4e7e442a9f132
[NET] back: Copy tx_ring data before verification
We need to make a copy of data from tx_ring before
verifying them as otherwise what we end up using may
be different from what was verified.
Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 55 ++++++++++-----------
1 files changed, 28 insertions(+), 27 deletions(-)
diff -r af1aa35265eb -r dcee7eca71af
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Oct 12
14:28:59 2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Oct 12
16:09:15 2006 +0100
@@ -883,20 +883,28 @@ static void netbk_tx_err(netif_t *netif,
netif_put(netif);
}
-static int netbk_count_requests(netif_t *netif, netif_tx_request_t *txp,
- int work_to_do)
-{
- netif_tx_request_t *first = txp;
+static int netbk_count_requests(netif_t *netif, netif_tx_request_t *first,
+ netif_tx_request_t *txp, int work_to_do)
+{
RING_IDX cons = netif->tx.req_cons;
int frags = 0;
- while (txp->flags & NETTXF_more_data) {
+ if (!(first->flags & NETTXF_more_data))
+ return 0;
+
+ do {
if (frags >= work_to_do) {
DPRINTK("Need more frags\n");
return -frags;
}
- txp = RING_GET_REQUEST(&netif->tx, cons + frags);
+ if (unlikely(frags >= MAX_SKB_FRAGS)) {
+ DPRINTK("Too many frags\n");
+ return -frags;
+ }
+
+ memcpy(txp, RING_GET_REQUEST(&netif->tx, cons + frags),
+ sizeof(*txp));
if (txp->size > first->size) {
DPRINTK("Frags galore\n");
return -frags;
@@ -910,27 +918,25 @@ static int netbk_count_requests(netif_t
txp->offset, txp->size);
return -frags;
}
- }
+ } while ((txp++)->flags & NETTXF_more_data);
return frags;
}
static gnttab_map_grant_ref_t *netbk_get_requests(netif_t *netif,
struct sk_buff *skb,
+ netif_tx_request_t *txp,
gnttab_map_grant_ref_t *mop)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
skb_frag_t *frags = shinfo->frags;
- netif_tx_request_t *txp;
unsigned long pending_idx = *((u16 *)skb->data);
- RING_IDX cons = netif->tx.req_cons;
int i, start;
/* Skip first skb fragment if it is on same page as header fragment. */
start = ((unsigned long)shinfo->frags[0].page == pending_idx);
- for (i = start; i < shinfo->nr_frags; i++) {
- txp = RING_GET_REQUEST(&netif->tx, cons++);
+ for (i = start; i < shinfo->nr_frags; i++, txp++) {
pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)];
gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx),
@@ -1044,7 +1050,7 @@ int netbk_get_extras(netif_t *netif, str
int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras,
int work_to_do)
{
- struct netif_extra_info *extra;
+ struct netif_extra_info extra;
RING_IDX cons = netif->tx.req_cons;
do {
@@ -1053,18 +1059,18 @@ int netbk_get_extras(netif_t *netif, str
return -EBADR;
}
- extra = (struct netif_extra_info *)
- RING_GET_REQUEST(&netif->tx, cons);
- if (unlikely(!extra->type ||
- extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+ memcpy(&extra, RING_GET_REQUEST(&netif->tx, cons),
+ sizeof(extra));
+ if (unlikely(!extra.type ||
+ extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
netif->tx.req_cons = ++cons;
- DPRINTK("Invalid extra type: %d\n", extra->type);
+ DPRINTK("Invalid extra type: %d\n", extra.type);
return -EINVAL;
}
- memcpy(&extras[extra->type - 1], extra, sizeof(*extra));
+ memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
netif->tx.req_cons = ++cons;
- } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+ } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
return work_to_do;
}
@@ -1099,6 +1105,7 @@ static void net_tx_action(unsigned long
struct sk_buff *skb;
netif_t *netif;
netif_tx_request_t txreq;
+ netif_tx_request_t txfrags[MAX_SKB_FRAGS];
struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
u16 pending_idx;
RING_IDX i;
@@ -1175,18 +1182,12 @@ static void net_tx_action(unsigned long
}
}
- ret = netbk_count_requests(netif, &txreq, work_to_do);
+ ret = netbk_count_requests(netif, &txreq, txfrags, work_to_do);
if (unlikely(ret < 0)) {
netbk_tx_err(netif, &txreq, i - ret);
continue;
}
i += ret;
-
- if (unlikely(ret > MAX_SKB_FRAGS)) {
- DPRINTK("Too many frags\n");
- netbk_tx_err(netif, &txreq, i);
- continue;
- }
if (unlikely(txreq.size < ETH_HLEN)) {
DPRINTK("Bad packet size: %d\n", txreq.size);
@@ -1256,7 +1257,7 @@ static void net_tx_action(unsigned long
pending_cons++;
- mop = netbk_get_requests(netif, skb, mop);
+ mop = netbk_get_requests(netif, skb, txfrags, mop);
netif->tx.req_cons = i;
netif_schedule_work(netif);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|