Skip to content

Commit a1f6740

Browse files
ummakynesgregkh
authored andcommitted
netfilter: nf_tables: initialize set before expression setup
[ Upstream commit ad9f151 ] nft_set_elem_expr_alloc() needs an initialized set if expression sets on the NFT_EXPR_GC flag. Move set fields initialization before expression setup. [4512935.019450] ================================================================== [4512935.019456] BUG: KASAN: null-ptr-deref in nft_set_elem_expr_alloc+0x84/0xd0 [nf_tables] [4512935.019487] Read of size 8 at addr 0000000000000070 by task nft/23532 [4512935.019494] CPU: 1 PID: 23532 Comm: nft Not tainted 5.12.0-rc4+ #48 [...] [4512935.019502] Call Trace: [4512935.019505] dump_stack+0x89/0xb4 [4512935.019512] ? nft_set_elem_expr_alloc+0x84/0xd0 [nf_tables] [4512935.019536] ? nft_set_elem_expr_alloc+0x84/0xd0 [nf_tables] [4512935.019560] kasan_report.cold.12+0x5f/0xd8 [4512935.019566] ? nft_set_elem_expr_alloc+0x84/0xd0 [nf_tables] [4512935.019590] nft_set_elem_expr_alloc+0x84/0xd0 [nf_tables] [4512935.019615] nf_tables_newset+0xc7f/0x1460 [nf_tables] Reported-by: [email protected] Fixes: 6503842 ("netfilter: nf_tables: allow to specify stateful expression in set definition") Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 2e44117 commit a1f6740

File tree

1 file changed

+42
-41
lines changed

1 file changed

+42
-41
lines changed

net/netfilter/nf_tables_api.c

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4317,13 +4317,44 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
43174317
err = nf_tables_set_alloc_name(&ctx, set, name);
43184318
kfree(name);
43194319
if (err < 0)
4320-
goto err_set_alloc_name;
4320+
goto err_set_name;
4321+
4322+
udata = NULL;
4323+
if (udlen) {
4324+
udata = set->data + size;
4325+
nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
4326+
}
4327+
4328+
INIT_LIST_HEAD(&set->bindings);
4329+
set->table = table;
4330+
write_pnet(&set->net, net);
4331+
set->ops = ops;
4332+
set->ktype = ktype;
4333+
set->klen = desc.klen;
4334+
set->dtype = dtype;
4335+
set->objtype = objtype;
4336+
set->dlen = desc.dlen;
4337+
set->flags = flags;
4338+
set->size = desc.size;
4339+
set->policy = policy;
4340+
set->udlen = udlen;
4341+
set->udata = udata;
4342+
set->timeout = timeout;
4343+
set->gc_int = gc_int;
4344+
4345+
set->field_count = desc.field_count;
4346+
for (i = 0; i < desc.field_count; i++)
4347+
set->field_len[i] = desc.field_len[i];
4348+
4349+
err = ops->init(set, &desc, nla);
4350+
if (err < 0)
4351+
goto err_set_init;
43214352

43224353
if (nla[NFTA_SET_EXPR]) {
43234354
expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
43244355
if (IS_ERR(expr)) {
43254356
err = PTR_ERR(expr);
4326-
goto err_set_alloc_name;
4357+
goto err_set_expr_alloc;
43274358
}
43284359
set->exprs[0] = expr;
43294360
set->num_exprs++;
@@ -4334,74 +4365,44 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
43344365

43354366
if (!(flags & NFT_SET_EXPR)) {
43364367
err = -EINVAL;
4337-
goto err_set_alloc_name;
4368+
goto err_set_expr_alloc;
43384369
}
43394370
i = 0;
43404371
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
43414372
if (i == NFT_SET_EXPR_MAX) {
43424373
err = -E2BIG;
4343-
goto err_set_init;
4374+
goto err_set_expr_alloc;
43444375
}
43454376
if (nla_type(tmp) != NFTA_LIST_ELEM) {
43464377
err = -EINVAL;
4347-
goto err_set_init;
4378+
goto err_set_expr_alloc;
43484379
}
43494380
expr = nft_set_elem_expr_alloc(&ctx, set, tmp);
43504381
if (IS_ERR(expr)) {
43514382
err = PTR_ERR(expr);
4352-
goto err_set_init;
4383+
goto err_set_expr_alloc;
43534384
}
43544385
set->exprs[i++] = expr;
43554386
set->num_exprs++;
43564387
}
43574388
}
43584389

4359-
udata = NULL;
4360-
if (udlen) {
4361-
udata = set->data + size;
4362-
nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
4363-
}
4364-
4365-
INIT_LIST_HEAD(&set->bindings);
4366-
set->table = table;
4367-
write_pnet(&set->net, net);
4368-
set->ops = ops;
4369-
set->ktype = ktype;
4370-
set->klen = desc.klen;
4371-
set->dtype = dtype;
4372-
set->objtype = objtype;
4373-
set->dlen = desc.dlen;
4374-
set->flags = flags;
4375-
set->size = desc.size;
4376-
set->policy = policy;
4377-
set->udlen = udlen;
4378-
set->udata = udata;
4379-
set->timeout = timeout;
4380-
set->gc_int = gc_int;
43814390
set->handle = nf_tables_alloc_handle(table);
43824391

4383-
set->field_count = desc.field_count;
4384-
for (i = 0; i < desc.field_count; i++)
4385-
set->field_len[i] = desc.field_len[i];
4386-
4387-
err = ops->init(set, &desc, nla);
4388-
if (err < 0)
4389-
goto err_set_init;
4390-
43914392
err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
43924393
if (err < 0)
4393-
goto err_set_trans;
4394+
goto err_set_expr_alloc;
43944395

43954396
list_add_tail_rcu(&set->list, &table->sets);
43964397
table->use++;
43974398
return 0;
43984399

4399-
err_set_trans:
4400-
ops->destroy(set);
4401-
err_set_init:
4400+
err_set_expr_alloc:
44024401
for (i = 0; i < set->num_exprs; i++)
44034402
nft_expr_destroy(&ctx, set->exprs[i]);
4404-
err_set_alloc_name:
4403+
4404+
ops->destroy(set);
4405+
err_set_init:
44054406
kfree(set->name);
44064407
err_set_name:
44074408
kvfree(set);

0 commit comments

Comments
 (0)