netfilter pull request 24-05-29
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEN9lkrMBJgcdVAPub1V2XiooUIOQFAmZWXboACgkQ1V2XiooU IOQW/BAAld3NcyYFzwhUmiAcig7jvYkIZwGE7wBVPz82G+gC4n8k+cIt50XlhTQt lctjKHI7y96hWqlAPbu96lRn/KFgFCCRF3sACpJ/rR5rLn+hLBgIiXKZohLoAkkA zoSfpHXQo8u8tGmdNJiweKNZbJWXj4Wmaj3SLqbf/0mMyIQUigZ+4EHDHWGP8JvQ 6ilcEndEy9IBD3M5jIE3ubPwbrXwBQjaGRgT+e7yLgNDP8FEg3IeWcPW5hMtPEW3 mizkxamzdNzhaBH2U33hKvoQv0q9QmtcBa8angvx9OCEDRa9c/RpfIYwj8SsdQW1 kdzSAMNpYho+lRmq708G02vYQya5+wfof9NlJHrRqPj4BwFpj53sGm11ksfrYkId WSJj4WAAcv4zNavS3jQD8SeGrA7bxyvyfO6JUSTEThyMYWvN0s8erGNZYa3Mk1AD PH3WqMp8WV6EtG4+jQymvLcJ6HrzncdNeBdmbvVhGa9xPGaDIQFs3c4WRRjRu9jd 0cPPITOtb0cOGbt/w9jK1ot7wcm00uwQ1xcFlJO88I7dkgqHxYEsQ8gUC+cJoqL6 s2oPVKMvYzJnyhkXumP1/w3hqkk9EJq5pZZiu47UHbtfT3HhQRBPNydwTvB3Mj30 X8rczN2sFFcDp1KkMQF6C8tQZSXIEEAf5XTUm+q69MmuiT0lrn8= =cexP -----END PGP SIGNATURE----- Merge tag 'nf-24-05-29' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: Patch #1 syzbot reports that nf_reinject() could be called without rcu_read_lock() when flushing pending packets at nfnetlink queue removal, from Eric Dumazet. Patch #2 flushes ipset list:set when canceling garbage collection to reference to other lists to fix a race, from Jozsef Kadlecsik. Patch #3 restores q-in-q matching with nft_payload by reverting f6ae9f120dad ("netfilter: nft_payload: add C-VLAN support"). Patch #4 fixes vlan mangling in skbuff when vlan offload is present in skbuff, without this patch nft_payload corrupts packets in this case. Patch #5 fixes possible nul-deref in tproxy no IP address is found in netdevice, reported by syzbot and patch from Florian Westphal. Patch #6 removes a superfluous restriction which prevents loose fib lookups from input and forward hooks, from Eric Garver. My assessment is that patches #1, #2 and #5 address possible kernel crash, anything else in this batch fixes broken features. netfilter pull request 24-05-29 * tag 'nf-24-05-29' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nft_fib: allow from forward/input without iif selector netfilter: tproxy: bail out if IP has been disabled on the device netfilter: nft_payload: skbuff vlan metadata mangle support netfilter: nft_payload: restore vlan q-in-q match support netfilter: ipset: Add list flush to cancel_gc netfilter: nfnetlink_queue: acquire rcu_read_lock() in instance_destroy_rcu() ==================== Link: https://lore.kernel.org/r/20240528225519.1155786-1-pablo@netfilter.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
e889eb17f4
@ -58,6 +58,8 @@ __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
|
||||
|
||||
laddr = 0;
|
||||
indev = __in_dev_get_rcu(skb->dev);
|
||||
if (!indev)
|
||||
return daddr;
|
||||
|
||||
in_dev_for_each_ifa_rcu(ifa, indev) {
|
||||
if (ifa->ifa_flags & IFA_F_SECONDARY)
|
||||
|
@ -549,6 +549,9 @@ list_set_cancel_gc(struct ip_set *set)
|
||||
|
||||
if (SET_WITH_TIMEOUT(set))
|
||||
timer_shutdown_sync(&map->gc);
|
||||
|
||||
/* Flush list to drop references to other ipsets */
|
||||
list_set_flush(set);
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant set_variant = {
|
||||
|
@ -169,7 +169,9 @@ instance_destroy_rcu(struct rcu_head *head)
|
||||
struct nfqnl_instance *inst = container_of(head, struct nfqnl_instance,
|
||||
rcu);
|
||||
|
||||
rcu_read_lock();
|
||||
nfqnl_flush(inst, NULL, 0);
|
||||
rcu_read_unlock();
|
||||
kfree(inst);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
@ -35,11 +35,9 @@ int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
switch (priv->result) {
|
||||
case NFT_FIB_RESULT_OIF:
|
||||
case NFT_FIB_RESULT_OIFNAME:
|
||||
hooks = (1 << NF_INET_PRE_ROUTING);
|
||||
if (priv->flags & NFTA_FIB_F_IIF) {
|
||||
hooks |= (1 << NF_INET_LOCAL_IN) |
|
||||
(1 << NF_INET_FORWARD);
|
||||
}
|
||||
hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_IN) |
|
||||
(1 << NF_INET_FORWARD);
|
||||
break;
|
||||
case NFT_FIB_RESULT_ADDRTYPE:
|
||||
if (priv->flags & NFTA_FIB_F_IIF)
|
||||
|
@ -45,36 +45,27 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
|
||||
int mac_off = skb_mac_header(skb) - skb->data;
|
||||
u8 *vlanh, *dst_u8 = (u8 *) d;
|
||||
struct vlan_ethhdr veth;
|
||||
u8 vlan_hlen = 0;
|
||||
|
||||
if ((skb->protocol == htons(ETH_P_8021AD) ||
|
||||
skb->protocol == htons(ETH_P_8021Q)) &&
|
||||
offset >= VLAN_ETH_HLEN && offset < VLAN_ETH_HLEN + VLAN_HLEN)
|
||||
vlan_hlen += VLAN_HLEN;
|
||||
|
||||
vlanh = (u8 *) &veth;
|
||||
if (offset < VLAN_ETH_HLEN + vlan_hlen) {
|
||||
if (offset < VLAN_ETH_HLEN) {
|
||||
u8 ethlen = len;
|
||||
|
||||
if (vlan_hlen &&
|
||||
skb_copy_bits(skb, mac_off, &veth, VLAN_ETH_HLEN) < 0)
|
||||
return false;
|
||||
else if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth))
|
||||
if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth))
|
||||
return false;
|
||||
|
||||
if (offset + len > VLAN_ETH_HLEN + vlan_hlen)
|
||||
ethlen -= offset + len - VLAN_ETH_HLEN - vlan_hlen;
|
||||
if (offset + len > VLAN_ETH_HLEN)
|
||||
ethlen -= offset + len - VLAN_ETH_HLEN;
|
||||
|
||||
memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen);
|
||||
memcpy(dst_u8, vlanh + offset, ethlen);
|
||||
|
||||
len -= ethlen;
|
||||
if (len == 0)
|
||||
return true;
|
||||
|
||||
dst_u8 += ethlen;
|
||||
offset = ETH_HLEN + vlan_hlen;
|
||||
offset = ETH_HLEN;
|
||||
} else {
|
||||
offset -= VLAN_HLEN + vlan_hlen;
|
||||
offset -= VLAN_HLEN;
|
||||
}
|
||||
|
||||
return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0;
|
||||
@ -154,12 +145,12 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt)
|
||||
return pkt->inneroff;
|
||||
}
|
||||
|
||||
static bool nft_payload_need_vlan_copy(const struct nft_payload *priv)
|
||||
static bool nft_payload_need_vlan_adjust(u32 offset, u32 len)
|
||||
{
|
||||
unsigned int len = priv->offset + priv->len;
|
||||
unsigned int boundary = offset + len;
|
||||
|
||||
/* data past ether src/dst requested, copy needed */
|
||||
if (len > offsetof(struct ethhdr, h_proto))
|
||||
if (boundary > offsetof(struct ethhdr, h_proto))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -183,7 +174,7 @@ void nft_payload_eval(const struct nft_expr *expr,
|
||||
goto err;
|
||||
|
||||
if (skb_vlan_tag_present(skb) &&
|
||||
nft_payload_need_vlan_copy(priv)) {
|
||||
nft_payload_need_vlan_adjust(priv->offset, priv->len)) {
|
||||
if (!nft_payload_copy_vlan(dest, skb,
|
||||
priv->offset, priv->len))
|
||||
goto err;
|
||||
@ -810,21 +801,79 @@ struct nft_payload_set {
|
||||
u8 csum_flags;
|
||||
};
|
||||
|
||||
/* This is not struct vlan_hdr. */
|
||||
struct nft_payload_vlan_hdr {
|
||||
__be16 h_vlan_proto;
|
||||
__be16 h_vlan_TCI;
|
||||
};
|
||||
|
||||
static bool
|
||||
nft_payload_set_vlan(const u32 *src, struct sk_buff *skb, u8 offset, u8 len,
|
||||
int *vlan_hlen)
|
||||
{
|
||||
struct nft_payload_vlan_hdr *vlanh;
|
||||
__be16 vlan_proto;
|
||||
u16 vlan_tci;
|
||||
|
||||
if (offset >= offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto)) {
|
||||
*vlan_hlen = VLAN_HLEN;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (offset) {
|
||||
case offsetof(struct vlan_ethhdr, h_vlan_proto):
|
||||
if (len == 2) {
|
||||
vlan_proto = nft_reg_load_be16(src);
|
||||
skb->vlan_proto = vlan_proto;
|
||||
} else if (len == 4) {
|
||||
vlanh = (struct nft_payload_vlan_hdr *)src;
|
||||
__vlan_hwaccel_put_tag(skb, vlanh->h_vlan_proto,
|
||||
ntohs(vlanh->h_vlan_TCI));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case offsetof(struct vlan_ethhdr, h_vlan_TCI):
|
||||
if (len != 2)
|
||||
return false;
|
||||
|
||||
vlan_tci = ntohs(nft_reg_load_be16(src));
|
||||
skb->vlan_tci = vlan_tci;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nft_payload_set_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
const struct nft_payload_set *priv = nft_expr_priv(expr);
|
||||
struct sk_buff *skb = pkt->skb;
|
||||
const u32 *src = ®s->data[priv->sreg];
|
||||
int offset, csum_offset;
|
||||
int offset, csum_offset, vlan_hlen = 0;
|
||||
struct sk_buff *skb = pkt->skb;
|
||||
__wsum fsum, tsum;
|
||||
|
||||
switch (priv->base) {
|
||||
case NFT_PAYLOAD_LL_HEADER:
|
||||
if (!skb_mac_header_was_set(skb))
|
||||
goto err;
|
||||
offset = skb_mac_header(skb) - skb->data;
|
||||
|
||||
if (skb_vlan_tag_present(skb) &&
|
||||
nft_payload_need_vlan_adjust(priv->offset, priv->len)) {
|
||||
if (!nft_payload_set_vlan(src, skb,
|
||||
priv->offset, priv->len,
|
||||
&vlan_hlen))
|
||||
goto err;
|
||||
|
||||
if (!vlan_hlen)
|
||||
return;
|
||||
}
|
||||
|
||||
offset = skb_mac_header(skb) - skb->data - vlan_hlen;
|
||||
break;
|
||||
case NFT_PAYLOAD_NETWORK_HEADER:
|
||||
offset = skb_network_offset(skb);
|
||||
|
Loading…
x
Reference in New Issue
Block a user