Skip to content

Commit a422757

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 the first batch of Netfilter fixes for your net tree: 1) Fix splat with IPv6 defragmenting locally generated fragments, from Florian Westphal. 2) Fix Incorrect check for missing attribute in nft_osf. 3) Missing INT_MIN & INT_MAX definition for netfilter bridge uapi header, from Jiri Slaby. 4) Revert map lookup in nft_numgen, this is already possible with the existing infrastructure without this extension. 5) Fix wrong listing of set reference counter, make counter synchronous again, from Stefano Brivio. 6) Fix CIDR 0 in hash:net,port,net, from Eric Westbrook. 7) Fix allocation failure with large set, use kvcalloc(). From Andrey Ryabinin. 8) No need to disable BH when fetch ip set comment, patch from Jozsef Kadlecsik. 9) Sanity check for valid sysfs entry in xt_IDLETIMER, from Taehee Yoo. 10) Fix suspicious rcu usage via ip_set() macro at netlink dump, from Jozsef Kadlecsik. 11) Fix setting default timeout via nfnetlink_cttimeout, this comes with preparation patch to add nf_{tcp,udp,...}_pernet() helper. 12) Allow ebtables table nat to be of filter type via nft_compat. From Florian Westphal. 13) Incorrect calculation of next bucket in early_drop, do no bump hash value, update bucket counter instead. From Vasily Khoruzhick. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 7131193 + f393808 commit a422757

22 files changed

+200
-247
lines changed

include/linux/netfilter/ipset/ip_set.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ enum {
314314
extern ip_set_id_t ip_set_get_byname(struct net *net,
315315
const char *name, struct ip_set **set);
316316
extern void ip_set_put_byindex(struct net *net, ip_set_id_t index);
317-
extern const char *ip_set_name_byindex(struct net *net, ip_set_id_t index);
317+
extern void ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name);
318318
extern ip_set_id_t ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index);
319319
extern void ip_set_nfnl_put(struct net *net, ip_set_id_t index);
320320

include/linux/netfilter/ipset/ip_set_comment.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ ip_set_init_comment(struct ip_set *set, struct ip_set_comment *comment,
4343
rcu_assign_pointer(comment->c, c);
4444
}
4545

46-
/* Used only when dumping a set, protected by rcu_read_lock_bh() */
46+
/* Used only when dumping a set, protected by rcu_read_lock() */
4747
static inline int
4848
ip_set_put_comment(struct sk_buff *skb, const struct ip_set_comment *comment)
4949
{
50-
struct ip_set_comment_rcu *c = rcu_dereference_bh(comment->c);
50+
struct ip_set_comment_rcu *c = rcu_dereference(comment->c);
5151

5252
if (!c)
5353
return 0;

include/net/netfilter/nf_conntrack_l4proto.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,43 @@ void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
153153
const char *fmt, ...) { }
154154
#endif /* CONFIG_SYSCTL */
155155

156+
static inline struct nf_generic_net *nf_generic_pernet(struct net *net)
157+
{
158+
return &net->ct.nf_ct_proto.generic;
159+
}
160+
161+
static inline struct nf_tcp_net *nf_tcp_pernet(struct net *net)
162+
{
163+
return &net->ct.nf_ct_proto.tcp;
164+
}
165+
166+
static inline struct nf_udp_net *nf_udp_pernet(struct net *net)
167+
{
168+
return &net->ct.nf_ct_proto.udp;
169+
}
170+
171+
static inline struct nf_icmp_net *nf_icmp_pernet(struct net *net)
172+
{
173+
return &net->ct.nf_ct_proto.icmp;
174+
}
175+
176+
static inline struct nf_icmp_net *nf_icmpv6_pernet(struct net *net)
177+
{
178+
return &net->ct.nf_ct_proto.icmpv6;
179+
}
180+
181+
#ifdef CONFIG_NF_CT_PROTO_DCCP
182+
static inline struct nf_dccp_net *nf_dccp_pernet(struct net *net)
183+
{
184+
return &net->ct.nf_ct_proto.dccp;
185+
}
186+
#endif
187+
188+
#ifdef CONFIG_NF_CT_PROTO_SCTP
189+
static inline struct nf_sctp_net *nf_sctp_pernet(struct net *net)
190+
{
191+
return &net->ct.nf_ct_proto.sctp;
192+
}
193+
#endif
194+
156195
#endif /*_NF_CONNTRACK_PROTOCOL_H*/

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,8 +1635,8 @@ enum nft_ng_attributes {
16351635
NFTA_NG_MODULUS,
16361636
NFTA_NG_TYPE,
16371637
NFTA_NG_OFFSET,
1638-
NFTA_NG_SET_NAME,
1639-
NFTA_NG_SET_ID,
1638+
NFTA_NG_SET_NAME, /* deprecated */
1639+
NFTA_NG_SET_ID, /* deprecated */
16401640
__NFTA_NG_MAX
16411641
};
16421642
#define NFTA_NG_MAX (__NFTA_NG_MAX - 1)

include/uapi/linux/netfilter_bridge.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#include <linux/if_vlan.h>
1212
#include <linux/if_pppox.h>
1313

14+
#ifndef __KERNEL__
15+
#include <limits.h> /* for INT_MIN, INT_MAX */
16+
#endif
17+
1418
/* Bridge Hooks */
1519
/* After promisc drops, checksum checks. */
1620
#define NF_BR_PRE_ROUTING 0

net/ipv6/netfilter/nf_conntrack_reasm.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,11 +587,16 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
587587
*/
588588
ret = -EINPROGRESS;
589589
if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
590-
fq->q.meat == fq->q.len &&
591-
nf_ct_frag6_reasm(fq, skb, dev))
592-
ret = 0;
593-
else
590+
fq->q.meat == fq->q.len) {
591+
unsigned long orefdst = skb->_skb_refdst;
592+
593+
skb->_skb_refdst = 0UL;
594+
if (nf_ct_frag6_reasm(fq, skb, dev))
595+
ret = 0;
596+
skb->_skb_refdst = orefdst;
597+
} else {
594598
skb_dst_drop(skb);
599+
}
595600

596601
out_unlock:
597602
spin_unlock_bh(&fq->q.lock);

net/netfilter/ipset/ip_set_core.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5555
MODULE_DESCRIPTION("core IP set support");
5656
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
5757

58-
/* When the nfnl mutex is held: */
58+
/* When the nfnl mutex or ip_set_ref_lock is held: */
5959
#define ip_set_dereference(p) \
60-
rcu_dereference_protected(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
60+
rcu_dereference_protected(p, \
61+
lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET) || \
62+
lockdep_is_held(&ip_set_ref_lock))
6163
#define ip_set(inst, id) \
6264
ip_set_dereference((inst)->ip_set_list)[id]
65+
#define ip_set_ref_netlink(inst,id) \
66+
rcu_dereference_raw((inst)->ip_set_list)[id]
6367

6468
/* The set types are implemented in modules and registered set types
6569
* can be found in ip_set_type_list. Adding/deleting types is
@@ -693,21 +697,20 @@ ip_set_put_byindex(struct net *net, ip_set_id_t index)
693697
EXPORT_SYMBOL_GPL(ip_set_put_byindex);
694698

695699
/* Get the name of a set behind a set index.
696-
* We assume the set is referenced, so it does exist and
697-
* can't be destroyed. The set cannot be renamed due to
698-
* the referencing either.
699-
*
700+
* Set itself is protected by RCU, but its name isn't: to protect against
701+
* renaming, grab ip_set_ref_lock as reader (see ip_set_rename()) and copy the
702+
* name.
700703
*/
701-
const char *
702-
ip_set_name_byindex(struct net *net, ip_set_id_t index)
704+
void
705+
ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name)
703706
{
704-
const struct ip_set *set = ip_set_rcu_get(net, index);
707+
struct ip_set *set = ip_set_rcu_get(net, index);
705708

706709
BUG_ON(!set);
707-
BUG_ON(set->ref == 0);
708710

709-
/* Referenced, so it's safe */
710-
return set->name;
711+
read_lock_bh(&ip_set_ref_lock);
712+
strncpy(name, set->name, IPSET_MAXNAMELEN);
713+
read_unlock_bh(&ip_set_ref_lock);
711714
}
712715
EXPORT_SYMBOL_GPL(ip_set_name_byindex);
713716

@@ -961,7 +964,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
961964
/* Wraparound */
962965
goto cleanup;
963966

964-
list = kcalloc(i, sizeof(struct ip_set *), GFP_KERNEL);
967+
list = kvcalloc(i, sizeof(struct ip_set *), GFP_KERNEL);
965968
if (!list)
966969
goto cleanup;
967970
/* nfnl mutex is held, both lists are valid */
@@ -973,7 +976,7 @@ static int ip_set_create(struct net *net, struct sock *ctnl,
973976
/* Use new list */
974977
index = inst->ip_set_max;
975978
inst->ip_set_max = i;
976-
kfree(tmp);
979+
kvfree(tmp);
977980
ret = 0;
978981
} else if (ret) {
979982
goto cleanup;
@@ -1153,7 +1156,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
11531156
if (!set)
11541157
return -ENOENT;
11551158

1156-
read_lock_bh(&ip_set_ref_lock);
1159+
write_lock_bh(&ip_set_ref_lock);
11571160
if (set->ref != 0) {
11581161
ret = -IPSET_ERR_REFERENCED;
11591162
goto out;
@@ -1170,7 +1173,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl,
11701173
strncpy(set->name, name2, IPSET_MAXNAMELEN);
11711174

11721175
out:
1173-
read_unlock_bh(&ip_set_ref_lock);
1176+
write_unlock_bh(&ip_set_ref_lock);
11741177
return ret;
11751178
}
11761179

@@ -1252,7 +1255,7 @@ ip_set_dump_done(struct netlink_callback *cb)
12521255
struct ip_set_net *inst =
12531256
(struct ip_set_net *)cb->args[IPSET_CB_NET];
12541257
ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
1255-
struct ip_set *set = ip_set(inst, index);
1258+
struct ip_set *set = ip_set_ref_netlink(inst, index);
12561259

12571260
if (set->variant->uref)
12581261
set->variant->uref(set, cb, false);
@@ -1441,7 +1444,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
14411444
release_refcount:
14421445
/* If there was an error or set is done, release set */
14431446
if (ret || !cb->args[IPSET_CB_ARG0]) {
1444-
set = ip_set(inst, index);
1447+
set = ip_set_ref_netlink(inst, index);
14451448
if (set->variant->uref)
14461449
set->variant->uref(set, cb, false);
14471450
pr_debug("release set %s\n", set->name);
@@ -2059,7 +2062,7 @@ ip_set_net_init(struct net *net)
20592062
if (inst->ip_set_max >= IPSET_INVALID_ID)
20602063
inst->ip_set_max = IPSET_INVALID_ID - 1;
20612064

2062-
list = kcalloc(inst->ip_set_max, sizeof(struct ip_set *), GFP_KERNEL);
2065+
list = kvcalloc(inst->ip_set_max, sizeof(struct ip_set *), GFP_KERNEL);
20632066
if (!list)
20642067
return -ENOMEM;
20652068
inst->is_deleted = false;
@@ -2087,7 +2090,7 @@ ip_set_net_exit(struct net *net)
20872090
}
20882091
}
20892092
nfnl_unlock(NFNL_SUBSYS_IPSET);
2090-
kfree(rcu_dereference_protected(inst->ip_set_list, 1));
2093+
kvfree(rcu_dereference_protected(inst->ip_set_list, 1));
20912094
}
20922095

20932096
static struct pernet_operations ip_set_net_ops = {

net/netfilter/ipset/ip_set_hash_netportnet.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
213213

214214
if (tb[IPSET_ATTR_CIDR]) {
215215
e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
216-
if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
216+
if (e.cidr[0] > HOST_MASK)
217217
return -IPSET_ERR_INVALID_CIDR;
218218
}
219219

220220
if (tb[IPSET_ATTR_CIDR2]) {
221221
e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
222-
if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
222+
if (e.cidr[1] > HOST_MASK)
223223
return -IPSET_ERR_INVALID_CIDR;
224224
}
225225

@@ -493,13 +493,13 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
493493

494494
if (tb[IPSET_ATTR_CIDR]) {
495495
e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
496-
if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
496+
if (e.cidr[0] > HOST_MASK)
497497
return -IPSET_ERR_INVALID_CIDR;
498498
}
499499

500500
if (tb[IPSET_ATTR_CIDR2]) {
501501
e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
502-
if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
502+
if (e.cidr[1] > HOST_MASK)
503503
return -IPSET_ERR_INVALID_CIDR;
504504
}
505505

net/netfilter/ipset/ip_set_list_set.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,25 +148,29 @@ __list_set_del_rcu(struct rcu_head * rcu)
148148
{
149149
struct set_elem *e = container_of(rcu, struct set_elem, rcu);
150150
struct ip_set *set = e->set;
151-
struct list_set *map = set->data;
152151

153-
ip_set_put_byindex(map->net, e->id);
154152
ip_set_ext_destroy(set, e);
155153
kfree(e);
156154
}
157155

158156
static inline void
159157
list_set_del(struct ip_set *set, struct set_elem *e)
160158
{
159+
struct list_set *map = set->data;
160+
161161
set->elements--;
162162
list_del_rcu(&e->list);
163+
ip_set_put_byindex(map->net, e->id);
163164
call_rcu(&e->rcu, __list_set_del_rcu);
164165
}
165166

166167
static inline void
167-
list_set_replace(struct set_elem *e, struct set_elem *old)
168+
list_set_replace(struct ip_set *set, struct set_elem *e, struct set_elem *old)
168169
{
170+
struct list_set *map = set->data;
171+
169172
list_replace_rcu(&old->list, &e->list);
173+
ip_set_put_byindex(map->net, old->id);
170174
call_rcu(&old->rcu, __list_set_del_rcu);
171175
}
172176

@@ -298,7 +302,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
298302
INIT_LIST_HEAD(&e->list);
299303
list_set_init_extensions(set, ext, e);
300304
if (n)
301-
list_set_replace(e, n);
305+
list_set_replace(set, e, n);
302306
else if (next)
303307
list_add_tail_rcu(&e->list, &next->list);
304308
else if (prev)
@@ -486,6 +490,7 @@ list_set_list(const struct ip_set *set,
486490
const struct list_set *map = set->data;
487491
struct nlattr *atd, *nested;
488492
u32 i = 0, first = cb->args[IPSET_CB_ARG0];
493+
char name[IPSET_MAXNAMELEN];
489494
struct set_elem *e;
490495
int ret = 0;
491496

@@ -504,8 +509,8 @@ list_set_list(const struct ip_set *set,
504509
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
505510
if (!nested)
506511
goto nla_put_failure;
507-
if (nla_put_string(skb, IPSET_ATTR_NAME,
508-
ip_set_name_byindex(map->net, e->id)))
512+
ip_set_name_byindex(map->net, e->id, name);
513+
if (nla_put_string(skb, IPSET_ATTR_NAME, name))
509514
goto nla_put_failure;
510515
if (ip_set_put_extensions(skb, set, e, true))
511516
goto nla_put_failure;

net/netfilter/nf_conntrack_core.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,19 +1073,22 @@ static unsigned int early_drop_list(struct net *net,
10731073
return drops;
10741074
}
10751075

1076-
static noinline int early_drop(struct net *net, unsigned int _hash)
1076+
static noinline int early_drop(struct net *net, unsigned int hash)
10771077
{
1078-
unsigned int i;
1078+
unsigned int i, bucket;
10791079

10801080
for (i = 0; i < NF_CT_EVICTION_RANGE; i++) {
10811081
struct hlist_nulls_head *ct_hash;
1082-
unsigned int hash, hsize, drops;
1082+
unsigned int hsize, drops;
10831083

10841084
rcu_read_lock();
10851085
nf_conntrack_get_ht(&ct_hash, &hsize);
1086-
hash = reciprocal_scale(_hash++, hsize);
1086+
if (!i)
1087+
bucket = reciprocal_scale(hash, hsize);
1088+
else
1089+
bucket = (bucket + 1) % hsize;
10871090

1088-
drops = early_drop_list(net, &ct_hash[hash]);
1091+
drops = early_drop_list(net, &ct_hash[bucket]);
10891092
rcu_read_unlock();
10901093

10911094
if (drops) {

net/netfilter/nf_conntrack_proto_dccp.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,6 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] =
384384
},
385385
};
386386

387-
static inline struct nf_dccp_net *dccp_pernet(struct net *net)
388-
{
389-
return &net->ct.nf_ct_proto.dccp;
390-
}
391-
392387
static noinline bool
393388
dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
394389
const struct dccp_hdr *dh)
@@ -401,7 +396,7 @@ dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
401396
state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
402397
switch (state) {
403398
default:
404-
dn = dccp_pernet(net);
399+
dn = nf_dccp_pernet(net);
405400
if (dn->dccp_loose == 0) {
406401
msg = "not picking up existing connection ";
407402
goto out_invalid;
@@ -568,7 +563,7 @@ static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb,
568563

569564
timeouts = nf_ct_timeout_lookup(ct);
570565
if (!timeouts)
571-
timeouts = dccp_pernet(nf_ct_net(ct))->dccp_timeout;
566+
timeouts = nf_dccp_pernet(nf_ct_net(ct))->dccp_timeout;
572567
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
573568

574569
return NF_ACCEPT;
@@ -681,7 +676,7 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
681676
static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
682677
struct net *net, void *data)
683678
{
684-
struct nf_dccp_net *dn = dccp_pernet(net);
679+
struct nf_dccp_net *dn = nf_dccp_pernet(net);
685680
unsigned int *timeouts = data;
686681
int i;
687682

@@ -814,7 +809,7 @@ static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
814809

815810
static int dccp_init_net(struct net *net)
816811
{
817-
struct nf_dccp_net *dn = dccp_pernet(net);
812+
struct nf_dccp_net *dn = nf_dccp_pernet(net);
818813
struct nf_proto_net *pn = &dn->pn;
819814

820815
if (!pn->users) {

0 commit comments

Comments
 (0)