mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
Merge tag 'nf-26-07-03' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Florian Westphal says: ==================== netfilter: updates for net The following patchset contains Netfilter fixes for *net*, all for ancient problems. Patch 7 raised drive-by sashiko findings, but those are not related to the change itself. 1) Rebuild the nf_nat_sip data pointer to prevent stale access after SKB reallocation. Restrict UDP mangling to UDP streams to avoid TCP packet corruption. 2) Prevent undefined behavior in xt_u32 caused by invalid shift counts. From Wyatt Feng. 3) Use u64 variables to prevent incorrect comparisons on links exceeding 34 Gbps in xt_rateest. From Feng Wu. 4) Cap the number of expectations per master during nfnetlink_cthelper updates. From Pablo Neira Ayuso. 5) Mark malformed IPv6 extension headers for hotdrop in ip6tables. From Zhixing Chen. 6) Skip the end element of an open interval during the get command when its closest match is the interval's start element. Also from Pablo Neira Ayuso. 7) Fix PMTU calculation for GUE/GRE tunnels in IPVS during ICMP fragmentation error handling. Include additional tunnel header length when computing the new MTU. From Yizhou Zhao. 8) Reset full ip_vs_seq structures in ip_vs_conn_new. Also from Yizhou Zhao. 9) Reject invalid shift parameters in xt_connmark. Also from Wyatt Feng. netfilter pull request nf-26-07-03 * tag 'nf-26-07-03' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: xt_connmark: reject invalid shift parameters ipvs: reset full ip_vs_seq structs in ip_vs_conn_new ipvs: fix PMTU for GUE/GRE tunnel ICMP errors netfilter: nft_set_rbtree: get command skips end element with open interval netfilter: ip6tables: mark malformed IPv6 extension headers for hotdrop netfilter: nfnetlink_cthelper: cap to maximum number of expectation per master on updates netfilter: xt_rateest: fix u64 truncation in xt_rateest_mt() netfilter: xt_u32: reject invalid shift counts netfilter: nf_nat_sip: reload possible stale data pointer ==================== Link: https://patch.msgid.link/20260703125709.16493-1-fw@strlen.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -56,6 +56,11 @@ static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
}
|
||||
|
||||
hdrlen = ipv6_authlen(ah);
|
||||
if (skb->len - ptr < hdrlen) {
|
||||
/* Packet smaller than its length field */
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
|
||||
pr_debug("RES %04X ", ah->reserved);
|
||||
|
||||
@@ -75,6 +75,7 @@ hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
hdrlen = ipv6_optlen(oh);
|
||||
if (skb->len - ptr < hdrlen) {
|
||||
/* Packet smaller than it's length field */
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
|
||||
hdrlen = ipv6_optlen(rh);
|
||||
if (skb->len - ptr < hdrlen) {
|
||||
/* Pcket smaller than its length field */
|
||||
/* Packet smaller than its length field */
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1420,8 +1420,8 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
|
||||
cp->app = NULL;
|
||||
cp->app_data = NULL;
|
||||
/* reset struct ip_vs_seq */
|
||||
cp->in_seq.delta = 0;
|
||||
cp->out_seq.delta = 0;
|
||||
memset(&cp->in_seq, 0, sizeof(cp->in_seq));
|
||||
memset(&cp->out_seq, 0, sizeof(cp->out_seq));
|
||||
|
||||
if (unlikely(flags & IP_VS_CONN_F_NO_CPORT)) {
|
||||
int af_id = ip_vs_af_index(cp->af);
|
||||
|
||||
@@ -1767,6 +1767,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
|
||||
bool tunnel, new_cp = false;
|
||||
union nf_inet_addr *raddr;
|
||||
char *outer_proto = "IPIP";
|
||||
int ulen = 0;
|
||||
|
||||
*related = 1;
|
||||
|
||||
@@ -1831,7 +1832,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
|
||||
/* Error for our tunnel must arrive at LOCAL_IN */
|
||||
(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) {
|
||||
__u8 iproto;
|
||||
int ulen;
|
||||
|
||||
/* Non-first fragment has no UDP/GRE header */
|
||||
if (unlikely(cih->frag_off & htons(IP_OFFSET)))
|
||||
@@ -1936,8 +1936,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
|
||||
if (dest_dst)
|
||||
mtu = dst_mtu(dest_dst->dst_cache);
|
||||
}
|
||||
if (mtu > 68 + sizeof(struct iphdr))
|
||||
mtu -= sizeof(struct iphdr);
|
||||
if (mtu > 68 + sizeof(struct iphdr) + ulen)
|
||||
mtu -= sizeof(struct iphdr) + ulen;
|
||||
info = htonl(mtu);
|
||||
}
|
||||
/* Strip outer IP, ICMP and IPIP/UDP/GRE, go to IP header of
|
||||
|
||||
@@ -289,13 +289,24 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
|
||||
|
||||
/* Mangle destination port for Cisco phones, then fix up checksums */
|
||||
if (dir == IP_CT_DIR_REPLY && ct_sip_info->forced_dport) {
|
||||
int doff = *dptr - (const char *)skb->data;
|
||||
struct udphdr *uh;
|
||||
|
||||
if (doff <= 0) {
|
||||
DEBUG_NET_WARN_ON_ONCE(1);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
/* ct_sip_info->forced_dport only expected with UDP */
|
||||
if (nf_ct_protonum(ct) != IPPROTO_UDP)
|
||||
return NF_DROP;
|
||||
|
||||
if (skb_ensure_writable(skb, skb->len)) {
|
||||
nf_ct_helper_log(skb, ct, "cannot mangle packet");
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
*dptr = skb->data + doff;
|
||||
uh = (void *)skb->data + protoff;
|
||||
uh->dest = ct_sip_info->forced_dport;
|
||||
|
||||
|
||||
@@ -6563,6 +6563,9 @@ static int nft_get_set_elem(struct nft_ctx *ctx, const struct nft_set *set,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!elem.priv)
|
||||
return 0;
|
||||
|
||||
err = -ENOMEM;
|
||||
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
|
||||
@@ -316,6 +316,8 @@ nfnl_cthelper_update_policy_one(const struct nf_conntrack_expect_policy *policy,
|
||||
|
||||
new_policy->max_expected =
|
||||
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
|
||||
if (!new_policy->max_expected)
|
||||
new_policy->max_expected = NF_CT_EXPECT_MAX_CNT;
|
||||
if (new_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -184,10 +184,14 @@ nft_rbtree_get(const struct net *net, const struct nft_set *set,
|
||||
if (!interval || nft_set_elem_expired(interval->from))
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (flags & NFT_SET_ELEM_INTERVAL_END)
|
||||
if (flags & NFT_SET_ELEM_INTERVAL_END) {
|
||||
if (!interval->to)
|
||||
return NULL;
|
||||
|
||||
rbe = container_of(interval->to, struct nft_rbtree_elem, ext);
|
||||
else
|
||||
} else {
|
||||
rbe = container_of(interval->from, struct nft_rbtree_elem, ext);
|
||||
}
|
||||
|
||||
return &rbe->priv;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,16 @@ static int connmark_tg_check(const struct xt_tgchk_param *par)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int connmark_tg_check_v2(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct xt_connmark_tginfo2 *info = par->targinfo;
|
||||
|
||||
if (info->shift_dir > D_SHIFT_RIGHT || info->shift_bits >= 32)
|
||||
return -EINVAL;
|
||||
|
||||
return connmark_tg_check(par);
|
||||
}
|
||||
|
||||
static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
nf_ct_netns_put(par->net, par->family);
|
||||
@@ -162,7 +172,7 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
|
||||
.name = "CONNMARK",
|
||||
.revision = 2,
|
||||
.family = NFPROTO_IPV4,
|
||||
.checkentry = connmark_tg_check,
|
||||
.checkentry = connmark_tg_check_v2,
|
||||
.target = connmark_tg_v2,
|
||||
.targetsize = sizeof(struct xt_connmark_tginfo2),
|
||||
.destroy = connmark_tg_destroy,
|
||||
@@ -183,7 +193,7 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
|
||||
.name = "CONNMARK",
|
||||
.revision = 2,
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = connmark_tg_check,
|
||||
.checkentry = connmark_tg_check_v2,
|
||||
.target = connmark_tg_v2,
|
||||
.targetsize = sizeof(struct xt_connmark_tginfo2),
|
||||
.destroy = connmark_tg_destroy,
|
||||
|
||||
@@ -16,7 +16,7 @@ xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct xt_rateest_match_info *info = par->matchinfo;
|
||||
struct gnet_stats_rate_est64 sample = {0};
|
||||
u_int32_t bps1, bps2, pps1, pps2;
|
||||
u64 bps1, bps2, pps1, pps2;
|
||||
bool ret = true;
|
||||
|
||||
gen_estimator_read(&info->est1->rate_est, &sample);
|
||||
|
||||
@@ -100,7 +100,7 @@ static int u32_mt_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct xt_u32 *data = par->matchinfo;
|
||||
const struct xt_u32_test *ct;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
|
||||
if (data->ntests > ARRAY_SIZE(data->tests))
|
||||
return -EINVAL;
|
||||
@@ -111,6 +111,16 @@ static int u32_mt_checkentry(const struct xt_mtchk_param *par)
|
||||
if (ct->nnums > ARRAY_SIZE(ct->location) ||
|
||||
ct->nvalues > ARRAY_SIZE(ct->value))
|
||||
return -EINVAL;
|
||||
|
||||
for (j = 1; j < ct->nnums; ++j) {
|
||||
switch (ct->location[j].nextop) {
|
||||
case XT_U32_LEFTSH:
|
||||
case XT_U32_RIGHTSH:
|
||||
if (ct->location[j].number >= 32)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user