Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 44593
b: refs/heads/master
c: a96be24
h: refs/heads/master
i:
  44591: 13a0cab
v: v3
  • Loading branch information
Dmitry Mishin authored and David S. Miller committed Dec 14, 2006
1 parent 9aaf26d commit 2a33bc6
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 98 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 11078c371e2ecfce011d1dffb67888c6fed1b664
refs/heads/master: a96be24679198469df28976c809575423e70d843
176 changes: 79 additions & 97 deletions trunk/net/ipv4/netfilter/ip_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,47 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
}

static inline int
check_match(struct ipt_entry_match *m,
check_entry(struct ipt_entry *e, const char *name)
{
struct ipt_entry_target *t;

if (!ip_checkentry(&e->ip)) {
duprintf("ip_tables: ip check failed %p %s.\n", e, name);
return -EINVAL;
}

if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
return -EINVAL;

t = ipt_get_target(e);
if (e->target_offset + t->u.target_size > e->next_offset)
return -EINVAL;

return 0;
}

static inline int check_match(struct ipt_entry_match *m, const char *name,
const struct ipt_ip *ip, unsigned int hookmask)
{
struct ipt_match *match;
int ret;

match = m->u.kernel.match;
ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
name, hookmask, ip->proto,
ip->invflags & IPT_INV_PROTO);
if (!ret && m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, match, m->data,
hookmask)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
}
return ret;
}

static inline int
find_check_match(struct ipt_entry_match *m,
const char *name,
const struct ipt_ip *ip,
unsigned int hookmask,
Expand All @@ -497,87 +537,78 @@ check_match(struct ipt_entry_match *m,
m->u.user.revision),
"ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) {
duprintf("check_match: `%s' not found\n", m->u.user.name);
duprintf("find_check_match: `%s' not found\n", m->u.user.name);
return match ? PTR_ERR(match) : -ENOENT;
}
m->u.kernel.match = match;

ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
name, hookmask, ip->proto,
ip->invflags & IPT_INV_PROTO);
ret = check_match(m, name, ip, hookmask);
if (ret)
goto err;

if (m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, match, m->data,
hookmask)) {
duprintf("ip_tables: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
goto err;
}

(*i)++;
return 0;
err:
module_put(m->u.kernel.match->me);
return ret;
}

static struct ipt_target ipt_standard_target;
static inline int check_target(struct ipt_entry *e, const char *name)
{
struct ipt_entry_target *t;
struct ipt_target *target;
int ret;

t = ipt_get_target(e);
target = t->u.kernel.target;
ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
name, e->comefrom, e->ip.proto,
e->ip.invflags & IPT_INV_PROTO);
if (!ret && t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(name, e, target,
t->data, e->comefrom)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
}
return ret;
}

static inline int
check_entry(struct ipt_entry *e, const char *name, unsigned int size,
find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
unsigned int *i)
{
struct ipt_entry_target *t;
struct ipt_target *target;
int ret;
unsigned int j;

if (!ip_checkentry(&e->ip)) {
duprintf("ip_tables: ip check failed %p %s.\n", e, name);
return -EINVAL;
}

if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
return -EINVAL;
ret = check_entry(e, name);
if (ret)
return ret;

j = 0;
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
ret = IPT_MATCH_ITERATE(e, find_check_match, name, &e->ip,
e->comefrom, &j);
if (ret != 0)
goto cleanup_matches;

t = ipt_get_target(e);
ret = -EINVAL;
if (e->target_offset + t->u.target_size > e->next_offset)
goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches;
}
t->u.kernel.target = target;

ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
name, e->comefrom, e->ip.proto,
e->ip.invflags & IPT_INV_PROTO);
ret = check_target(e, name);
if (ret)
goto err;

if (t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(name, e, target, t->data,
e->comefrom)) {
duprintf("ip_tables: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
goto err;
}

(*i)++;
return 0;
err:
Expand Down Expand Up @@ -712,7 +743,7 @@ translate_table(const char *name,
/* Finally, each sanity check must pass */
i = 0;
ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
find_check_entry, name, size, &i);

if (ret != 0) {
IPT_ENTRY_ITERATE(entry0, newinfo->size,
Expand Down Expand Up @@ -1452,14 +1483,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL;
}

if (!ip_checkentry(&e->ip)) {
duprintf("ip_tables: ip check failed %p %s.\n", e, name);
return -EINVAL;
}

if (e->target_offset + sizeof(struct compat_xt_entry_target) >
e->next_offset)
return -EINVAL;
ret = check_entry(e, name);
if (ret)
return ret;

off = 0;
entry_offset = (void *)e - (void *)base;
Expand All @@ -1470,15 +1496,13 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
goto cleanup_matches;

t = ipt_get_target(e);
ret = -EINVAL;
if (e->target_offset + t->u.target_size > e->next_offset)
goto cleanup_matches;
target = try_then_request_module(xt_find_target(AF_INET,
t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
goto cleanup_matches;
}
Expand Down Expand Up @@ -1555,57 +1579,15 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
return ret;
}

static inline int compat_check_match(struct ipt_entry_match *m, const char *name,
const struct ipt_ip *ip, unsigned int hookmask)
{
struct ipt_match *match;
int ret;

match = m->u.kernel.match;
ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m),
name, hookmask, ip->proto,
ip->invflags & IPT_INV_PROTO);
if (!ret && m->u.kernel.match->checkentry
&& !m->u.kernel.match->checkentry(name, ip, match, m->data,
hookmask)) {
duprintf("ip_tables: compat: check failed for `%s'.\n",
m->u.kernel.match->name);
ret = -EINVAL;
}
return ret;
}

static inline int compat_check_target(struct ipt_entry *e, const char *name)
{
struct ipt_entry_target *t;
struct ipt_target *target;
int ret;

t = ipt_get_target(e);
target = t->u.kernel.target;
ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
name, e->comefrom, e->ip.proto,
e->ip.invflags & IPT_INV_PROTO);
if (!ret && t->u.kernel.target->checkentry
&& !t->u.kernel.target->checkentry(name, e, target,
t->data, e->comefrom)) {
duprintf("ip_tables: compat: check failed for `%s'.\n",
t->u.kernel.target->name);
ret = -EINVAL;
}
return ret;
}

static inline int compat_check_entry(struct ipt_entry *e, const char *name)
{
int ret;

ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip,
e->comefrom);
ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
if (ret)
return ret;

return compat_check_target(e, name);
return check_target(e, name);
}

static int
Expand Down

0 comments on commit 2a33bc6

Please sign in to comment.