Skip to content

Commit 284f1f1

Browse files
committed
Florian Westphal says: ==================== netfilter: updates for net The following patchset contains Netfilter fixes for *net*: 1) Add missing __rcu annotations to NAT helper hook pointers in Amanda, FTP, IRC, SNMP and TFTP helpers. From Sun Jian. 2-4): - Add global spinlock to serialize nft_counter fetch+reset operations. - Use atomic64_xchg() for nft_quota reset instead of read+subtract pattern. Note AI review detects a race in this change but it isn't new. The 'racing' bit only exists to prevent constant stream of 'quota expired' notifications. - Revert commit_mutex usage in nf_tables reset path, it caused circular lock dependency. All from Brian Witte. 5) Fix uninitialized l3num value in nf_conntrack_h323 helper. 6) Fix musl libc compatibility in netfilter_bridge.h UAPI header. This change isn't nice (UAPI headers should not include libc headers), but as-is musl builds may fail due to redefinition of struct ethhdr. 7) Fix protocol checksum validation in IPVS for IPv6 with extension headers, from Julian Anastasov. 8) Fix device reference leak in IPVS when netdev goes down. Also from Julian. 9) Remove WARN_ON_ONCE when accessing forward path array, this can trigger with sufficiently long forward paths. From Pablo Neira Ayuso. 10) Fix use-after-free in nf_tables_addchain() error path, from Inseo An. * tag 'nf-26-02-17' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_tables: fix use-after-free in nf_tables_addchain() net: remove WARN_ON_ONCE when accessing forward path array ipvs: do not keep dest_dst if dev is going down ipvs: skip ipv6 extension headers for csum checks include: uapi: netfilter_bridge.h: Cover for musl libc netfilter: nf_conntrack_h323: don't pass uninitialised l3num value netfilter: nf_tables: revert commit_mutex usage in reset path netfilter: nft_quota: use atomic64_xchg for reset netfilter: nft_counter: serialize reset with spinlock netfilter: annotate NAT helper hook pointers with __rcu ==================== Link: https://patch.msgid.link/20260217163233.31455-1-fw@strlen.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 0da1dba + 71e99ee commit 284f1f1

20 files changed

Lines changed: 166 additions & 303 deletions

include/linux/netfilter/nf_conntrack_amanda.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <linux/skbuff.h>
88
#include <net/netfilter/nf_conntrack_expect.h>
99

10-
extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
10+
extern unsigned int (__rcu *nf_nat_amanda_hook)(struct sk_buff *skb,
1111
enum ip_conntrack_info ctinfo,
1212
unsigned int protoff,
1313
unsigned int matchoff,

include/linux/netfilter/nf_conntrack_ftp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct nf_ct_ftp_master {
2626

2727
/* For NAT to hook in when we find a packet which describes what other
2828
* connection we should expect. */
29-
extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
29+
extern unsigned int (__rcu *nf_nat_ftp_hook)(struct sk_buff *skb,
3030
enum ip_conntrack_info ctinfo,
3131
enum nf_ct_ftp_type type,
3232
unsigned int protoff,

include/linux/netfilter/nf_conntrack_irc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#define IRC_PORT 6667
1010

11-
extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
11+
extern unsigned int (__rcu *nf_nat_irc_hook)(struct sk_buff *skb,
1212
enum ip_conntrack_info ctinfo,
1313
unsigned int protoff,
1414
unsigned int matchoff,

include/linux/netfilter/nf_conntrack_snmp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <linux/netfilter.h>
66
#include <linux/skbuff.h>
77

8-
extern int (*nf_nat_snmp_hook)(struct sk_buff *skb,
8+
extern int (__rcu *nf_nat_snmp_hook)(struct sk_buff *skb,
99
unsigned int protoff,
1010
struct nf_conn *ct,
1111
enum ip_conntrack_info ctinfo);

include/linux/netfilter/nf_conntrack_tftp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct tftphdr {
1919
#define TFTP_OPCODE_ACK 4
2020
#define TFTP_OPCODE_ERROR 5
2121

22-
extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
22+
extern unsigned int (__rcu *nf_nat_tftp_hook)(struct sk_buff *skb,
2323
enum ip_conntrack_info ctinfo,
2424
struct nf_conntrack_expect *exp);
2525

include/uapi/linux/netfilter_bridge.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
/* bridge-specific defines for netfilter.
66
*/
77

8+
#ifndef __KERNEL__
9+
#include <netinet/if_ether.h> /* for __UAPI_DEF_ETHHDR if defined */
10+
#endif
11+
812
#include <linux/in.h>
913
#include <linux/netfilter.h>
1014
#include <linux/if_ether.h>

net/core/dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
744744
{
745745
int k = stack->num_paths++;
746746

747-
if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX))
747+
if (k >= NET_DEVICE_PATH_STACK_MAX)
748748
return NULL;
749749

750750
return &stack->path[k];

net/netfilter/ipvs/ip_vs_proto_sctp.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
#include <net/ip_vs.h>
1111

1212
static int
13-
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
13+
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
14+
unsigned int sctphoff);
1415

1516
static int
1617
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -108,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
108109
int ret;
109110

110111
/* Some checks before mangling */
111-
if (!sctp_csum_check(cp->af, skb, pp))
112+
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
112113
return 0;
113114

114115
/* Call application helper if needed */
@@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
156157
int ret;
157158

158159
/* Some checks before mangling */
159-
if (!sctp_csum_check(cp->af, skb, pp))
160+
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
160161
return 0;
161162

162163
/* Call application helper if needed */
@@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
185186
}
186187

187188
static int
188-
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
189+
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
190+
unsigned int sctphoff)
189191
{
190-
unsigned int sctphoff;
191192
struct sctphdr *sh;
192193
__le32 cmp, val;
193194

194-
#ifdef CONFIG_IP_VS_IPV6
195-
if (af == AF_INET6)
196-
sctphoff = sizeof(struct ipv6hdr);
197-
else
198-
#endif
199-
sctphoff = ip_hdrlen(skb);
200-
201195
sh = (struct sctphdr *)(skb->data + sctphoff);
202196
cmp = sh->checksum;
203197
val = sctp_compute_cksum(skb, sctphoff);

net/netfilter/ipvs/ip_vs_proto_tcp.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
#include <net/ip_vs.h>
2929

3030
static int
31-
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
31+
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
32+
unsigned int tcphoff);
3233

3334
static int
3435
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -165,7 +166,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
165166
int ret;
166167

167168
/* Some checks before mangling */
168-
if (!tcp_csum_check(cp->af, skb, pp))
169+
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
169170
return 0;
170171

171172
/* Call application helper if needed */
@@ -243,7 +244,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
243244
int ret;
244245

245246
/* Some checks before mangling */
246-
if (!tcp_csum_check(cp->af, skb, pp))
247+
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
247248
return 0;
248249

249250
/*
@@ -300,17 +301,9 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
300301

301302

302303
static int
303-
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
304+
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
305+
unsigned int tcphoff)
304306
{
305-
unsigned int tcphoff;
306-
307-
#ifdef CONFIG_IP_VS_IPV6
308-
if (af == AF_INET6)
309-
tcphoff = sizeof(struct ipv6hdr);
310-
else
311-
#endif
312-
tcphoff = ip_hdrlen(skb);
313-
314307
switch (skb->ip_summed) {
315308
case CHECKSUM_NONE:
316309
skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
@@ -321,7 +314,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
321314
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
322315
&ipv6_hdr(skb)->daddr,
323316
skb->len - tcphoff,
324-
ipv6_hdr(skb)->nexthdr,
317+
IPPROTO_TCP,
325318
skb->csum)) {
326319
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
327320
"Failed checksum for");

net/netfilter/ipvs/ip_vs_proto_udp.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include <net/ip6_checksum.h>
2525

2626
static int
27-
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
27+
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
28+
unsigned int udphoff);
2829

2930
static int
3031
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -154,7 +155,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
154155
int ret;
155156

156157
/* Some checks before mangling */
157-
if (!udp_csum_check(cp->af, skb, pp))
158+
if (!udp_csum_check(cp->af, skb, pp, udphoff))
158159
return 0;
159160

160161
/*
@@ -237,7 +238,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
237238
int ret;
238239

239240
/* Some checks before mangling */
240-
if (!udp_csum_check(cp->af, skb, pp))
241+
if (!udp_csum_check(cp->af, skb, pp, udphoff))
241242
return 0;
242243

243244
/*
@@ -296,17 +297,10 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
296297

297298

298299
static int
299-
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
300+
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
301+
unsigned int udphoff)
300302
{
301303
struct udphdr _udph, *uh;
302-
unsigned int udphoff;
303-
304-
#ifdef CONFIG_IP_VS_IPV6
305-
if (af == AF_INET6)
306-
udphoff = sizeof(struct ipv6hdr);
307-
else
308-
#endif
309-
udphoff = ip_hdrlen(skb);
310304

311305
uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
312306
if (uh == NULL)
@@ -324,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
324318
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
325319
&ipv6_hdr(skb)->daddr,
326320
skb->len - udphoff,
327-
ipv6_hdr(skb)->nexthdr,
321+
IPPROTO_UDP,
328322
skb->csum)) {
329323
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
330324
"Failed checksum for");

0 commit comments

Comments
 (0)