Skip to content

Commit ad9f151

Browse files
committed
netfilter: nf_tables: initialize set before expression setup
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]>
1 parent f2386cf commit ad9f151

File tree

1 file changed

+43
-42
lines changed

1 file changed

+43
-42
lines changed

net/netfilter/nf_tables_api.c

+43-42
Original file line numberDiff line numberDiff line change
@@ -4364,13 +4364,45 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
43644364
err = nf_tables_set_alloc_name(&ctx, set, name);
43654365
kfree(name);
43664366
if (err < 0)
4367-
goto err_set_alloc_name;
4367+
goto err_set_name;
4368+
4369+
udata = NULL;
4370+
if (udlen) {
4371+
udata = set->data + size;
4372+
nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
4373+
}
4374+
4375+
INIT_LIST_HEAD(&set->bindings);
4376+
INIT_LIST_HEAD(&set->catchall_list);
4377+
set->table = table;
4378+
write_pnet(&set->net, net);
4379+
set->ops = ops;
4380+
set->ktype = ktype;
4381+
set->klen = desc.klen;
4382+
set->dtype = dtype;
4383+
set->objtype = objtype;
4384+
set->dlen = desc.dlen;
4385+
set->flags = flags;
4386+
set->size = desc.size;
4387+
set->policy = policy;
4388+
set->udlen = udlen;
4389+
set->udata = udata;
4390+
set->timeout = timeout;
4391+
set->gc_int = gc_int;
4392+
4393+
set->field_count = desc.field_count;
4394+
for (i = 0; i < desc.field_count; i++)
4395+
set->field_len[i] = desc.field_len[i];
4396+
4397+
err = ops->init(set, &desc, nla);
4398+
if (err < 0)
4399+
goto err_set_init;
43684400

43694401
if (nla[NFTA_SET_EXPR]) {
43704402
expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
43714403
if (IS_ERR(expr)) {
43724404
err = PTR_ERR(expr);
4373-
goto err_set_alloc_name;
4405+
goto err_set_expr_alloc;
43744406
}
43754407
set->exprs[0] = expr;
43764408
set->num_exprs++;
@@ -4381,75 +4413,44 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
43814413

43824414
if (!(flags & NFT_SET_EXPR)) {
43834415
err = -EINVAL;
4384-
goto err_set_alloc_name;
4416+
goto err_set_expr_alloc;
43854417
}
43864418
i = 0;
43874419
nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
43884420
if (i == NFT_SET_EXPR_MAX) {
43894421
err = -E2BIG;
4390-
goto err_set_init;
4422+
goto err_set_expr_alloc;
43914423
}
43924424
if (nla_type(tmp) != NFTA_LIST_ELEM) {
43934425
err = -EINVAL;
4394-
goto err_set_init;
4426+
goto err_set_expr_alloc;
43954427
}
43964428
expr = nft_set_elem_expr_alloc(&ctx, set, tmp);
43974429
if (IS_ERR(expr)) {
43984430
err = PTR_ERR(expr);
4399-
goto err_set_init;
4431+
goto err_set_expr_alloc;
44004432
}
44014433
set->exprs[i++] = expr;
44024434
set->num_exprs++;
44034435
}
44044436
}
44054437

4406-
udata = NULL;
4407-
if (udlen) {
4408-
udata = set->data + size;
4409-
nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
4410-
}
4411-
4412-
INIT_LIST_HEAD(&set->bindings);
4413-
INIT_LIST_HEAD(&set->catchall_list);
4414-
set->table = table;
4415-
write_pnet(&set->net, net);
4416-
set->ops = ops;
4417-
set->ktype = ktype;
4418-
set->klen = desc.klen;
4419-
set->dtype = dtype;
4420-
set->objtype = objtype;
4421-
set->dlen = desc.dlen;
4422-
set->flags = flags;
4423-
set->size = desc.size;
4424-
set->policy = policy;
4425-
set->udlen = udlen;
4426-
set->udata = udata;
4427-
set->timeout = timeout;
4428-
set->gc_int = gc_int;
44294438
set->handle = nf_tables_alloc_handle(table);
44304439

4431-
set->field_count = desc.field_count;
4432-
for (i = 0; i < desc.field_count; i++)
4433-
set->field_len[i] = desc.field_len[i];
4434-
4435-
err = ops->init(set, &desc, nla);
4436-
if (err < 0)
4437-
goto err_set_init;
4438-
44394440
err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
44404441
if (err < 0)
4441-
goto err_set_trans;
4442+
goto err_set_expr_alloc;
44424443

44434444
list_add_tail_rcu(&set->list, &table->sets);
44444445
table->use++;
44454446
return 0;
44464447

4447-
err_set_trans:
4448-
ops->destroy(set);
4449-
err_set_init:
4448+
err_set_expr_alloc:
44504449
for (i = 0; i < set->num_exprs; i++)
44514450
nft_expr_destroy(&ctx, set->exprs[i]);
4452-
err_set_alloc_name:
4451+
4452+
ops->destroy(set);
4453+
err_set_init:
44534454
kfree(set->name);
44544455
err_set_name:
44554456
kvfree(set);

0 commit comments

Comments
 (0)