Skip to content

Commit aba53cc

Browse files
committed
Merge tag 'nf-26-04-01' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net. Note that most of the bugs fixed here are >5 years old. The large PR is not due to an increase in regressions. 1) Flowtable hardware offload support in IPv6 can lead to out-of-bounds when populating the rule action array when combined with double-tagged vlan. Bump the maximum number of actions from 16 to 24 and check that such limit is never reached, otherwise bail out. This bugs stems from the original flowtable hardware offload support. 2) nfnetlink_log does not include the netlink header size of the trailing NLMSG_DONE message when calculating the skb size. From Florian Westphal. 3) Reject names in xt_cgroup and xt_rateest extensions which are not nul-terminated. Also from Florian. 4) Use nla_strcmp in ipset lookup by set name, since IPSET_ATTR_NAME and IPSET_ATTR_NAMEREF are of NLA_STRING type. From Florian Westphal. 5) When unregistering conntrack helpers, pass the helper that is going away so the expectation cleanup is done accordingly, otherwise UaF is possible when accessing expectation that refer to the helper that is gone. From Qi Tang. 6) Zero expectation NAT fields to address leaking kernel memory through the expectation netlink dump when unset. Also from Qi Tang. 7) Use the master conntrack helper when creating expectations via ctnetlink, ignore the suggested helper through CTA_EXPECT_HELP_NAME. This allows to address a possible read of kernel memory off the expectation object boundary. 8) Fix incorrect release of the hash bucket logic in ipset when the bucket is empty, leading to shrinking the hash bucket to size 0 which deals to out-of-bound write in next element additions. From Yifan Wu. 9) Allow the use of x_tables extensions that explicitly declare NFPROTO_ARP support only. This is to avoid an incorrect hook number validation due to non-overlapping arp and inet hook number definitions. 10) Reject immediate NF_QUEUE verdict in nf_tables. The userspace nft tool always uses the nft_queue expression for queueing. This ensures this verdict cannot be used for the arp family, which does supported this. * tag 'nf-26-04-01' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_tables: reject immediate NF_QUEUE verdict netfilter: x_tables: restrict xt_check_match/xt_check_target extensions for NFPROTO_ARP netfilter: ipset: drop logically empty buckets in mtype_del netfilter: ctnetlink: ignore explicit helper on new expectations netfilter: ctnetlink: zero expect NAT fields when CTA_EXPECT_NAT absent netfilter: nf_conntrack_helper: pass helper to expect cleanup netfilter: ipset: use nla_strcmp for IPSET_ATTR_NAME attr netfilter: x_tables: ensure names are nul-terminated netfilter: nfnetlink_log: account for netlink header size netfilter: flowtable: strictly check for maximum number of actions ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 6d6be70 + da10739 commit aba53cc

12 files changed

Lines changed: 192 additions & 121 deletions

File tree

include/linux/netfilter/ipset/ip_set.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ enum {
309309

310310
/* register and unregister set references */
311311
extern ip_set_id_t ip_set_get_byname(struct net *net,
312-
const char *name, struct ip_set **set);
312+
const struct nlattr *name, struct ip_set **set);
313313
extern void ip_set_put_byindex(struct net *net, ip_set_id_t index);
314314
extern void ip_set_name_byindex(struct net *net, ip_set_id_t index, char *name);
315315
extern ip_set_id_t ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index);

net/netfilter/ipset/ip_set_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ EXPORT_SYMBOL_GPL(ip_set_del);
821821
*
822822
*/
823823
ip_set_id_t
824-
ip_set_get_byname(struct net *net, const char *name, struct ip_set **set)
824+
ip_set_get_byname(struct net *net, const struct nlattr *name, struct ip_set **set)
825825
{
826826
ip_set_id_t i, index = IPSET_INVALID_ID;
827827
struct ip_set *s;
@@ -830,7 +830,7 @@ ip_set_get_byname(struct net *net, const char *name, struct ip_set **set)
830830
rcu_read_lock();
831831
for (i = 0; i < inst->ip_set_max; i++) {
832832
s = rcu_dereference(inst->ip_set_list)[i];
833-
if (s && STRNCMP(s->name, name)) {
833+
if (s && nla_strcmp(name, s->name) == 0) {
834834
__ip_set_get(s);
835835
index = i;
836836
*set = s;

net/netfilter/ipset/ip_set_hash_gen.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10981098
if (!test_bit(i, n->used))
10991099
k++;
11001100
}
1101-
if (n->pos == 0 && k == 0) {
1101+
if (k == n->pos) {
11021102
t->hregion[r].ext_size -= ext_size(n->size, dsize);
11031103
rcu_assign_pointer(hbucket(t, key), NULL);
11041104
kfree_rcu(n, rcu);

net/netfilter/ipset/ip_set_list_set.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
367367
ret = ip_set_get_extensions(set, tb, &ext);
368368
if (ret)
369369
return ret;
370-
e.id = ip_set_get_byname(map->net, nla_data(tb[IPSET_ATTR_NAME]), &s);
370+
e.id = ip_set_get_byname(map->net, tb[IPSET_ATTR_NAME], &s);
371371
if (e.id == IPSET_INVALID_ID)
372372
return -IPSET_ERR_NAME;
373373
/* "Loop detection" */
@@ -389,7 +389,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
389389

390390
if (tb[IPSET_ATTR_NAMEREF]) {
391391
e.refid = ip_set_get_byname(map->net,
392-
nla_data(tb[IPSET_ATTR_NAMEREF]),
392+
tb[IPSET_ATTR_NAMEREF],
393393
&s);
394394
if (e.refid == IPSET_INVALID_ID) {
395395
ret = -IPSET_ERR_NAMEREF;

net/netfilter/nf_conntrack_helper.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
415415
*/
416416
synchronize_rcu();
417417

418-
nf_ct_expect_iterate_destroy(expect_iter_me, NULL);
418+
nf_ct_expect_iterate_destroy(expect_iter_me, me);
419419
nf_ct_iterate_destroy(unhelp, me);
420420

421421
/* nf_ct_iterate_destroy() does an unconditional synchronize_rcu() as

net/netfilter/nf_conntrack_netlink.c

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,7 +2636,6 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
26362636

26372637
static struct nf_conntrack_expect *
26382638
ctnetlink_alloc_expect(const struct nlattr *const cda[], struct nf_conn *ct,
2639-
struct nf_conntrack_helper *helper,
26402639
struct nf_conntrack_tuple *tuple,
26412640
struct nf_conntrack_tuple *mask);
26422641

@@ -2865,7 +2864,6 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
28652864
{
28662865
struct nlattr *cda[CTA_EXPECT_MAX+1];
28672866
struct nf_conntrack_tuple tuple, mask;
2868-
struct nf_conntrack_helper *helper = NULL;
28692867
struct nf_conntrack_expect *exp;
28702868
int err;
28712869

@@ -2879,17 +2877,8 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,
28792877
if (err < 0)
28802878
return err;
28812879

2882-
if (cda[CTA_EXPECT_HELP_NAME]) {
2883-
const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
2884-
2885-
helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
2886-
nf_ct_protonum(ct));
2887-
if (helper == NULL)
2888-
return -EOPNOTSUPP;
2889-
}
2890-
28912880
exp = ctnetlink_alloc_expect((const struct nlattr * const *)cda, ct,
2892-
helper, &tuple, &mask);
2881+
&tuple, &mask);
28932882
if (IS_ERR(exp))
28942883
return PTR_ERR(exp);
28952884

@@ -3528,11 +3517,11 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr,
35283517

35293518
static struct nf_conntrack_expect *
35303519
ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
3531-
struct nf_conntrack_helper *helper,
35323520
struct nf_conntrack_tuple *tuple,
35333521
struct nf_conntrack_tuple *mask)
35343522
{
35353523
struct net *net = read_pnet(&ct->ct_net);
3524+
struct nf_conntrack_helper *helper;
35363525
struct nf_conntrack_expect *exp;
35373526
struct nf_conn_help *help;
35383527
u32 class = 0;
@@ -3542,7 +3531,11 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
35423531
if (!help)
35433532
return ERR_PTR(-EOPNOTSUPP);
35443533

3545-
if (cda[CTA_EXPECT_CLASS] && helper) {
3534+
helper = rcu_dereference(help->helper);
3535+
if (!helper)
3536+
return ERR_PTR(-EOPNOTSUPP);
3537+
3538+
if (cda[CTA_EXPECT_CLASS]) {
35463539
class = ntohl(nla_get_be32(cda[CTA_EXPECT_CLASS]));
35473540
if (class > helper->expect_class_max)
35483541
return ERR_PTR(-EINVAL);
@@ -3576,8 +3569,6 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
35763569
#ifdef CONFIG_NF_CONNTRACK_ZONES
35773570
exp->zone = ct->zone;
35783571
#endif
3579-
if (!helper)
3580-
helper = rcu_dereference(help->helper);
35813572
rcu_assign_pointer(exp->helper, helper);
35823573
exp->tuple = *tuple;
35833574
exp->mask.src.u3 = mask->src.u3;
@@ -3588,6 +3579,12 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
35883579
exp, nf_ct_l3num(ct));
35893580
if (err < 0)
35903581
goto err_out;
3582+
#if IS_ENABLED(CONFIG_NF_NAT)
3583+
} else {
3584+
memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
3585+
memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
3586+
exp->dir = 0;
3587+
#endif
35913588
}
35923589
return exp;
35933590
err_out:
@@ -3603,7 +3600,6 @@ ctnetlink_create_expect(struct net *net,
36033600
{
36043601
struct nf_conntrack_tuple tuple, mask, master_tuple;
36053602
struct nf_conntrack_tuple_hash *h = NULL;
3606-
struct nf_conntrack_helper *helper = NULL;
36073603
struct nf_conntrack_expect *exp;
36083604
struct nf_conn *ct;
36093605
int err;
@@ -3629,33 +3625,7 @@ ctnetlink_create_expect(struct net *net,
36293625
ct = nf_ct_tuplehash_to_ctrack(h);
36303626

36313627
rcu_read_lock();
3632-
if (cda[CTA_EXPECT_HELP_NAME]) {
3633-
const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
3634-
3635-
helper = __nf_conntrack_helper_find(helpname, u3,
3636-
nf_ct_protonum(ct));
3637-
if (helper == NULL) {
3638-
rcu_read_unlock();
3639-
#ifdef CONFIG_MODULES
3640-
if (request_module("nfct-helper-%s", helpname) < 0) {
3641-
err = -EOPNOTSUPP;
3642-
goto err_ct;
3643-
}
3644-
rcu_read_lock();
3645-
helper = __nf_conntrack_helper_find(helpname, u3,
3646-
nf_ct_protonum(ct));
3647-
if (helper) {
3648-
err = -EAGAIN;
3649-
goto err_rcu;
3650-
}
3651-
rcu_read_unlock();
3652-
#endif
3653-
err = -EOPNOTSUPP;
3654-
goto err_ct;
3655-
}
3656-
}
3657-
3658-
exp = ctnetlink_alloc_expect(cda, ct, helper, &tuple, &mask);
3628+
exp = ctnetlink_alloc_expect(cda, ct, &tuple, &mask);
36593629
if (IS_ERR(exp)) {
36603630
err = PTR_ERR(exp);
36613631
goto err_rcu;
@@ -3665,8 +3635,8 @@ ctnetlink_create_expect(struct net *net,
36653635
nf_ct_expect_put(exp);
36663636
err_rcu:
36673637
rcu_read_unlock();
3668-
err_ct:
36693638
nf_ct_put(ct);
3639+
36703640
return err;
36713641
}
36723642

0 commit comments

Comments
 (0)