mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 06:33:34 +00:00
netfilter: nft_payload: mangle ckecksum if NFT_PAYLOAD_L4CSUM_PSEUDOHDR is set
If the NFT_PAYLOAD_L4CSUM_PSEUDOHDR flag is set, then mangle layer 4
checksum. This should not depend on csum_type NFT_PAYLOAD_CSUM_INET
since IPv6 header has no checksum field, but still an update of any of
the pseudoheader fields may trigger a layer 4 checksum update.
Fixes: 1814096980
("netfilter: nft_payload: layer 4 checksum adjustment for pseudoheader fields")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
3e38df136e
commit
053d20f571
@ -250,6 +250,22 @@ static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src,
|
||||
__wsum fsum, __wsum tsum, int csum_offset)
|
||||
{
|
||||
__sum16 sum;
|
||||
|
||||
if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
|
||||
return -1;
|
||||
|
||||
nft_csum_replace(&sum, fsum, tsum);
|
||||
if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
|
||||
skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_payload_set_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
@ -259,7 +275,6 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
|
||||
const u32 *src = ®s->data[priv->sreg];
|
||||
int offset, csum_offset;
|
||||
__wsum fsum, tsum;
|
||||
__sum16 sum;
|
||||
|
||||
switch (priv->base) {
|
||||
case NFT_PAYLOAD_LL_HEADER:
|
||||
@ -282,18 +297,14 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
|
||||
csum_offset = offset + priv->csum_offset;
|
||||
offset += priv->offset;
|
||||
|
||||
if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
|
||||
if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) &&
|
||||
(priv->base != NFT_PAYLOAD_TRANSPORT_HEADER ||
|
||||
skb->ip_summed != CHECKSUM_PARTIAL)) {
|
||||
if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
|
||||
goto err;
|
||||
|
||||
fsum = skb_checksum(skb, offset, priv->len, 0);
|
||||
tsum = csum_partial(src, priv->len, 0);
|
||||
nft_csum_replace(&sum, fsum, tsum);
|
||||
|
||||
if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
|
||||
skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
|
||||
if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
|
||||
nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset))
|
||||
goto err;
|
||||
|
||||
if (priv->csum_flags &&
|
||||
|
Loading…
Reference in New Issue
Block a user