xsk: validate launch-time metadata size

Launch-time metadata extends beyond the first 16 bytes of struct
xsk_tx_metadata. Reject the request when the registered metadata area does
not contain the complete field.

Snapshot the validated flags for the generic transmit path and use that
snapshot for request and completion processing, avoiding inconsistent
decisions if user space changes the flags concurrently.

Note that only xsk_skb_metadata is properly using the flags,
__xsk_buff_get_metadata ignores them. Next commits address that.

Fixes: ca4419f15a ("xsk: Add launch time hardware offload support to XDP Tx metadata")
Cc: Cen Zhang (Microsoft) <blbllhy@gmail.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260727161959.885642-5-sdf@fomichev.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Stanislav Fomichev
2026-07-27 09:19:57 -07:00
committed by Jakub Kicinski
parent 9f60a67df8
commit 439ce2dddf
2 changed files with 19 additions and 9 deletions

View File

@@ -260,21 +260,28 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
0)
static inline bool
xsk_buff_valid_tx_metadata(const struct xsk_tx_metadata *meta)
xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
const struct xsk_tx_metadata *meta, u64 *flags)
{
return !(meta->flags & ~XDP_TXMD_FLAGS_VALID);
*flags = READ_ONCE(meta->flags);
if (*flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
if (pool->tx_metadata_len <
offsetofend(struct xsk_tx_metadata, request.launch_time))
return false;
return !(*flags & ~XDP_TXMD_FLAGS_VALID);
}
static inline struct xsk_tx_metadata *
__xsk_buff_get_metadata(const struct xsk_buff_pool *pool, void *data)
{
struct xsk_tx_metadata *meta;
u64 flags;
if (!pool->tx_metadata_len)
return NULL;
meta = data - pool->tx_metadata_len;
if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
return NULL; /* no way to signal the error to the user */
return meta;
@@ -469,7 +476,9 @@ xsk_buff_raw_get_ctx(const struct xsk_buff_pool *pool, u64 addr)
return (struct xdp_desc_ctx){ };
}
static inline bool xsk_buff_valid_tx_metadata(struct xsk_tx_metadata *meta)
static inline bool
xsk_buff_valid_tx_metadata(const struct xsk_buff_pool *pool,
const struct xsk_tx_metadata *meta, u64 *flags)
{
return false;
}

View File

@@ -967,15 +967,16 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
{
struct xsk_tx_metadata *meta = NULL;
u16 csum_start, csum_offset;
u64 flags;
if (unlikely(pool->tx_metadata_len == 0))
return -EINVAL;
meta = buffer - pool->tx_metadata_len;
if (unlikely(!xsk_buff_valid_tx_metadata(meta)))
if (unlikely(!xsk_buff_valid_tx_metadata(pool, meta, &flags)))
return -EINVAL;
if (meta->flags & XDP_TXMD_FLAGS_CHECKSUM) {
if (flags & XDP_TXMD_FLAGS_CHECKSUM) {
csum_start = READ_ONCE(meta->request.csum_start);
csum_offset = READ_ONCE(meta->request.csum_offset);
@@ -996,9 +997,9 @@ static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
}
}
if (meta->flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
skb->skb_mstamp_ns = meta->request.launch_time;
if (!(meta->flags & XDP_TXMD_FLAGS_TIMESTAMP))
if (flags & XDP_TXMD_FLAGS_LAUNCH_TIME)
skb->skb_mstamp_ns = READ_ONCE(meta->request.launch_time);
if (!(flags & XDP_TXMD_FLAGS_TIMESTAMP))
meta = NULL;
xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta);