Commit e5e61a27 authored by Rusty Russell's avatar Rusty Russell Committed by David S. Miller

[PKT_SCHED]: Restore net/sched/ipt.c After iptables Kmod Cleanup

Thomas Graf points out that I broke net/sched/ipt.c when I removed
__ipt_find_target_lock.  In fact, those routines don't need to keep
the lock held, so we can simplify them, and expose an interface
(ipt_find_target) which does module loading correctly for
net/sched/ipt.c.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5aae0d22
...@@ -456,6 +456,9 @@ struct ipt_table ...@@ -456,6 +456,9 @@ struct ipt_table
struct module *me; struct module *me;
}; };
/* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */
extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
extern int ipt_register_table(struct ipt_table *table); extern int ipt_register_table(struct ipt_table *table);
extern void ipt_unregister_table(struct ipt_table *table); extern void ipt_unregister_table(struct ipt_table *table);
extern unsigned int ipt_do_table(struct sk_buff **pskb, extern unsigned int ipt_do_table(struct sk_buff **pskb,
......
...@@ -430,62 +430,63 @@ static inline struct ipt_table *find_table_lock(const char *name) ...@@ -430,62 +430,63 @@ static inline struct ipt_table *find_table_lock(const char *name)
return NULL; return NULL;
} }
/* Find match, grabs mutex & ref. Returns ERR_PTR() on error. */ /* Find match, grabs ref. Returns ERR_PTR() on error. */
static inline struct ipt_match *find_match_lock(const char *name, u8 revision) static inline struct ipt_match *find_match(const char *name, u8 revision)
{ {
struct ipt_match *m; struct ipt_match *m;
int found = 0; int err = 0;
if (down_interruptible(&ipt_mutex) != 0) if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR); return ERR_PTR(-EINTR);
list_for_each_entry(m, &ipt_match, list) { list_for_each_entry(m, &ipt_match, list) {
if (strcmp(m->name, name) == 0) { if (strcmp(m->name, name) == 0) {
found = 1;
if (m->revision == revision) { if (m->revision == revision) {
if (!try_module_get(m->me)) if (try_module_get(m->me)) {
found = 0; up(&ipt_mutex);
else
return m; return m;
} }
} else
err = -EPROTOTYPE; /* Found something. */
} }
} }
up(&ipt_mutex); up(&ipt_mutex);
return ERR_PTR(err);
/* Not found at all? NULL so try_then_request_module loads module. */
if (!found)
return NULL;
return ERR_PTR(-EPROTOTYPE);
} }
/* Find target, grabs mutex & ref. Returns ERR_PTR() on error. */ /* Find target, grabs ref. Returns ERR_PTR() on error. */
static inline struct ipt_target *find_target_lock(const char *name, u8 revision) static inline struct ipt_target *find_target(const char *name, u8 revision)
{ {
struct ipt_target *t; struct ipt_target *t;
int found = 0; int err = 0;
if (down_interruptible(&ipt_mutex) != 0) if (down_interruptible(&ipt_mutex) != 0)
return ERR_PTR(-EINTR); return ERR_PTR(-EINTR);
list_for_each_entry(t, &ipt_target, list) { list_for_each_entry(t, &ipt_target, list) {
if (strcmp(t->name, name) == 0) { if (strcmp(t->name, name) == 0) {
found = 1;
if (t->revision == revision) { if (t->revision == revision) {
if (!try_module_get(t->me)) if (try_module_get(t->me)) {
found = 0; up(&ipt_mutex);
else
return t; return t;
} }
} else
err = -EPROTOTYPE; /* Found something. */
} }
} }
up(&ipt_mutex); up(&ipt_mutex);
return ERR_PTR(err);
}
/* Not found at all? NULL so try_then_request_module loads module. */ struct ipt_target *ipt_find_target(const char *name, u8 revision)
if (!found) {
return NULL; struct ipt_target *target;
return ERR_PTR(-EPROTOTYPE); target = try_then_request_module(find_target(name, revision),
"ipt_%s", name);
if (IS_ERR(target) || !target)
return NULL;
return target;
} }
static int match_revfn(const char *name, u8 revision, int *bestp) static int match_revfn(const char *name, u8 revision, int *bestp)
...@@ -708,7 +709,7 @@ check_match(struct ipt_entry_match *m, ...@@ -708,7 +709,7 @@ check_match(struct ipt_entry_match *m,
{ {
struct ipt_match *match; struct ipt_match *match;
match = try_then_request_module(find_match_lock(m->u.user.name, match = try_then_request_module(find_match(m->u.user.name,
m->u.user.revision), m->u.user.revision),
"ipt_%s", m->u.user.name); "ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) { if (IS_ERR(match) || !match) {
...@@ -716,7 +717,6 @@ check_match(struct ipt_entry_match *m, ...@@ -716,7 +717,6 @@ check_match(struct ipt_entry_match *m,
return match ? PTR_ERR(match) : -ENOENT; return match ? PTR_ERR(match) : -ENOENT;
} }
m->u.kernel.match = match; m->u.kernel.match = match;
up(&ipt_mutex);
if (m->u.kernel.match->checkentry if (m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, m->data, && !m->u.kernel.match->checkentry(name, ip, m->data,
...@@ -754,7 +754,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, ...@@ -754,7 +754,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches; goto cleanup_matches;
t = ipt_get_target(e); t = ipt_get_target(e);
target = try_then_request_module(find_target_lock(t->u.user.name, target = try_then_request_module(find_target(t->u.user.name,
t->u.user.revision), t->u.user.revision),
"ipt_%s", t->u.user.name); "ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) { if (IS_ERR(target) || !target) {
...@@ -763,7 +763,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, ...@@ -763,7 +763,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches; goto cleanup_matches;
} }
t->u.kernel.target = target; t->u.kernel.target = target;
up(&ipt_mutex);
if (t->u.kernel.target == &ipt_standard_target) { if (t->u.kernel.target == &ipt_standard_target) {
if (!standard_check(t, size)) { if (!standard_check(t, size)) {
...@@ -1959,6 +1958,7 @@ EXPORT_SYMBOL(ipt_unregister_match); ...@@ -1959,6 +1958,7 @@ EXPORT_SYMBOL(ipt_unregister_match);
EXPORT_SYMBOL(ipt_do_table); EXPORT_SYMBOL(ipt_do_table);
EXPORT_SYMBOL(ipt_register_target); EXPORT_SYMBOL(ipt_register_target);
EXPORT_SYMBOL(ipt_unregister_target); EXPORT_SYMBOL(ipt_unregister_target);
EXPORT_SYMBOL(ipt_find_target);
module_init(init); module_init(init);
module_exit(fini); module_exit(fini);
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/kmod.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <linux/tc_act/tc_ipt.h> #include <linux/tc_act/tc_ipt.h>
...@@ -60,32 +61,23 @@ init_targ(struct tcf_ipt *p) ...@@ -60,32 +61,23 @@ init_targ(struct tcf_ipt *p)
struct ipt_target *target; struct ipt_target *target;
int ret = 0; int ret = 0;
struct ipt_entry_target *t = p->t; struct ipt_entry_target *t = p->t;
target = __ipt_find_target_lock(t->u.user.name, &ret);
target = ipt_find_target(t->u.user.name, t->u.user.revision);
if (!target) { if (!target) {
printk("init_targ: Failed to find %s\n", t->u.user.name); printk("init_targ: Failed to find %s\n", t->u.user.name);
return -1; return -1;
} }
DPRINTK("init_targ: found %s\n", target->name); DPRINTK("init_targ: found %s\n", target->name);
/* we really need proper ref counting
seems to be only needed for modules?? Talk to laforge */
/* if (target->me)
__MOD_INC_USE_COUNT(target->me);
*/
t->u.kernel.target = target; t->u.kernel.target = target;
__ipt_mutex_up();
if (t->u.kernel.target->checkentry if (t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(p->tname, NULL, t->data, && !t->u.kernel.target->checkentry(p->tname, NULL, t->data,
t->u.target_size t->u.target_size
- sizeof (*t), p->hook)) { - sizeof (*t), p->hook)) {
/* if (t->u.kernel.target->me)
__MOD_DEC_USE_COUNT(t->u.kernel.target->me);
*/
DPRINTK("ip_tables: check failed for `%s'.\n", DPRINTK("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name); t->u.kernel.target->name);
module_put(t->u.kernel.target->me);
ret = -EINVAL; ret = -EINVAL;
} }
...@@ -235,8 +227,12 @@ tcf_ipt_cleanup(struct tc_action *a, int bind) ...@@ -235,8 +227,12 @@ tcf_ipt_cleanup(struct tc_action *a, int bind)
{ {
struct tcf_ipt *p; struct tcf_ipt *p;
p = PRIV(a,ipt); p = PRIV(a,ipt);
if (NULL != p) if (NULL != p) {
struct ipt_entry_target *t = p->t;
if (t && t->u.kernel.target)
module_put(t->u.kernel.target->me);
return tcf_hash_release(p, bind); return tcf_hash_release(p, bind);
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment