diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-08-01 13:32:41 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-08-08 09:38:46 -0400 |
commit | a3716e70e1def691ad39e0f908fea0870ce010d9 (patch) | |
tree | 1d263f1e8ac0c42bbfb259dea32111ae6bf34280 /net | |
parent | 33caee39925b887a99a2400dc5c980097c3573f9 (diff) |
netfilter: nf_tables: uninitialize element key/data from the commit path
This should happen once the element has been effectively released in
the commit path, not before. This fixes a possible chain refcount leak
if the transaction is aborted.
Reported-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_tables_api.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index b8035c2d6667..c6f9d3d18ed1 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -3139,11 +3139,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | |||
3139 | 3139 | ||
3140 | nft_trans_elem(trans) = elem; | 3140 | nft_trans_elem(trans) = elem; |
3141 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 3141 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
3142 | |||
3143 | nft_data_uninit(&elem.key, NFT_DATA_VALUE); | ||
3144 | if (set->flags & NFT_SET_MAP) | ||
3145 | nft_data_uninit(&elem.data, set->dtype); | ||
3146 | |||
3147 | return 0; | 3142 | return 0; |
3148 | err2: | 3143 | err2: |
3149 | nft_data_uninit(&elem.key, desc.type); | 3144 | nft_data_uninit(&elem.key, desc.type); |
@@ -3310,7 +3305,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3310 | { | 3305 | { |
3311 | struct net *net = sock_net(skb->sk); | 3306 | struct net *net = sock_net(skb->sk); |
3312 | struct nft_trans *trans, *next; | 3307 | struct nft_trans *trans, *next; |
3313 | struct nft_set *set; | 3308 | struct nft_trans_elem *te; |
3314 | 3309 | ||
3315 | /* Bump generation counter, invalidate any dump in progress */ | 3310 | /* Bump generation counter, invalidate any dump in progress */ |
3316 | while (++net->nft.base_seq == 0); | 3311 | while (++net->nft.base_seq == 0); |
@@ -3396,13 +3391,17 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3396 | nft_trans_destroy(trans); | 3391 | nft_trans_destroy(trans); |
3397 | break; | 3392 | break; |
3398 | case NFT_MSG_DELSETELEM: | 3393 | case NFT_MSG_DELSETELEM: |
3399 | nf_tables_setelem_notify(&trans->ctx, | 3394 | te = (struct nft_trans_elem *)trans->data; |
3400 | nft_trans_elem_set(trans), | 3395 | nf_tables_setelem_notify(&trans->ctx, te->set, |
3401 | &nft_trans_elem(trans), | 3396 | &te->elem, |
3402 | NFT_MSG_DELSETELEM, 0); | 3397 | NFT_MSG_DELSETELEM, 0); |
3403 | set = nft_trans_elem_set(trans); | 3398 | te->set->ops->get(te->set, &te->elem); |
3404 | set->ops->get(set, &nft_trans_elem(trans)); | 3399 | te->set->ops->remove(te->set, &te->elem); |
3405 | set->ops->remove(set, &nft_trans_elem(trans)); | 3400 | nft_data_uninit(&te->elem.key, NFT_DATA_VALUE); |
3401 | if (te->elem.flags & NFT_SET_MAP) { | ||
3402 | nft_data_uninit(&te->elem.data, | ||
3403 | te->set->dtype); | ||
3404 | } | ||
3406 | nft_trans_destroy(trans); | 3405 | nft_trans_destroy(trans); |
3407 | break; | 3406 | break; |
3408 | } | 3407 | } |