Skip to content

Commit 06cad3a

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: core: export raw versions of add/delete hook functions
This will allow the nat core to reuse the nf_hook infrastructure to maintain nat lookup functions. The raw versions don't assume a particular hook location, the functions get added/deleted from the hook blob that is passed to the functions. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 4e25ceb commit 06cad3a

File tree

2 files changed

+59
-21
lines changed

2 files changed

+59
-21
lines changed

net/netfilter/core.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,31 @@ static void hooks_validate(const struct nf_hook_entries *hooks)
186186
#endif
187187
}
188188

189+
int nf_hook_entries_insert_raw(struct nf_hook_entries __rcu **pp,
190+
const struct nf_hook_ops *reg)
191+
{
192+
struct nf_hook_entries *new_hooks;
193+
struct nf_hook_entries *p;
194+
195+
p = rcu_dereference_raw(*pp);
196+
new_hooks = nf_hook_entries_grow(p, reg);
197+
if (IS_ERR(new_hooks))
198+
return PTR_ERR(new_hooks);
199+
200+
hooks_validate(new_hooks);
201+
202+
rcu_assign_pointer(*pp, new_hooks);
203+
204+
BUG_ON(p == new_hooks);
205+
nf_hook_entries_free(p);
206+
return 0;
207+
}
208+
EXPORT_SYMBOL_GPL(nf_hook_entries_insert_raw);
209+
189210
/*
190211
* __nf_hook_entries_try_shrink - try to shrink hook array
191212
*
213+
* @old -- current hook blob at @pp
192214
* @pp -- location of hook blob
193215
*
194216
* Hook unregistration must always succeed, so to-be-removed hooks
@@ -201,14 +223,14 @@ static void hooks_validate(const struct nf_hook_entries *hooks)
201223
*
202224
* Returns address to free, or NULL.
203225
*/
204-
static void *__nf_hook_entries_try_shrink(struct nf_hook_entries __rcu **pp)
226+
static void *__nf_hook_entries_try_shrink(struct nf_hook_entries *old,
227+
struct nf_hook_entries __rcu **pp)
205228
{
206-
struct nf_hook_entries *old, *new = NULL;
207229
unsigned int i, j, skip = 0, hook_entries;
230+
struct nf_hook_entries *new = NULL;
208231
struct nf_hook_ops **orig_ops;
209232
struct nf_hook_ops **new_ops;
210233

211-
old = nf_entry_dereference(*pp);
212234
if (WARN_ON_ONCE(!old))
213235
return NULL;
214236

@@ -347,11 +369,10 @@ static int __nf_register_net_hook(struct net *net, int pf,
347369
* This cannot fail, hook unregistration must always succeed.
348370
* Therefore replace the to-be-removed hook with a dummy hook.
349371
*/
350-
static void nf_remove_net_hook(struct nf_hook_entries *old,
351-
const struct nf_hook_ops *unreg, int pf)
372+
static bool nf_remove_net_hook(struct nf_hook_entries *old,
373+
const struct nf_hook_ops *unreg)
352374
{
353375
struct nf_hook_ops **orig_ops;
354-
bool found = false;
355376
unsigned int i;
356377

357378
orig_ops = nf_hook_entries_get_hook_ops(old);
@@ -360,21 +381,10 @@ static void nf_remove_net_hook(struct nf_hook_entries *old,
360381
continue;
361382
WRITE_ONCE(old->hooks[i].hook, accept_all);
362383
WRITE_ONCE(orig_ops[i], &dummy_ops);
363-
found = true;
364-
break;
384+
return true;
365385
}
366386

367-
if (found) {
368-
#ifdef CONFIG_NETFILTER_INGRESS
369-
if (pf == NFPROTO_NETDEV && unreg->hooknum == NF_NETDEV_INGRESS)
370-
net_dec_ingress_queue();
371-
#endif
372-
#ifdef HAVE_JUMP_LABEL
373-
static_key_slow_dec(&nf_hooks_needed[pf][unreg->hooknum]);
374-
#endif
375-
} else {
376-
WARN_ONCE(1, "hook not found, pf %d num %d", pf, unreg->hooknum);
377-
}
387+
return false;
378388
}
379389

380390
static void __nf_unregister_net_hook(struct net *net, int pf,
@@ -395,9 +405,19 @@ static void __nf_unregister_net_hook(struct net *net, int pf,
395405
return;
396406
}
397407

398-
nf_remove_net_hook(p, reg, pf);
408+
if (nf_remove_net_hook(p, reg)) {
409+
#ifdef CONFIG_NETFILTER_INGRESS
410+
if (pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
411+
net_dec_ingress_queue();
412+
#endif
413+
#ifdef HAVE_JUMP_LABEL
414+
static_key_slow_dec(&nf_hooks_needed[pf][reg->hooknum]);
415+
#endif
416+
} else {
417+
WARN_ONCE(1, "hook not found, pf %d num %d", pf, reg->hooknum);
418+
}
399419

400-
p = __nf_hook_entries_try_shrink(pp);
420+
p = __nf_hook_entries_try_shrink(p, pp);
401421
mutex_unlock(&nf_hook_mutex);
402422
if (!p)
403423
return;
@@ -417,6 +437,19 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
417437
}
418438
EXPORT_SYMBOL(nf_unregister_net_hook);
419439

440+
void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp,
441+
const struct nf_hook_ops *reg)
442+
{
443+
struct nf_hook_entries *p;
444+
445+
p = rcu_dereference_raw(*pp);
446+
if (nf_remove_net_hook(p, reg)) {
447+
p = __nf_hook_entries_try_shrink(p, pp);
448+
nf_hook_entries_free(p);
449+
}
450+
}
451+
EXPORT_SYMBOL_GPL(nf_hook_entries_delete_raw);
452+
420453
int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
421454
{
422455
int err;

net/netfilter/nf_internals.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ void nf_queue_nf_hook_drop(struct net *net);
1515
/* nf_log.c */
1616
int __init netfilter_log_init(void);
1717

18+
/* core.c */
19+
void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp,
20+
const struct nf_hook_ops *reg);
21+
int nf_hook_entries_insert_raw(struct nf_hook_entries __rcu **pp,
22+
const struct nf_hook_ops *reg);
1823
#endif

0 commit comments

Comments
 (0)