Skip to content

Commit 71e15f7

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for your net tree: 1) Fix crash when dumping rules after conversion to RCU, from Florian Westphal. 2) Fix incorrect hook reinjection from nf_queue in case NF_REPEAT, from Jagdish Motwani. 3) Fix check for route existence in fib extension, from Phil Sutter. 4) Fix use after free in ip_vs_in() hook, from YueHaibing. 5) Check for veth existence from netfilter selftests, from Jeffrin Jose T. 6) Checksum corruption in UDP NAT helpers due to typo, from Florian Westphal. 7) Pass up packets to classic forwarding path regardless of IPv4 DF bit, patch for the flowtable infrastructure from Florian. 8) Set liberal TCP tracking for flows that are placed in the flowtable, in case they need to go back to classic forwarding path, also from Florian. 9) Don't add flow with sequence adjustment to flowtable, from Florian. 10) Skip IPv4 options from IPv6 datapath in flowtable, from Florian. 11) Add selftest for the flowtable infrastructure, from Florian. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents b573006 + 2de03b4 commit 71e15f7

File tree

13 files changed

+375
-63
lines changed

13 files changed

+375
-63
lines changed

include/net/netfilter/nft_fib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
3434
const struct nft_pktinfo *pkt);
3535

3636
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
37-
const struct nft_pktinfo *pkt, int index);
37+
const struct net_device *dev);
3838
#endif

net/ipv4/netfilter/nft_fib_ipv4.c

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,6 @@ void nft_fib4_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
5858
}
5959
EXPORT_SYMBOL_GPL(nft_fib4_eval_type);
6060

61-
static int get_ifindex(const struct net_device *dev)
62-
{
63-
return dev ? dev->ifindex : 0;
64-
}
65-
6661
void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
6762
const struct nft_pktinfo *pkt)
6863
{
@@ -94,8 +89,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
9489

9590
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
9691
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
97-
nft_fib_store_result(dest, priv, pkt,
98-
nft_in(pkt)->ifindex);
92+
nft_fib_store_result(dest, priv, nft_in(pkt));
9993
return;
10094
}
10195

@@ -108,8 +102,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
108102
if (ipv4_is_zeronet(iph->saddr)) {
109103
if (ipv4_is_lbcast(iph->daddr) ||
110104
ipv4_is_local_multicast(iph->daddr)) {
111-
nft_fib_store_result(dest, priv, pkt,
112-
get_ifindex(pkt->skb->dev));
105+
nft_fib_store_result(dest, priv, pkt->skb->dev);
113106
return;
114107
}
115108
}
@@ -150,17 +143,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
150143
found = oif;
151144
}
152145

153-
switch (priv->result) {
154-
case NFT_FIB_RESULT_OIF:
155-
*dest = found->ifindex;
156-
break;
157-
case NFT_FIB_RESULT_OIFNAME:
158-
strncpy((char *)dest, found->name, IFNAMSIZ);
159-
break;
160-
default:
161-
WARN_ON_ONCE(1);
162-
break;
163-
}
146+
nft_fib_store_result(dest, priv, found);
164147
}
165148
EXPORT_SYMBOL_GPL(nft_fib4_eval);
166149

net/ipv6/netfilter/nft_fib_ipv6.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
169169

170170
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
171171
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
172-
nft_fib_store_result(dest, priv, pkt,
173-
nft_in(pkt)->ifindex);
172+
nft_fib_store_result(dest, priv, nft_in(pkt));
174173
return;
175174
}
176175

@@ -187,18 +186,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
187186
if (oif && oif != rt->rt6i_idev->dev)
188187
goto put_rt_err;
189188

