Commit 916a917d authored by Jan Engelhardt's avatar Jan Engelhardt Committed by Patrick McHardy

netfilter: xtables: provide invoked family value to extensions

By passing in the family through which extensions were invoked, a bit
of data space can be reclaimed. The "family" member will be added to
the parameter structures and the check functions be adjusted.
Signed-off-by: default avatarJan Engelhardt <jengelh@medozas.de>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent a2df1648
...@@ -183,6 +183,8 @@ struct xt_counters_info ...@@ -183,6 +183,8 @@ struct xt_counters_info
* @fragoff: packet is a fragment, this is the data offset * @fragoff: packet is a fragment, this is the data offset
* @thoff: position of transport header relative to skb->data * @thoff: position of transport header relative to skb->data
* @hotdrop: drop packet if we had inspection problems * @hotdrop: drop packet if we had inspection problems
* @family: Actual NFPROTO_* through which the function is invoked
* (helpful when match->family == NFPROTO_UNSPEC)
*/ */
struct xt_match_param { struct xt_match_param {
const struct net_device *in, *out; const struct net_device *in, *out;
...@@ -191,6 +193,7 @@ struct xt_match_param { ...@@ -191,6 +193,7 @@ struct xt_match_param {
int fragoff; int fragoff;
unsigned int thoff; unsigned int thoff;
bool *hotdrop; bool *hotdrop;
u_int8_t family;
}; };
/** /**
...@@ -210,12 +213,14 @@ struct xt_mtchk_param { ...@@ -210,12 +213,14 @@ struct xt_mtchk_param {
const struct xt_match *match; const struct xt_match *match;
void *matchinfo; void *matchinfo;
unsigned int hook_mask; unsigned int hook_mask;
u_int8_t family;
}; };
/* Match destructor parameters */ /* Match destructor parameters */
struct xt_mtdtor_param { struct xt_mtdtor_param {
const struct xt_match *match; const struct xt_match *match;
void *matchinfo; void *matchinfo;
u_int8_t family;
}; };
/** /**
...@@ -232,6 +237,7 @@ struct xt_target_param { ...@@ -232,6 +237,7 @@ struct xt_target_param {
unsigned int hooknum; unsigned int hooknum;
const struct xt_target *target; const struct xt_target *target;
const void *targinfo; const void *targinfo;
u_int8_t family;
}; };
/** /**
...@@ -249,12 +255,14 @@ struct xt_tgchk_param { ...@@ -249,12 +255,14 @@ struct xt_tgchk_param {
const struct xt_target *target; const struct xt_target *target;
void *targinfo; void *targinfo;
unsigned int hook_mask; unsigned int hook_mask;
u_int8_t family;
}; };
/* Target destructor parameters */ /* Target destructor parameters */
struct xt_tgdtor_param { struct xt_tgdtor_param {
const struct xt_target *target; const struct xt_target *target;
void *targinfo; void *targinfo;
u_int8_t family;
}; };
struct xt_match struct xt_match
...@@ -393,9 +401,9 @@ extern void xt_unregister_match(struct xt_match *target); ...@@ -393,9 +401,9 @@ extern void xt_unregister_match(struct xt_match *target);
extern int xt_register_matches(struct xt_match *match, unsigned int n); extern int xt_register_matches(struct xt_match *match, unsigned int n);
extern void xt_unregister_matches(struct xt_match *match, unsigned int n); extern void xt_unregister_matches(struct xt_match *match, unsigned int n);
extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family, extern int xt_check_match(struct xt_mtchk_param *,
unsigned int size, u_int8_t proto, bool inv_proto); unsigned int size, u_int8_t proto, bool inv_proto);
extern int xt_check_target(struct xt_tgchk_param *, u_int8_t family, extern int xt_check_target(struct xt_tgchk_param *,
unsigned int size, u_int8_t proto, bool inv_proto); unsigned int size, u_int8_t proto, bool inv_proto);
extern struct xt_table *xt_register_table(struct net *net, extern struct xt_table *xt_register_table(struct net *net,
......
...@@ -160,6 +160,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, ...@@ -160,6 +160,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
struct xt_match_param mtpar; struct xt_match_param mtpar;
struct xt_target_param tgpar; struct xt_target_param tgpar;
mtpar.family = tgpar.family = NFPROTO_BRIDGE;
mtpar.in = tgpar.in = in; mtpar.in = tgpar.in = in;
mtpar.out = tgpar.out = out; mtpar.out = tgpar.out = out;
mtpar.hotdrop = &hotdrop; mtpar.hotdrop = &hotdrop;
...@@ -351,7 +352,7 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par, ...@@ -351,7 +352,7 @@ ebt_check_match(struct ebt_entry_match *m, struct xt_mtchk_param *par,
par->match = match; par->match = match;
par->matchinfo = m->data; par->matchinfo = m->data;
ret = xt_check_match(par, NFPROTO_BRIDGE, m->match_size, ret = xt_check_match(par, m->match_size,
e->ethproto, e->invflags & EBT_IPROTO); e->ethproto, e->invflags & EBT_IPROTO);
if (ret < 0) { if (ret < 0) {
module_put(match->me); module_put(match->me);
...@@ -386,7 +387,7 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, ...@@ -386,7 +387,7 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
par->target = watcher; par->target = watcher;
par->targinfo = w->data; par->targinfo = w->data;
ret = xt_check_target(par, NFPROTO_BRIDGE, w->watcher_size, ret = xt_check_target(par, w->watcher_size,
e->ethproto, e->invflags & EBT_IPROTO); e->ethproto, e->invflags & EBT_IPROTO);
if (ret < 0) { if (ret < 0) {
module_put(watcher->me); module_put(watcher->me);
...@@ -572,6 +573,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i) ...@@ -572,6 +573,7 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
par.match = m->u.match; par.match = m->u.match;
par.matchinfo = m->data; par.matchinfo = m->data;
par.family = NFPROTO_BRIDGE;
if (par.match->destroy != NULL) if (par.match->destroy != NULL)
par.match->destroy(&par); par.match->destroy(&par);
module_put(par.match->me); module_put(par.match->me);
...@@ -588,6 +590,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) ...@@ -588,6 +590,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
par.target = w->u.watcher; par.target = w->u.watcher;
par.targinfo = w->data; par.targinfo = w->data;
par.family = NFPROTO_BRIDGE;
if (par.target->destroy != NULL) if (par.target->destroy != NULL)
par.target->destroy(&par); par.target->destroy(&par);
module_put(par.target->me); module_put(par.target->me);
...@@ -611,6 +614,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) ...@@ -611,6 +614,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
par.target = t->u.target; par.target = t->u.target;
par.targinfo = t->data; par.targinfo = t->data;
par.family = NFPROTO_BRIDGE;
if (par.target->destroy != NULL) if (par.target->destroy != NULL)
par.target->destroy(&par); par.target->destroy(&par);
module_put(par.target->me); module_put(par.target->me);
...@@ -673,6 +677,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -673,6 +677,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
mtpar.table = tgpar.table = name; mtpar.table = tgpar.table = name;
mtpar.entryinfo = tgpar.entryinfo = e; mtpar.entryinfo = tgpar.entryinfo = e;
mtpar.hook_mask = tgpar.hook_mask = hookmask; mtpar.hook_mask = tgpar.hook_mask = hookmask;
mtpar.family = tgpar.family = NFPROTO_BRIDGE;
ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i); ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i);
if (ret != 0) if (ret != 0)
goto cleanup_matches; goto cleanup_matches;
...@@ -715,7 +720,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, ...@@ -715,7 +720,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
tgpar.target = target; tgpar.target = target;
tgpar.targinfo = t->data; tgpar.targinfo = t->data;
ret = xt_check_target(&tgpar, NFPROTO_BRIDGE, t->target_size, ret = xt_check_target(&tgpar, t->target_size,
e->ethproto, e->invflags & EBT_IPROTO); e->ethproto, e->invflags & EBT_IPROTO);
if (ret < 0) { if (ret < 0) {
module_put(target->me); module_put(target->me);
......
...@@ -246,6 +246,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, ...@@ -246,6 +246,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
tgpar.in = in; tgpar.in = in;
tgpar.out = out; tgpar.out = out;
tgpar.hooknum = hook; tgpar.hooknum = hook;
tgpar.family = NFPROTO_ARP;
arp = arp_hdr(skb); arp = arp_hdr(skb);
do { do {
...@@ -465,10 +466,10 @@ static inline int check_target(struct arpt_entry *e, const char *name) ...@@ -465,10 +466,10 @@ static inline int check_target(struct arpt_entry *e, const char *name)
.target = t->u.kernel.target, .target = t->u.kernel.target,
.targinfo = t->data, .targinfo = t->data,
.hook_mask = e->comefrom, .hook_mask = e->comefrom,
.family = NFPROTO_ARP,
}; };
ret = xt_check_target(&par, NFPROTO_ARP, ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
t->u.target_size - sizeof(*t), 0, false);
if (ret < 0) { if (ret < 0) {
duprintf("arp_tables: check failed for `%s'.\n", duprintf("arp_tables: check failed for `%s'.\n",
t->u.kernel.target->name); t->u.kernel.target->name);
...@@ -566,6 +567,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) ...@@ -566,6 +567,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
t = arpt_get_target(e); t = arpt_get_target(e);
par.target = t->u.kernel.target; par.target = t->u.kernel.target;
par.targinfo = t->data; par.targinfo = t->data;
par.family = NFPROTO_ARP;
if (par.target->destroy != NULL) if (par.target->destroy != NULL)
par.target->destroy(&par); par.target->destroy(&par);
module_put(par.target->me); module_put(par.target->me);
......
...@@ -348,6 +348,7 @@ ipt_do_table(struct sk_buff *skb, ...@@ -348,6 +348,7 @@ ipt_do_table(struct sk_buff *skb,
mtpar.hotdrop = &hotdrop; mtpar.hotdrop = &hotdrop;
mtpar.in = tgpar.in = in; mtpar.in = tgpar.in = in;
mtpar.out = tgpar.out = out; mtpar.out = tgpar.out = out;
mtpar.family = tgpar.family = NFPROTO_IPV4;
tgpar.hooknum = hook; tgpar.hooknum = hook;
read_lock_bh(&table->lock); read_lock_bh(&table->lock);
...@@ -579,6 +580,7 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i) ...@@ -579,6 +580,7 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
par.match = m->u.kernel.match; par.match = m->u.kernel.match;
par.matchinfo = m->data; par.matchinfo = m->data;
par.family = NFPROTO_IPV4;
if (par.match->destroy != NULL) if (par.match->destroy != NULL)
par.match->destroy(&par); par.match->destroy(&par);
module_put(par.match->me); module_put(par.match->me);
...@@ -616,7 +618,7 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, ...@@ -616,7 +618,7 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,
par->match = m->u.kernel.match; par->match = m->u.kernel.match;
par->matchinfo = m->data; par->matchinfo = m->data;
ret = xt_check_match(par, NFPROTO_IPV4, m->u.match_size - sizeof(*m), ret = xt_check_match(par, m->u.match_size - sizeof(*m),
ip->proto, ip->invflags & IPT_INV_PROTO); ip->proto, ip->invflags & IPT_INV_PROTO);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
...@@ -662,10 +664,11 @@ static int check_target(struct ipt_entry *e, const char *name) ...@@ -662,10 +664,11 @@ static int check_target(struct ipt_entry *e, const char *name)
.target = t->u.kernel.target, .target = t->u.kernel.target,
.targinfo = t->data, .targinfo = t->data,
.hook_mask = e->comefrom, .hook_mask = e->comefrom,
.family = NFPROTO_IPV4,
}; };
int ret; int ret;
ret = xt_check_target(&par, NFPROTO_IPV4, t->u.target_size - sizeof(*t), ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
e->ip.proto, e->ip.invflags & IPT_INV_PROTO); e->ip.proto, e->ip.invflags & IPT_INV_PROTO);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
...@@ -693,6 +696,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size, ...@@ -693,6 +696,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
mtpar.table = name; mtpar.table = name;
mtpar.entryinfo = &e->ip; mtpar.entryinfo = &e->ip;
mtpar.hook_mask = e->comefrom; mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV4;
ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j); ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
if (ret != 0) if (ret != 0)
goto cleanup_matches; goto cleanup_matches;
...@@ -780,6 +784,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) ...@@ -780,6 +784,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
par.target = t->u.kernel.target; par.target = t->u.kernel.target;
par.targinfo = t->data; par.targinfo = t->data;
par.family = NFPROTO_IPV4;
if (par.target->destroy != NULL) if (par.target->destroy != NULL)
par.target->destroy(&par); par.target->destroy(&par);
module_put(par.target->me); module_put(par.target->me);
...@@ -1659,6 +1664,7 @@ compat_check_entry(struct ipt_entry *e, const char *name, ...@@ -1659,6 +1664,7 @@ compat_check_entry(struct ipt_entry *e, const char *name,
mtpar.table = name; mtpar.table = name;
mtpar.entryinfo = &e->ip; mtpar.entryinfo = &e->ip;
mtpar.hook_mask = e->comefrom; mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV4;
ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j); ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);
if (ret) if (ret)
goto cleanup_matches; goto cleanup_matches;
......
...@@ -370,6 +370,7 @@ ip6t_do_table(struct sk_buff *skb, ...@@ -370,6 +370,7 @@ ip6t_do_table(struct sk_buff *skb,
mtpar.hotdrop = &hotdrop; mtpar.hotdrop = &hotdrop;
mtpar.in = tgpar.in = in; mtpar.in = tgpar.in = in;
mtpar.out = tgpar.out = out; mtpar.out = tgpar.out = out;
mtpar.family = tgpar.family = NFPROTO_IPV6;
tgpar.hooknum = hook; tgpar.hooknum = hook;
read_lock_bh(&table->lock); read_lock_bh(&table->lock);
...@@ -604,6 +605,7 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i) ...@@ -604,6 +605,7 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
par.match = m->u.kernel.match; par.match = m->u.kernel.match;
par.matchinfo = m->data; par.matchinfo = m->data;
par.family = NFPROTO_IPV6;
if (par.match->destroy != NULL) if (par.match->destroy != NULL)
par.match->destroy(&par); par.match->destroy(&par);
module_put(par.match->me); module_put(par.match->me);
...@@ -640,7 +642,7 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, ...@@ -640,7 +642,7 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,
par->match = m->u.kernel.match; par->match = m->u.kernel.match;
par->matchinfo = m->data; par->matchinfo = m->data;
ret = xt_check_match(par, NFPROTO_IPV6, m->u.match_size - sizeof(*m), ret = xt_check_match(par, m->u.match_size - sizeof(*m),
ipv6->proto, ipv6->invflags & IP6T_INV_PROTO); ipv6->proto, ipv6->invflags & IP6T_INV_PROTO);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
...@@ -686,11 +688,12 @@ static int check_target(struct ip6t_entry *e, const char *name) ...@@ -686,11 +688,12 @@ static int check_target(struct ip6t_entry *e, const char *name)
.target = t->u.kernel.target, .target = t->u.kernel.target,
.targinfo = t->data, .targinfo = t->data,
.hook_mask = e->comefrom, .hook_mask = e->comefrom,
.family = NFPROTO_IPV6,
}; };
int ret; int ret;
t = ip6t_get_target(e); t = ip6t_get_target(e);
ret = xt_check_target(&par, NFPROTO_IPV6, t->u.target_size - sizeof(*t), ret = xt_check_target(&par, t->u.target_size - sizeof(*t),
e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO); e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO);
if (ret < 0) { if (ret < 0) {
duprintf("ip_tables: check failed for `%s'.\n", duprintf("ip_tables: check failed for `%s'.\n",
...@@ -718,6 +721,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, ...@@ -718,6 +721,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
mtpar.table = name; mtpar.table = name;
mtpar.entryinfo = &e->ipv6; mtpar.entryinfo = &e->ipv6;
mtpar.hook_mask = e->comefrom; mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV6;
ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j); ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j);
if (ret != 0) if (ret != 0)
goto cleanup_matches; goto cleanup_matches;
...@@ -805,6 +809,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) ...@@ -805,6 +809,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
par.target = t->u.kernel.target; par.target = t->u.kernel.target;
par.targinfo = t->data; par.targinfo = t->data;
par.family = NFPROTO_IPV6;
if (par.target->destroy != NULL) if (par.target->destroy != NULL)
par.target->destroy(&par); par.target->destroy(&par);
module_put(par.target->me); module_put(par.target->me);
...@@ -1685,6 +1690,7 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name, ...@@ -1685,6 +1690,7 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name,
mtpar.table = name; mtpar.table = name;
mtpar.entryinfo = &e->ipv6; mtpar.entryinfo = &e->ipv6;
mtpar.hook_mask = e->comefrom; mtpar.hook_mask = e->comefrom;
mtpar.family = NFPROTO_IPV6;
ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j); ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j);
if (ret) if (ret)
goto cleanup_matches; goto cleanup_matches;
......
...@@ -321,7 +321,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target, ...@@ -321,7 +321,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
} }
EXPORT_SYMBOL_GPL(xt_find_revision); EXPORT_SYMBOL_GPL(xt_find_revision);
int xt_check_match(struct xt_mtchk_param *par, u_int8_t family, int xt_check_match(struct xt_mtchk_param *par,
unsigned int size, u_int8_t proto, bool inv_proto) unsigned int size, u_int8_t proto, bool inv_proto)
{ {
if (XT_ALIGN(par->match->matchsize) != size && if (XT_ALIGN(par->match->matchsize) != size &&
...@@ -331,26 +331,27 @@ int xt_check_match(struct xt_mtchk_param *par, u_int8_t family, ...@@ -331,26 +331,27 @@ int xt_check_match(struct xt_mtchk_param *par, u_int8_t family,
* because it uses a dynamic-size data set. * because it uses a dynamic-size data set.
*/ */
printk("%s_tables: %s match: invalid size %Zu != %u\n", printk("%s_tables: %s match: invalid size %Zu != %u\n",
xt_prefix[family], par->match->name, xt_prefix[par->family], par->match->name,
XT_ALIGN(par->match->matchsize), size); XT_ALIGN(par->match->matchsize), size);
return -EINVAL; return -EINVAL;
} }
if (par->match->table != NULL && if (par->match->table != NULL &&
strcmp(par->match->table, par->table) != 0) { strcmp(par->match->table, par->table) != 0) {
printk("%s_tables: %s match: only valid in %s table, not %s\n", printk("%s_tables: %s match: only valid in %s table, not %s\n",
xt_prefix[family], par->match->name, xt_prefix[par->family], par->match->name,
par->match->table, par->table); par->match->table, par->table);
return -EINVAL; return -EINVAL;
} }
if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) { if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) {
printk("%s_tables: %s match: bad hook_mask %#x/%#x\n", printk("%s_tables: %s match: bad hook_mask %#x/%#x\n",
xt_prefix[family], par->match->name, xt_prefix[par->family], par->match->name,
par->hook_mask, par->match->hooks); par->hook_mask, par->match->hooks);
return -EINVAL; return -EINVAL;
} }
if (par->match->proto && (par->match->proto != proto || inv_proto)) { if (par->match->proto && (par->match->proto != proto || inv_proto)) {
printk("%s_tables: %s match: only valid for protocol %u\n", printk("%s_tables: %s match: only valid for protocol %u\n",
xt_prefix[family], par->match->name, par->match->proto); xt_prefix[par->family], par->match->name,
par->match->proto);
return -EINVAL; return -EINVAL;
} }
if (par->match->checkentry != NULL && !par->match->checkentry(par)) if (par->match->checkentry != NULL && !par->match->checkentry(par))
...@@ -471,31 +472,31 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, ...@@ -471,31 +472,31 @@ int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr,
EXPORT_SYMBOL_GPL(xt_compat_match_to_user); EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
int xt_check_target(struct xt_tgchk_param *par, u_int8_t family, int xt_check_target(struct xt_tgchk_param *par,
unsigned int size, u_int8_t proto, bool inv_proto) unsigned int size, u_int8_t proto, bool inv_proto)
{ {
if (XT_ALIGN(par->target->targetsize) != size) { if (XT_ALIGN(par->target->targetsize) != size) {
printk("%s_tables: %s target: invalid size %Zu != %u\n", printk("%s_tables: %s target: invalid size %Zu != %u\n",
xt_prefix[family], par->target->name, xt_prefix[par->family], par->target->name,
XT_ALIGN(par->target->targetsize), size); XT_ALIGN(par->target->targetsize), size);
return -EINVAL; return -EINVAL;
} }
if (par->target->table != NULL && if (par->target->table != NULL &&
strcmp(par->target->table, par->table) != 0) { strcmp(par->target->table, par->table) != 0) {
printk("%s_tables: %s target: only valid in %s table, not %s\n", printk("%s_tables: %s target: only valid in %s table, not %s\n",
xt_prefix[family], par->target->name, xt_prefix[par->family], par->target->name,
par->target->table, par->table); par->target->table, par->table);
return -EINVAL; return -EINVAL;
} }
if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) { if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) {
printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", printk("%s_tables: %s target: bad hook_mask %#x/%#x\n",
xt_prefix[family], par->target->name, par->hook_mask, xt_prefix[par->family], par->target->name,
par->target->hooks); par->hook_mask, par->target->hooks);
return -EINVAL; return -EINVAL;
} }
if (par->target->proto && (par->target->proto != proto || inv_proto)) { if (par->target->proto && (par->target->proto != proto || inv_proto)) {
printk("%s_tables: %s target: only valid for protocol %u\n", printk("%s_tables: %s target: only valid for protocol %u\n",
xt_prefix[family], par->target->name, xt_prefix[par->family], par->target->name,
par->target->proto); par->target->proto);
return -EINVAL; return -EINVAL;
} }
......
...@@ -55,9 +55,9 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int ...@@ -55,9 +55,9 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
par.target = target; par.target = target;
par.targinfo = t->data; par.targinfo = t->data;
par.hook_mask = hook; par.hook_mask = hook;
par.family = NFPROTO_IPV4;
ret = xt_check_target(&par, NFPROTO_IPV4, ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
t->u.target_size - sizeof(*t), 0, false);
if (ret < 0) { if (ret < 0) {
module_put(t->u.kernel.target->me); module_put(t->u.kernel.target->me);
return ret; return ret;
......
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