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