rte_flow_item_flex_conv() is dispatched from rte_flow_conv_copy() to
deep-copy the variable-length pattern that follows a flex item header.
The function took no size argument at all, so the trailing rte_memcpy()
of `src->length` bytes was gated only on `buf != NULL`, violating the
documented contract that output is truncated to the caller-supplied
buffer size. A caller passing a buffer just large enough for the header
struct had adjacent memory clobbered by up to 4 GiB of pattern data,
since `src->length` is uint32_t and unbounded.

Propagate the remaining buffer size `size - sz` from
rte_flow_conv_copy() into the desc_fn callback and gate the inner
memcpy on it.

Fixes: dc4d860e8a89 ("ethdev: introduce configurable flexible item")
Cc: [email protected]

Signed-off-by: James Raphael Tiovalen <[email protected]>
---
 lib/ethdev/rte_flow.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 63b686ddfb..2744cfab2f 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -36,7 +36,7 @@ uint64_t rte_flow_dynf_metadata_mask;
 struct rte_flow_desc_data {
        const char *name;
        size_t size;
-       size_t (*desc_fn)(void *dst, const void *src);
+       size_t (*desc_fn)(void *dst, const void *src, size_t size);
 };
 
 /**
@@ -68,16 +68,17 @@ rte_flow_conv_copy(void *buf, const void *data, const 
size_t size,
        if (buf != NULL)
                rte_memcpy(buf, data, (size > sz ? sz : size));
        if (rte_type && desc[type].desc_fn)
-               sz += desc[type].desc_fn(size > 0 ? buf : NULL, data);
+               sz += desc[type].desc_fn(size > 0 ? buf : NULL, data,
+                                        size > sz ? size - sz : 0);
        return sz;
 }
 
 static size_t
-rte_flow_item_flex_conv(void *buf, const void *data)
+rte_flow_item_flex_conv(void *buf, const void *data, size_t size)
 {
        struct rte_flow_item_flex *dst = buf;
        const struct rte_flow_item_flex *src = data;
-       if (buf) {
+       if (buf && size >= src->length) {
                dst->pattern = rte_memcpy
                        ((void *)((uintptr_t)(dst + 1)), src->pattern,
                         src->length);
-- 
2.43.0

Reply via email to