190-
switch (priv->result) {
191-
case NFT_FIB_RESULT_OIF:
192-
*dest = rt->rt6i_idev->dev->ifindex;
193-
break;
194-
case NFT_FIB_RESULT_OIFNAME:
195-
strncpy((char *)dest, rt->rt6i_idev->dev->name, IFNAMSIZ);
196-
break;
197-
default:
198-
WARN_ON_ONCE(1);
199-
break;
200-
}
201-
189+
nft_fib_store_result(dest, priv, rt->rt6i_idev->dev);
202190
put_rt_err:
203191
ip6_rt_put(rt);
204192
}

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2312,7 +2312,6 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
23122312
{
23132313
struct netns_ipvs *ipvs = net_ipvs(net);
23142314

2315-
nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
23162315
ip_vs_service_net_cleanup(ipvs); /* ip_vs_flush() with locks */
23172316
ip_vs_conn_net_cleanup(ipvs);
23182317
ip_vs_app_net_cleanup(ipvs);
@@ -2327,6 +2326,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
23272326
{
23282327
struct netns_ipvs *ipvs = net_ipvs(net);
23292328
EnterFunction(2);
2329+
nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
23302330
ipvs->enable = 0; /* Disable packet reception */
23312331
smp_wmb();
23322332
ip_vs_sync_net_cleanup(ipvs);

net/netfilter/nf_flow_table_ip.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
244244
rt = (struct rtable *)flow->tuplehash[dir].tuple.dst_cache;
245245
outdev = rt->dst.dev;
246246

247-
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)) &&
248-
(ip_hdr(skb)->frag_off & htons(IP_DF)) != 0)
247+
if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu)))
249248
return NF_ACCEPT;
250249

251250
if (skb_try_make_writable(skb, sizeof(*iph)))

net/netfilter/nf_nat_helper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb,
170170
if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
171171
return true;
172172

173-
nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_TCP,
173+
nf_nat_csum_recalc(skb, nf_ct_l3num(ct), IPPROTO_UDP,
174174
udph, &udph->check, datalen, oldlen);
175175

176176
return true;

net/netfilter/nf_queue.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static unsigned int nf_iterate(struct sk_buff *skb,
255255
repeat:
256256
verdict = nf_hook_entry_hookfn(hook, skb, state);
257257
if (verdict != NF_ACCEPT) {
258+
*index = i;
258259
if (verdict != NF_REPEAT)
259260
return verdict;
260261
goto repeat;

net/netfilter/nf_tables_api.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,13 +2270,13 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
22702270
u32 flags, int family,
22712271
const struct nft_table *table,
22722272
const struct nft_chain *chain,
2273-
const struct nft_rule *rule)
2273+
const struct nft_rule *rule,
2274+
const struct nft_rule *prule)
22742275
{
22752276
struct nlmsghdr *nlh;
22762277
struct nfgenmsg *nfmsg;
22772278
const struct nft_expr *expr, *next;
22782279
struct nlattr *list;
2279-
const struct nft_rule *prule;
22802280
u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
22812281

22822282
nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags);
@@ -2296,8 +2296,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
22962296
NFTA_RULE_PAD))
22972297
goto nla_put_failure;
22982298

2299-
if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
2300-
prule = list_prev_entry(rule, list);
2299+
if (event != NFT_MSG_DELRULE && prule) {
23012300
if (nla_put_be64(skb, NFTA_RULE_POSITION,
23022301
cpu_to_be64(prule->handle),
23032302
NFTA_RULE_PAD))
@@ -2344,7 +2343,7 @@ static void nf_tables_rule_notify(const struct nft_ctx *ctx,
23442343

23452344
err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
23462345
event, 0, ctx->family, ctx->table,
2347-
ctx->chain, rule);
2346+
ctx->chain, rule, NULL);
23482347
if (err < 0) {
23492348
kfree_skb(skb);
23502349
goto err;
@@ -2369,12 +2368,13 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
23692368
const struct nft_chain *chain)
23702369
{
23712370
struct net *net = sock_net(skb->sk);
2371+
const struct nft_rule *rule, *prule;
23722372
unsigned int s_idx = cb->args[0];
2373-
const struct nft_rule *rule;
23742373

2374+
prule = NULL;
23752375
list_for_each_entry_rcu(rule, &chain->rules, list) {
23762376
if (!nft_is_active(net, rule))
2377-
goto cont;
2377+
goto cont_skip;
23782378
if (*idx < s_idx)
23792379
goto cont;
23802380
if (*idx > s_idx) {
@@ -2386,11 +2386,13 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
23862386
NFT_MSG_NEWRULE,
23872387
NLM_F_MULTI | NLM_F_APPEND,
23882388
table->family,
2389-
table, chain, rule) < 0)
2389+
table, chain, rule, prule) < 0)
23902390
return 1;
23912391

23922392
nl_dump_check_consistent(cb, nlmsg_hdr(skb));
23932393
cont:
2394+
prule = rule;
2395+
cont_skip:
23942396
(*idx)++;
23952397
}
23962398
return 0;
@@ -2546,7 +2548,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
25462548

25472549
err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
25482550
nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
2549-
family, table, chain, rule);
2551+
family, table, chain, rule, NULL);
25502552
if (err < 0)
25512553
goto err;
25522554

net/netfilter/nft_fib.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,17 @@ int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
135135
EXPORT_SYMBOL_GPL(nft_fib_dump);
136136

137137
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
138-
const struct nft_pktinfo *pkt, int index)
138+
const struct net_device *dev)
139139
{
140-
struct net_device *dev;
141140
u32 *dreg = reg;
141+
int index;
142142

143143
switch (priv->result) {
144144
case NFT_FIB_RESULT_OIF:
145+
index = dev ? dev->ifindex : 0;
145146
*dreg = (priv->flags & NFTA_FIB_F_PRESENT) ? !!index : index;
146147
break;
147148
case NFT_FIB_RESULT_OIFNAME:
148-
dev = dev_get_by_index_rcu(nft_net(pkt), index);
149149
if (priv->flags & NFTA_FIB_F_PRESENT)
150150
*dreg = !!dev;
151151
else

net/netfilter/nft_flow_offload.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <net/netfilter/nf_conntrack_core.h>
1414
#include <linux/netfilter/nf_conntrack_common.h>
1515
#include <net/netfilter/nf_flow_table.h>
16-
#include <net/netfilter/nf_conntrack_helper.h>
1716

1817
struct nft_flow_offload {
1918
struct nft_flowtable *flowtable;
@@ -50,15 +49,20 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
5049
return 0;
5150
}
5251

53-
static bool nft_flow_offload_skip(struct sk_buff *skb)
52+
static bool nft_flow_offload_skip(struct sk_buff *skb, int family)
5453
{
55-
struct ip_options *opt = &(IPCB(skb)->opt);
56-
57-
if (unlikely(opt->optlen))
58-
return true;
5954
if (skb_sec_path(skb))
6055
return true;
6156

57+
if (family == NFPROTO_IPV4) {
58+
const struct ip_options *opt;
59+
60+
opt = &(IPCB(skb)->opt);
61+
62+
if (unlikely(opt->optlen))
63+
return true;
64+
}
65+
6266
return false;
6367
}
6468

@@ -68,15 +72,15 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
6872
{
6973
struct nft_flow_offload *priv = nft_expr_priv(expr);
7074
struct nf_flowtable *flowtable = &priv->flowtable->data;
71-
const struct nf_conn_help *help;
7275
enum ip_conntrack_info ctinfo;
7376
struct nf_flow_route route;
7477
struct flow_offload *flow;
7578
enum ip_conntrack_dir dir;
79+
bool is_tcp = false;
7680
struct nf_conn *ct;
7781
int ret;
7882

79-
if (nft_flow_offload_skip(pkt->skb))
83+
if (nft_flow_offload_skip(pkt->skb, nft_pf(pkt)))
8084
goto out;
8185

8286
ct = nf_ct_get(pkt->skb, &ctinfo);
@@ -85,14 +89,16 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
8589

8690
switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) {
8791
case IPPROTO_TCP:
92+
is_tcp = true;
93+
break;
8894
case IPPROTO_UDP:
8995
break;
9096
default:
9197
goto out;
9298
}
9399

94-
help = nfct_help(ct);
95-
if (help)
100+
if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
101+
ct->status & IPS_SEQ_ADJUST)
96102
goto out;
97103

98104
if (!nf_ct_is_confirmed(ct))
@@ -109,6 +115,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
109115
if (!flow)
110116
goto err_flow_alloc;
111117

118+
if (is_tcp) {
119+
ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
120+
ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
121+
}
122+
112123
ret = flow_offload_add(flowtable, flow);
113124
if (ret < 0)
114125
goto err_flow_add;

tools/testing/selftests/netfilter/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
# Makefile for netfilter selftests
33

44
TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
5-
conntrack_icmp_related.sh
5+
conntrack_icmp_related.sh nft_flowtable.sh
66

77
include ../lib.mk

0 commit comments

Comments
 (0)