Skip to content

Commit 7da538c

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Wait for rcu grace period after releasing netns in ctnetlink, from Florian Westphal. 2) Incorrect command type in flowtable offload ndo invocation, from wenxu. 3) Incorrect callback type in flowtable offload flow tuple updates, also from wenxu. 4) Fix compile warning on flowtable offload infrastructure due to possible reference to uninitialized variable, from Nathan Chancellor. 5) Do not inline nf_ct_resolve_clash(), this is called from slow path / stress situations. From Florian Westphal. 6) Missing IPv6 flow selector description in flowtable offload. 7) Missing check for NETDEV_UNREGISTER in nf_tables offload infrastructure, from wenxu. 8) Update NAT selftest to use randomized netns names, from Florian Westphal. 9) Restore nfqueue bridge support, from Marco Oliverio. 10) Compilation warning in SCTP_CHUNKMAP_*() on xt_sctp header. From Phil Sutter. 11) Fix bogus lookup/get match for non-anonymous rbtree sets. 12) Missing netlink validation for NFT_SET_ELEM_INTERVAL_END elements. 13) Missing netlink validation for NFT_DATA_VALUE after nft_data_init(). 14) If rule specifies no actions, offload infrastructure returns EOPNOTSUPP. 15) Module refcount leak in object updates. 16) Missing sanitization for ARP traffic from br_netfilter, from Eric Dumazet. 17) Compilation breakage on big-endian due to incorrect memcpy() size in the flowtable offload infrastructure. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents f8fc57e + 7acd937 commit 7da538c

File tree

13 files changed

+288
-213
lines changed

13 files changed

+288
-213
lines changed

include/uapi/linux/netfilter/xt_sctp.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,19 @@ struct xt_sctp_info {
4141
#define SCTP_CHUNKMAP_SET(chunkmap, type) \
4242
do { \
4343
(chunkmap)[type / bytes(__u32)] |= \
44-
1 << (type % bytes(__u32)); \
44+
1u << (type % bytes(__u32)); \
4545
} while (0)
4646

4747
#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
4848
do { \
4949
(chunkmap)[type / bytes(__u32)] &= \
50-
~(1 << (type % bytes(__u32))); \
50+
~(1u << (type % bytes(__u32))); \
5151
} while (0)
5252

5353
#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
5454
({ \
5555
((chunkmap)[type / bytes (__u32)] & \
56-
(1 << (type % bytes (__u32)))) ? 1: 0; \
56+
(1u << (type % bytes (__u32)))) ? 1: 0; \
5757
})
5858

5959
#define SCTP_CHUNKMAP_RESET(chunkmap) \

net/bridge/br_netfilter_hooks.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,9 @@ static unsigned int br_nf_forward_arp(void *priv,
662662
nf_bridge_pull_encap_header(skb);
663663
}
664664

665+
if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
666+
return NF_DROP;
667+
665668
if (arp_hdr(skb)->ar_pln != 4) {
666669
if (is_vlan_arp(skb, state->net))
667670
nf_bridge_push_encap_header(skb);

net/netfilter/nf_conntrack_core.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,10 @@ static void nf_ct_acct_merge(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
895895
}
896896

897897
/* Resolve race on insertion if this protocol allows this. */
898-
static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
899-
enum ip_conntrack_info ctinfo,
900-
struct nf_conntrack_tuple_hash *h)
898+
static __cold noinline int
899+
nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
900+
enum ip_conntrack_info ctinfo,
901+
struct nf_conntrack_tuple_hash *h)
901902
{
902903
/* This is the conntrack entry already in hashes that won race. */
903904
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);

net/netfilter/nf_conntrack_netlink.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,9 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
36263626

36273627
list_for_each_entry(net, net_exit_list, exit_list)
36283628
ctnetlink_net_exit(net);
3629+
3630+
/* wait for other cpus until they are done with ctnl_notifiers */
3631+
synchronize_rcu();
36293632
}
36303633

36313634
static struct pernet_operations ctnetlink_net_ops = {

net/netfilter/nf_flow_table_offload.c

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct nf_flow_key {
2828
struct flow_dissector_key_basic basic;
2929
union {
3030
struct flow_dissector_key_ipv4_addrs ipv4;
31+
struct flow_dissector_key_ipv6_addrs ipv6;
3132
};
3233
struct flow_dissector_key_tcp tcp;
3334
struct flow_dissector_key_ports tp;
@@ -57,6 +58,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
5758
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_CONTROL, control);
5859
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_BASIC, basic);
5960
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4);
61+
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
6062
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
6163
NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
6264

@@ -69,9 +71,18 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
6971
key->ipv4.dst = tuple->dst_v4.s_addr;
7072
mask->ipv4.dst = 0xffffffff;
7173
break;
74+
case AF_INET6:
75+
key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
76+
key->basic.n_proto = htons(ETH_P_IPV6);
77+
key->ipv6.src = tuple->src_v6;
78+
memset(&mask->ipv6.src, 0xff, sizeof(mask->ipv6.src));
79+
key->ipv6.dst = tuple->dst_v6;
80+
memset(&mask->ipv6.dst, 0xff, sizeof(mask->ipv6.dst));
81+
break;
7282
default:
7383
return -EOPNOTSUPP;
7484
}
85+
match->dissector.used_keys |= BIT(key->control.addr_type);
7586
mask->basic.n_proto = 0xffff;
7687

7788
switch (tuple->l4proto) {
@@ -96,14 +107,13 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
96107

97108
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL) |
98109
BIT(FLOW_DISSECTOR_KEY_BASIC) |
99-
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
100110
BIT(FLOW_DISSECTOR_KEY_PORTS);
101111
return 0;
102112
}
103113

104114
static void flow_offload_mangle(struct flow_action_entry *entry,
105-
enum flow_action_mangle_base htype,
106-
u32 offset, u8 *value, u8 *mask)
115+
enum flow_action_mangle_base htype, u32 offset,
116+
const __be32 *value, const __be32 *mask)
107117
{
108118
entry->id = FLOW_ACTION_MANGLE;
109119
entry->mangle.htype = htype;
@@ -140,12 +150,12 @@ static int flow_offload_eth_src(struct net *net,
140150
memcpy(&val16, dev->dev_addr, 2);
141151
val = val16 << 16;
142152
flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
143-
(u8 *)&val, (u8 *)&mask);
153+
&val, &mask);
144154

145155
mask = ~0xffffffff;
146156
memcpy(&val, dev->dev_addr + 2, 4);
147157
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8,
148-
(u8 *)&val, (u8 *)&mask);
158+
&val, &mask);
149159
dev_put(dev);
150160

151161
return 0;
@@ -170,13 +180,13 @@ static int flow_offload_eth_dst(struct net *net,
170180
mask = ~0xffffffff;
171181
memcpy(&val, n->ha, 4);
172182
flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 0,
173-
(u8 *)&val, (u8 *)&mask);
183+
&val, &mask);
174184

175185
mask = ~0x0000ffff;
176186
memcpy(&val16, n->ha + 4, 2);
177187
val = val16;
178188
flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
179-
(u8 *)&val, (u8 *)&mask);
189+
&val, &mask);
180190
neigh_release(n);
181191

182192
return 0;
@@ -206,7 +216,7 @@ static void flow_offload_ipv4_snat(struct net *net,
206216
}
207217

208218
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
209-
(u8 *)&addr, (u8 *)&mask);
219+
&addr, &mask);
210220
}
211221

212222
static void flow_offload_ipv4_dnat(struct net *net,
@@ -233,21 +243,20 @@ static void flow_offload_ipv4_dnat(struct net *net,
233243
}
234244

235245
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
236-
(u8 *)&addr, (u8 *)&mask);
246+
&addr, &mask);
237247
}
238248

239249
static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
240250
unsigned int offset,
241-
u8 *addr, u8 *mask)
251+
const __be32 *addr, const __be32 *mask)
242252
{
243253
struct flow_action_entry *entry;
244254
int i;
245255

246256
for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32)) {
247257
entry = flow_action_entry_next(flow_rule);
248258
flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6,
249-
offset + i,
250-
&addr[i], mask);
259+
offset + i, &addr[i], mask);
251260
}
252261
}
253262

@@ -257,23 +266,23 @@ static void flow_offload_ipv6_snat(struct net *net,
257266
struct nf_flow_rule *flow_rule)
258267
{
259268
u32 mask = ~htonl(0xffffffff);
260-
const u8 *addr;
269+
const __be32 *addr;
261270
u32 offset;
262271

263272
switch (dir) {
264273
case FLOW_OFFLOAD_DIR_ORIGINAL:
265-
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr;
274+
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr32;
266275
offset = offsetof(struct ipv6hdr, saddr);
267276
break;
268277
case FLOW_OFFLOAD_DIR_REPLY:
269-
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr;
278+
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr32;
270279
offset = offsetof(struct ipv6hdr, daddr);
271280
break;
272281
default:
273282
return;
274283
}
275284

276-
flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask);
285+
flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
277286
}
278287

279288
static void flow_offload_ipv6_dnat(struct net *net,
@@ -282,23 +291,23 @@ static void flow_offload_ipv6_dnat(struct net *net,
282291
struct nf_flow_rule *flow_rule)
283292
{
284293
u32 mask = ~htonl(0xffffffff);
285-
const u8 *addr;
294+
const __be32 *addr;
286295
u32 offset;
287296

288297
switch (dir) {
289298
case FLOW_OFFLOAD_DIR_ORIGINAL:
290-
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr;
299+
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr32;
291300
offset = offsetof(struct ipv6hdr, daddr);
292301
break;
293302
case FLOW_OFFLOAD_DIR_REPLY:
294-
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr;
303+
addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr32;
295304
offset = offsetof(struct ipv6hdr, saddr);
296305
break;
297306
default:
298307
return;
299308
}
300309

301-
flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask);
310+
flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
302311
}
303312

304313
static int flow_offload_l4proto(const struct flow_offload *flow)
@@ -326,25 +335,24 @@ static void flow_offload_port_snat(struct net *net,
326335
struct nf_flow_rule *flow_rule)
327336
{
328337
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
329-
u32 mask = ~htonl(0xffff0000);
330-
__be16 port;
338+
u32 mask = ~htonl(0xffff0000), port;
331339
u32 offset;
332340

333341
switch (dir) {
334342
case FLOW_OFFLOAD_DIR_ORIGINAL:
335-
port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port;
343+
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
336344
offset = 0; /* offsetof(struct tcphdr, source); */
337345
break;
338346
case FLOW_OFFLOAD_DIR_REPLY:
339-
port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port;
347+
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
340348
offset = 0; /* offsetof(struct tcphdr, dest); */
341349
break;
342350
default:
343-
break;
351+
return;
344352
}
345-
353+
port = htonl(port << 16);
346354
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
347-
(u8 *)&port, (u8 *)&mask);
355+
&port, &mask);
348356
}
349357

350358
static void flow_offload_port_dnat(struct net *net,
@@ -353,25 +361,24 @@ static void flow_offload_port_dnat(struct net *net,
353361
struct nf_flow_rule *flow_rule)
354362
{
355363
struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
356-
u32 mask = ~htonl(0xffff);
357-
__be16 port;
364+
u32 mask = ~htonl(0xffff), port;
358365
u32 offset;
359366

360367
switch (dir) {
361368
case FLOW_OFFLOAD_DIR_ORIGINAL:
362-
port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port;
369+
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
363370
offset = 0; /* offsetof(struct tcphdr, source); */
364371
break;
365372
case FLOW_OFFLOAD_DIR_REPLY:
366-
port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port;
373+
port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
367374
offset = 0; /* offsetof(struct tcphdr, dest); */
368375
break;
369376
default:
370-
break;
377+
return;
371378
}
372-
379+
port = htonl(port);
373380
flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
374-
(u8 *)&port, (u8 *)&mask);
381+
&port, &mask);
375382
}
376383

377384
static void flow_offload_ipv4_checksum(struct net *net,
@@ -574,7 +581,7 @@ static int flow_offload_tuple_add(struct flow_offload_work *offload,
574581
cls_flow.rule = flow_rule->rule;
575582

576583
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) {
577-
err = block_cb->cb(TC_SETUP_FT, &cls_flow,
584+
err = block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow,
578585
block_cb->cb_priv);
579586
if (err < 0)
580587
continue;
@@ -599,7 +606,7 @@ static void flow_offload_tuple_del(struct flow_offload_work *offload,
599606
&offload->flow->tuplehash[dir].tuple, &extack);
600607

601608
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
602-
block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv);
609+
block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
603610

604611
offload->flow->flags |= FLOW_OFFLOAD_HW_DEAD;
605612
}
@@ -656,7 +663,7 @@ static void flow_offload_tuple_stats(struct flow_offload_work *offload,
656663
&offload->flow->tuplehash[dir].tuple, &extack);
657664

658665
list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
659-
block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv);
666+
block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
660667
memcpy(stats, &cls_flow.stats, sizeof(*stats));
661668
}
662669

@@ -822,7 +829,7 @@ int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
822829
bo.extack = &extack;
823830
INIT_LIST_HEAD(&bo.cb_list);
824831

825-
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
832+
err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, &bo);
826833
if (err < 0)
827834
return err;
828835

net/netfilter/nf_queue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
189189
goto err;
190190
}
191191

192-
if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) {
192+
if (skb_dst(skb) && !skb_dst_force(skb)) {
193193
status = -ENETDOWN;
194194
goto err;
195195
}

net/netfilter/nf_tables_api.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4519,8 +4519,10 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
45194519
return err;
45204520

45214521
err = -EINVAL;
4522-
if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
4522+
if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
4523+
nft_data_release(&elem.key.val, desc.type);
45234524
return err;
4525+
}
45244526

45254527
priv = set->ops->get(ctx->net, set, &elem, flags);
45264528
if (IS_ERR(priv))
@@ -4756,14 +4758,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
47564758
if (nla[NFTA_SET_ELEM_DATA] == NULL &&
47574759
!(flags & NFT_SET_ELEM_INTERVAL_END))
47584760
return -EINVAL;
4759-
if (nla[NFTA_SET_ELEM_DATA] != NULL &&
4760-
flags & NFT_SET_ELEM_INTERVAL_END)
4761-
return -EINVAL;
47624761
} else {
47634762
if (nla[NFTA_SET_ELEM_DATA] != NULL)
47644763
return -EINVAL;
47654764
}
47664765

4766+
if ((flags & NFT_SET_ELEM_INTERVAL_END) &&
4767+
(nla[NFTA_SET_ELEM_DATA] ||
4768+
nla[NFTA_SET_ELEM_OBJREF] ||
4769+
nla[NFTA_SET_ELEM_TIMEOUT] ||
4770+
nla[NFTA_SET_ELEM_EXPIRATION] ||
4771+
nla[NFTA_SET_ELEM_USERDATA] ||
4772+
nla[NFTA_SET_ELEM_EXPR]))
4773+
return -EINVAL;
4774+
47674775
timeout = 0;
47684776
if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
47694777
if (!(set->flags & NFT_SET_TIMEOUT))
@@ -5476,7 +5484,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
54765484
if (nlh->nlmsg_flags & NLM_F_REPLACE)
54775485
return -EOPNOTSUPP;
54785486

5479-
type = nft_obj_type_get(net, objtype);
5487+
type = __nft_obj_type_get(objtype);
54805488
nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
54815489

54825490
return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);

0 commit comments

Comments
 (0)