ethdev: fix shallow copy of flow API RAW item
authorAdrien Mazarguil <adrien.mazarguil@6wind.com>
Mon, 21 May 2018 11:44:28 +0000 (13:44 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 22 May 2018 22:35:01 +0000 (00:35 +0200)
Like original commit mentioned below, this fix synchronizes flow rule copy
function with testpmd's own implementation following "app/testpmd: fix copy
of raw flow item (revisited)".

It addresses a crash that occurs when feeding a RAW pattern item to
rte_flow_copy(). Besides external applications, two PMDs (bonding and
failsafe) rely on this function internally.

Note the scope of this patch is limited to the RAW pattern item and has no
impact on all others.

Fixes: 972bf3610611 ("ethdev: fix shallow copy of flow API RSS action")
Cc: stable@dpdk.org
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
lib/librte_ethdev/rte_flow.c

index 7947529..b2afba0 100644 (file)
@@ -300,15 +300,24 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
                    enum item_spec_type type)
 {
        size_t size = 0;
-       const void *item_spec =
+       const void *data =
                type == ITEM_SPEC ? item->spec :
                type == ITEM_LAST ? item->last :
                type == ITEM_MASK ? item->mask :
                NULL;
 
-       if (!item_spec)
+       if (!item->spec || !data)
                goto empty;
        switch (item->type) {
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } spec;
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } last;
+               union {
+                       const struct rte_flow_item_raw *raw;
+               } mask;
                union {
                        const struct rte_flow_item_raw *raw;
                } src;
@@ -318,11 +327,21 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
                size_t off;
 
        case RTE_FLOW_ITEM_TYPE_RAW:
-               src.raw = item_spec;
+               spec.raw = item->spec;
+               last.raw = item->last ? item->last : item->spec;
+               mask.raw = item->mask ? item->mask : &rte_flow_item_raw_mask;
+               src.raw = data;
                dst.raw = buf;
                off = RTE_ALIGN_CEIL(sizeof(struct rte_flow_item_raw),
                                     sizeof(*src.raw->pattern));
-               size = off + src.raw->length * sizeof(*src.raw->pattern);
+               if (type == ITEM_SPEC ||
+                   (type == ITEM_MASK &&
+                    ((spec.raw->length & mask.raw->length) >=
+                     (last.raw->length & mask.raw->length))))
+                       size = spec.raw->length & mask.raw->length;
+               else
+                       size = last.raw->length & mask.raw->length;
+               size = off + size * sizeof(*src.raw->pattern);
                if (dst.raw) {
                        memcpy(dst.raw, src.raw, sizeof(*src.raw));
                        dst.raw->pattern = memcpy((uint8_t *)dst.raw + off,
@@ -333,7 +352,7 @@ flow_item_spec_copy(void *buf, const struct rte_flow_item *item,
        default:
                size = rte_flow_desc_item[item->type].size;
                if (buf)
-                       memcpy(buf, item_spec, size);
+                       memcpy(buf, data, size);
                break;
        }
 empty: