Skip to content

Commit 9dad402

Browse files
committed
netfilter: nf_tables: expose opaque set element as struct nft_elem_priv
Add placeholder structure and place it at the beginning of each struct nft_*_elem for each existing set backend, instead of exposing elements as void type to the frontend which defeats compiler type checks. Use this pointer to this new type to replace void *. This patch updates the following set backend API to use this new struct nft_elem_priv placeholder structure: - update - deactivate - flush - get as well as the following helper functions: - nft_set_elem_ext() - nft_set_elem_init() - nft_set_elem_destroy() - nf_tables_set_elem_destroy() This patch adds nft_elem_priv_cast() to cast struct nft_elem_priv to native element representation from the corresponding set backend. BUILD_BUG_ON() makes sure this .priv placeholder is always at the top of the opaque set element representation. Suggested-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 6509a2e commit 9dad402

File tree

8 files changed

+173
-121
lines changed

8 files changed

+173
-121
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ struct nft_userdata {
274274
unsigned char data[];
275275
};
276276

277+
/* placeholder structure for opaque set element backend representation. */
278+
struct nft_elem_priv { };
279+
277280
/**
278281
* struct nft_set_elem - generic representation of set elements
279282
*
@@ -294,9 +297,14 @@ struct nft_set_elem {
294297
u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
295298
struct nft_data val;
296299
} data;
297-
void *priv;
300+
struct nft_elem_priv *priv;
298301
};
299302

303+
static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
304+
{
305+
return (void *)priv;
306+
}
307+
300308
struct nft_set;
301309
struct nft_set_iter {
302310
u8 genmask;
@@ -430,7 +438,8 @@ struct nft_set_ops {
430438
const struct nft_set_ext **ext);
431439
bool (*update)(struct nft_set *set,
432440
const u32 *key,
433-
void *(*new)(struct nft_set *,
441+
struct nft_elem_priv *
442+
(*new)(struct nft_set *,
434443
const struct nft_expr *,
435444
struct nft_regs *),
436445
const struct nft_expr *expr,
@@ -446,19 +455,19 @@ struct nft_set_ops {
446455
void (*activate)(const struct net *net,
447456
const struct nft_set *set,
448457
const struct nft_set_elem *elem);
449-
void * (*deactivate)(const struct net *net,
458+
struct nft_elem_priv * (*deactivate)(const struct net *net,
450459
const struct nft_set *set,
451460
const struct nft_set_elem *elem);
452461
void (*flush)(const struct net *net,
453462
const struct nft_set *set,
454-
void *priv);
463+
struct nft_elem_priv *priv);
455464
void (*remove)(const struct net *net,
456465
const struct nft_set *set,
457466
const struct nft_set_elem *elem);
458467
void (*walk)(const struct nft_ctx *ctx,
459468
struct nft_set *set,
460469
struct nft_set_iter *iter);
461-
void * (*get)(const struct net *net,
470+
struct nft_elem_priv * (*get)(const struct net *net,
462471
const struct nft_set *set,
463472
const struct nft_set_elem *elem,
464473
unsigned int flags);
@@ -796,9 +805,9 @@ static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
796805
}
797806

798807
static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
799-
void *elem)
808+
const struct nft_elem_priv *elem_priv)
800809
{
801-
return elem + set->ops->elemsize;
810+
return (void *)elem_priv + set->ops->elemsize;
802811
}
803812

804813
static inline struct nft_object **nft_set_ext_obj(const struct nft_set_ext *ext)
@@ -810,16 +819,19 @@ struct nft_expr *nft_set_elem_expr_alloc(const struct nft_ctx *ctx,
810819
const struct nft_set *set,
811820
const struct nlattr *attr);
812821

813-
void *nft_set_elem_init(const struct nft_set *set,
814-
const struct nft_set_ext_tmpl *tmpl,
815-
const u32 *key, const u32 *key_end, const u32 *data,
816-
u64 timeout, u64 expiration, gfp_t gfp);
822+
struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
823+
const struct nft_set_ext_tmpl *tmpl,
824+
const u32 *key, const u32 *key_end,
825+
const u32 *data,
826+
u64 timeout, u64 expiration, gfp_t gfp);
817827
int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
818828
struct nft_expr *expr_array[]);
819-
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
829+
void nft_set_elem_destroy(const struct nft_set *set,
830+
const struct nft_elem_priv *elem_priv,
820831
bool destroy_expr);
821832
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
822-
const struct nft_set *set, void *elem);
833+
const struct nft_set *set,
834+
const struct nft_elem_priv *elem_priv);
823835

824836
struct nft_expr_ops;
825837
/**

net/netfilter/nf_tables_api.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
601601
struct nft_set_elem_catchall {
602602
struct list_head list;
603603
struct rcu_head rcu;
604-
void *elem;
604+
struct nft_elem_priv *elem;
605605
};
606606

607607
static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
@@ -6218,10 +6218,11 @@ static int nft_set_ext_memcpy(const struct nft_set_ext_tmpl *tmpl, u8 id,
62186218
return 0;
62196219
}
62206220

6221-
void *nft_set_elem_init(const struct nft_set *set,
6222-
const struct nft_set_ext_tmpl *tmpl,
6223-
const u32 *key, const u32 *key_end,
6224-
const u32 *data, u64 timeout, u64 expiration, gfp_t gfp)
6221+
struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
6222+
const struct nft_set_ext_tmpl *tmpl,
6223+
const u32 *key, const u32 *key_end,
6224+
const u32 *data,
6225+
u64 timeout, u64 expiration, gfp_t gfp)
62256226
{
62266227
struct nft_set_ext *ext;
62276228
void *elem;
@@ -6286,10 +6287,11 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
62866287
}
62876288

62886289
/* Drop references and destroy. Called from gc, dynset and abort path. */
6289-
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
6290+
void nft_set_elem_destroy(const struct nft_set *set,
6291+
const struct nft_elem_priv *elem_priv,
62906292
bool destroy_expr)
62916293
{
6292-
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
6294+
struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
62936295
struct nft_ctx ctx = {
62946296
.net = read_pnet(&set->net),
62956297
.family = set->table->family,
@@ -6300,25 +6302,26 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
63006302
nft_data_release(nft_set_ext_data(ext), set->dtype);
63016303
if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
63026304
nft_set_elem_expr_destroy(&ctx, nft_set_ext_expr(ext));
6303-
63046305
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
63056306
nft_use_dec(&(*nft_set_ext_obj(ext))->use);
6306-
kfree(elem);
6307+
6308+
kfree(elem_priv);
63076309
}
63086310
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
63096311

63106312
/* Destroy element. References have been already dropped in the preparation
63116313
* path via nft_setelem_data_deactivate().
63126314
*/
63136315
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
6314-
const struct nft_set *set, void *elem)
6316+
const struct nft_set *set,
6317+
const struct nft_elem_priv *elem_priv)
63156318
{
6316-
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
6319+
struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
63176320

63186321
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
63196322
nft_set_elem_expr_destroy(ctx, nft_set_ext_expr(ext));
63206323

6321-
kfree(elem);
6324+
kfree(elem_priv);
63226325
}
63236326

63246327
int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,

net/netfilter/nft_dynset.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,34 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv,
4444
return 0;
4545
}
4646

47-
static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr,
48-
struct nft_regs *regs)
47+
static struct nft_elem_priv *nft_dynset_new(struct nft_set *set,
48+
const struct nft_expr *expr,
49+
struct nft_regs *regs)
4950
{
5051
const struct nft_dynset *priv = nft_expr_priv(expr);
5152
struct nft_set_ext *ext;
53+
void *elem_priv;
5254
u64 timeout;
53-
void *elem;
5455

5556
if (!atomic_add_unless(&set->nelems, 1, set->size))
5657
return NULL;
5758

5859
timeout = priv->timeout ? : set->timeout;
59-
elem = nft_set_elem_init(set, &priv->tmpl,
60-
&regs->data[priv->sreg_key], NULL,
61-
&regs->data[priv->sreg_data],
62-
timeout, 0, GFP_ATOMIC);
63-
if (IS_ERR(elem))
60+
elem_priv = nft_set_elem_init(set, &priv->tmpl,
61+
&regs->data[priv->sreg_key], NULL,
62+
&regs->data[priv->sreg_data],
63+
timeout, 0, GFP_ATOMIC);
64+
if (IS_ERR(elem_priv))
6465
goto err1;
6566

66-
ext = nft_set_elem_ext(set, elem);
67+
ext = nft_set_elem_ext(set, elem_priv);
6768
if (priv->num_exprs && nft_dynset_expr_setup(priv, ext) < 0)
6869
goto err2;
6970

70-
return elem;
71+
return elem_priv;
7172

7273
err2:
73-
nft_set_elem_destroy(set, elem, false);
74+
nft_set_elem_destroy(set, elem_priv, false);
7475
err1:
7576
if (set->size)
7677
atomic_dec(&set->nelems);

net/netfilter/nft_set_bitmap.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <net/netfilter/nf_tables_core.h>
1414

1515
struct nft_bitmap_elem {
16+
struct nft_elem_priv priv;
1617
struct list_head head;
1718
struct nft_set_ext ext;
1819
};
@@ -104,8 +105,9 @@ nft_bitmap_elem_find(const struct nft_set *set, struct nft_bitmap_elem *this,
104105
return NULL;
105106
}
106107

107-
static void *nft_bitmap_get(const struct net *net, const struct nft_set *set,
108-
const struct nft_set_elem *elem, unsigned int flags)
108+
static struct nft_elem_priv *
109+
nft_bitmap_get(const struct net *net, const struct nft_set *set,
110+
const struct nft_set_elem *elem, unsigned int flags)
109111
{
110112
const struct nft_bitmap *priv = nft_set_priv(set);
111113
u8 genmask = nft_genmask_cur(net);
@@ -116,7 +118,7 @@ static void *nft_bitmap_get(const struct net *net, const struct nft_set *set,
116118
!nft_set_elem_active(&be->ext, genmask))
117119
continue;
118120

119-
return be;
121+
return &be->priv;
120122
}
121123
return ERR_PTR(-ENOENT);
122124
}
@@ -125,8 +127,8 @@ static int nft_bitmap_insert(const struct net *net, const struct nft_set *set,
125127
const struct nft_set_elem *elem,
126128
struct nft_set_ext **ext)
127129
{
130+
struct nft_bitmap_elem *new = nft_elem_priv_cast(elem->priv), *be;
128131
struct nft_bitmap *priv = nft_set_priv(set);
129-
struct nft_bitmap_elem *new = elem->priv, *be;
130132
u8 genmask = nft_genmask_next(net);
131133
u32 idx, off;
132134

@@ -148,8 +150,8 @@ static void nft_bitmap_remove(const struct net *net,
148150
const struct nft_set *set,
149151
const struct nft_set_elem *elem)
150152
{
153+
struct nft_bitmap_elem *be = nft_elem_priv_cast(elem->priv);
151154
struct nft_bitmap *priv = nft_set_priv(set);
152-
struct nft_bitmap_elem *be = elem->priv;
153155
u8 genmask = nft_genmask_next(net);
154156
u32 idx, off;
155157

@@ -163,8 +165,8 @@ static void nft_bitmap_activate(const struct net *net,
163165
const struct nft_set *set,
164166
const struct nft_set_elem *elem)
165167
{
168+
struct nft_bitmap_elem *be = nft_elem_priv_cast(elem->priv);
166169
struct nft_bitmap *priv = nft_set_priv(set);
167-
struct nft_bitmap_elem *be = elem->priv;
168170
u8 genmask = nft_genmask_next(net);
169171
u32 idx, off;
170172

@@ -175,11 +177,12 @@ static void nft_bitmap_activate(const struct net *net,
175177
}
176178

177179
static void nft_bitmap_flush(const struct net *net,
178-
const struct nft_set *set, void *_be)
180+
const struct nft_set *set,
181+
struct nft_elem_priv *elem_priv)
179182
{
183+
struct nft_bitmap_elem *be = nft_elem_priv_cast(elem_priv);
180184
struct nft_bitmap *priv = nft_set_priv(set);
181185
u8 genmask = nft_genmask_next(net);
182-
struct nft_bitmap_elem *be = _be;
183186
u32 idx, off;
184187

185188
nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
@@ -188,12 +191,12 @@ static void nft_bitmap_flush(const struct net *net,
188191
nft_set_elem_change_active(net, set, &be->ext);
189192
}
190193

191-
static void *nft_bitmap_deactivate(const struct net *net,
192-
const struct nft_set *set,
193-
const struct nft_set_elem *elem)
194+
static struct nft_elem_priv *
195+
nft_bitmap_deactivate(const struct net *net, const struct nft_set *set,
196+
const struct nft_set_elem *elem)
194197
{
198+
struct nft_bitmap_elem *this = nft_elem_priv_cast(elem->priv), *be;
195199
struct nft_bitmap *priv = nft_set_priv(set);
196-
struct nft_bitmap_elem *this = elem->priv, *be;
197200
u8 genmask = nft_genmask_next(net);
198201
u32 idx, off;
199202

@@ -207,7 +210,7 @@ static void *nft_bitmap_deactivate(const struct net *net,
207210
priv->bitmap[idx] &= ~(genmask << off);
208211
nft_set_elem_change_active(net, set, &be->ext);
209212

210-
return be;
213+
return &be->priv;
211214
}
212215

213216
static void nft_bitmap_walk(const struct nft_ctx *ctx,
@@ -224,7 +227,7 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
224227
if (!nft_set_elem_active(&be->ext, iter->genmask))
225228
goto cont;
226229

227-
elem.priv = be;
230+
elem.priv = &be->priv;
228231

229232
iter->err = iter->fn(ctx, set, iter, &elem);
230233

@@ -263,6 +266,8 @@ static int nft_bitmap_init(const struct nft_set *set,
263266
{
264267
struct nft_bitmap *priv = nft_set_priv(set);
265268

269+
BUILD_BUG_ON(offsetof(struct nft_bitmap_elem, priv) != 0);
270+
266271
INIT_LIST_HEAD(&priv->list);
267272
priv->bitmap_size = nft_bitmap_size(set->klen);
268273

@@ -276,7 +281,7 @@ static void nft_bitmap_destroy(const struct nft_ctx *ctx,
276281
struct nft_bitmap_elem *be, *n;
277282

278283
list_for_each_entry_safe(be, n, &priv->list, head)
279-
nf_tables_set_elem_destroy(ctx, set, be);
284+
nf_tables_set_elem_destroy(ctx, set, &be->priv);
280285
}
281286

282287
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,

0 commit comments

Comments
 (0)