netfilter: nf_tables: pass ctx to nf_tables_expr_destroy()
nft_set_elem_destroy() can be called from call_rcu context. Annotate netns and table in set object so we can populate the context object. Moreover, pass context object to nf_tables_set_elem_destroy() from the commit phase, since it is already available from there. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Родитель
5e5cbc7b23
Коммит
3453c92731
|
@ -370,6 +370,8 @@ void nft_unregister_set(struct nft_set_type *type);
|
||||||
*
|
*
|
||||||
* @list: table set list node
|
* @list: table set list node
|
||||||
* @bindings: list of set bindings
|
* @bindings: list of set bindings
|
||||||
|
* @table: table this set belongs to
|
||||||
|
* @net: netnamespace this set belongs to
|
||||||
* @name: name of the set
|
* @name: name of the set
|
||||||
* @handle: unique handle of the set
|
* @handle: unique handle of the set
|
||||||
* @ktype: key type (numeric type defined by userspace, not used in the kernel)
|
* @ktype: key type (numeric type defined by userspace, not used in the kernel)
|
||||||
|
@ -393,6 +395,8 @@ void nft_unregister_set(struct nft_set_type *type);
|
||||||
struct nft_set {
|
struct nft_set {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct list_head bindings;
|
struct list_head bindings;
|
||||||
|
struct nft_table *table;
|
||||||
|
possible_net_t net;
|
||||||
char *name;
|
char *name;
|
||||||
u64 handle;
|
u64 handle;
|
||||||
u32 ktype;
|
u32 ktype;
|
||||||
|
|
|
@ -3359,6 +3359,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_LIST_HEAD(&set->bindings);
|
INIT_LIST_HEAD(&set->bindings);
|
||||||
|
set->table = table;
|
||||||
|
write_pnet(&set->net, net);
|
||||||
set->ops = ops;
|
set->ops = ops;
|
||||||
set->ktype = ktype;
|
set->ktype = ktype;
|
||||||
set->klen = desc.klen;
|
set->klen = desc.klen;
|
||||||
|
@ -4036,12 +4038,16 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||||
bool destroy_expr)
|
bool destroy_expr)
|
||||||
{
|
{
|
||||||
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
||||||
|
struct nft_ctx ctx = {
|
||||||
|
.net = read_pnet(&set->net),
|
||||||
|
.family = set->table->family,
|
||||||
|
};
|
||||||
|
|
||||||
nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
|
nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
|
||||||
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
|
||||||
nft_data_release(nft_set_ext_data(ext), set->dtype);
|
nft_data_release(nft_set_ext_data(ext), set->dtype);
|
||||||
if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
|
if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
|
||||||
nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
|
nf_tables_expr_destroy(&ctx, nft_set_ext_expr(ext));
|
||||||
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
|
||||||
(*nft_set_ext_obj(ext))->use--;
|
(*nft_set_ext_obj(ext))->use--;
|
||||||
kfree(elem);
|
kfree(elem);
|
||||||
|
@ -4051,12 +4057,13 @@ EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
|
||||||
/* Only called from commit path, nft_set_elem_deactivate() already deals with
|
/* Only called from commit path, nft_set_elem_deactivate() already deals with
|
||||||
* the refcounting from the preparation phase.
|
* the refcounting from the preparation phase.
|
||||||
*/
|
*/
|
||||||
static void nf_tables_set_elem_destroy(const struct nft_set *set, void *elem)
|
static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||||
|
const struct nft_set *set, void *elem)
|
||||||
{
|
{
|
||||||
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
||||||
|
|
||||||
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
|
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
|
||||||
nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
|
nf_tables_expr_destroy(ctx, nft_set_ext_expr(ext));
|
||||||
kfree(elem);
|
kfree(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5999,7 +6006,8 @@ static void nft_commit_release(struct nft_trans *trans)
|
||||||
nft_set_destroy(nft_trans_set(trans));
|
nft_set_destroy(nft_trans_set(trans));
|
||||||
break;
|
break;
|
||||||
case NFT_MSG_DELSETELEM:
|
case NFT_MSG_DELSETELEM:
|
||||||
nf_tables_set_elem_destroy(nft_trans_elem_set(trans),
|
nf_tables_set_elem_destroy(&trans->ctx,
|
||||||
|
nft_trans_elem_set(trans),
|
||||||
nft_trans_elem(trans).priv);
|
nft_trans_elem(trans).priv);
|
||||||
break;
|
break;
|
||||||
case NFT_MSG_DELOBJ:
|
case NFT_MSG_DELOBJ:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче