On Tue, Feb 06, 2024 at 12:11:12PM +0100, Florian Westphal wrote: > Michal Kubecek <mkubecek@xxxxxxx> wrote: > > I stumbled upon this when the issue got a CVE id (sigh) and I share > > Andrea's (Cc-ed) concern that the fix is incomplete. While the fix, > > commit c301f0981fdd ("netfilter: nf_tables: fix pointer math issue in > > nft_byteorder_eval()") now, fixes the destination side, src is still > > a pointer to u32, i.e. we are reading 64-bit values with relative > > offsets which are multiples of 32 bits. > > > > Shouldn't we fix this as well, e.g. like indicated below? > > No, please remove multi-elem support instead, nothing uses this feature. See attached patch. I posted this: https://patchwork.ozlabs.org/project/netfilter-devel/patch/20240202120602.5122-1-pablo@xxxxxxxxxxxxx/ I can replace it by the attached patch if you prefer. This can only help in the future to microoptimize some set configurations, where several byteorder can be coalesced into one single expression.
diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c index 8cf91e47fd7a..af3412602869 100644 --- a/net/netfilter/nft_byteorder.c +++ b/net/netfilter/nft_byteorder.c @@ -43,18 +43,14 @@ void nft_byteorder_eval(const struct nft_expr *expr, switch (priv->op) { case NFT_BYTEORDER_NTOH: - for (i = 0; i < priv->len / 8; i++) { - src64 = nft_reg_load64(&src[i]); - nft_reg_store64(&dst64[i], - be64_to_cpu((__force __be64)src64)); - } + src64 = nft_reg_load64(&src[i]); + nft_reg_store64(&dst64[i], + be64_to_cpu((__force __be64)src64)); break; case NFT_BYTEORDER_HTON: - for (i = 0; i < priv->len / 8; i++) { - src64 = (__force __u64) - cpu_to_be64(nft_reg_load64(&src[i])); - nft_reg_store64(&dst64[i], src64); - } + src64 = (__force __u64) + cpu_to_be64(nft_reg_load64(&src[i])); + nft_reg_store64(&dst64[i], src64); break; } break; @@ -62,24 +58,20 @@ void nft_byteorder_eval(const struct nft_expr *expr, case 4: switch (priv->op) { case NFT_BYTEORDER_NTOH: - for (i = 0; i < priv->len / 4; i++) - dst[i] = ntohl((__force __be32)src[i]); + dst[i] = ntohl((__force __be32)src[i]); break; case NFT_BYTEORDER_HTON: - for (i = 0; i < priv->len / 4; i++) - dst[i] = (__force __u32)htonl(src[i]); + dst[i] = (__force __u32)htonl(src[i]); break; } break; case 2: switch (priv->op) { case NFT_BYTEORDER_NTOH: - for (i = 0; i < priv->len / 2; i++) - d16[i] = ntohs((__force __be16)s16[i]); + d16[i] = ntohs((__force __be16)s16[i]); break; case NFT_BYTEORDER_HTON: - for (i = 0; i < priv->len / 2; i++) - d16[i] = (__force __u16)htons(s16[i]); + d16[i] = (__force __u16)htons(s16[i]); break; } break; @@ -137,6 +129,9 @@ static int nft_byteorder_init(const struct nft_ctx *ctx, if (err < 0) return err; + if (priv->size != len) + return -EINVAL; + priv->len = len; if (len % size != 0)