mirror of
https://github.com/torvalds/linux.git
synced 2024-12-25 12:21:37 +00:00
[NETFILTER]: Convert ip6_tables matches/targets to centralized error checking
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
aa83c1ab43
commit
7f9397138e
@ -544,21 +544,12 @@ standard_check(const struct ip6t_entry_target *t,
|
||||
struct ip6t_standard_target *targ = (void *)t;
|
||||
|
||||
/* Check standard info. */
|
||||
if (t->u.target_size
|
||||
!= IP6T_ALIGN(sizeof(struct ip6t_standard_target))) {
|
||||
duprintf("standard_check: target size %u != %u\n",
|
||||
t->u.target_size,
|
||||
IP6T_ALIGN(sizeof(struct ip6t_standard_target)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (targ->verdict >= 0
|
||||
&& targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
|
||||
duprintf("ip6t_standard_check: bad verdict (%i)\n",
|
||||
targ->verdict);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (targ->verdict < -NF_MAX_VERDICT - 1) {
|
||||
duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
|
||||
targ->verdict);
|
||||
@ -1385,24 +1376,22 @@ icmp6_checkentry(const char *tablename,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
const struct ip6t_ip6 *ipv6 = entry;
|
||||
const struct ip6t_icmp *icmpinfo = matchinfo;
|
||||
|
||||
/* Must specify proto == ICMP, and no unknown invflags */
|
||||
return ipv6->proto == IPPROTO_ICMPV6
|
||||
&& !(ipv6->invflags & IP6T_INV_PROTO)
|
||||
&& matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp))
|
||||
&& !(icmpinfo->invflags & ~IP6T_ICMP_INV);
|
||||
/* Must specify no unknown invflags */
|
||||
return !(icmpinfo->invflags & ~IP6T_ICMP_INV);
|
||||
}
|
||||
|
||||
/* The built-in targets: standard (NULL) and error. */
|
||||
static struct ip6t_target ip6t_standard_target = {
|
||||
.name = IP6T_STANDARD_TARGET,
|
||||
.targetsize = sizeof(int),
|
||||
};
|
||||
|
||||
static struct ip6t_target ip6t_error_target = {
|
||||
.name = IP6T_ERROR_TARGET,
|
||||
.target = ip6t_error,
|
||||
.targetsize = IP6T_FUNCTION_MAXNAMELEN,
|
||||
};
|
||||
|
||||
static struct nf_sockopt_ops ip6t_sockopts = {
|
||||
@ -1418,7 +1407,9 @@ static struct nf_sockopt_ops ip6t_sockopts = {
|
||||
static struct ip6t_match icmp6_matchstruct = {
|
||||
.name = "icmp6",
|
||||
.match = &icmp6_match,
|
||||
.checkentry = &icmp6_checkentry,
|
||||
.matchsize = sizeof(struct ip6t_icmp),
|
||||
.checkentry = icmp6_checkentry,
|
||||
.proto = IPPROTO_ICMPV6,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
|
@ -69,37 +69,24 @@ static int ip6t_hl_checkentry(const char *tablename,
|
||||
{
|
||||
struct ip6t_HL_info *info = targinfo;
|
||||
|
||||
if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
|
||||
printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n",
|
||||
targinfosize,
|
||||
IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(tablename, "mangle")) {
|
||||
printk(KERN_WARNING "ip6t_HL: can only be called from "
|
||||
"\"mangle\" table, not \"%s\"\n", tablename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (info->mode > IP6T_HL_MAXMODE) {
|
||||
printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
|
||||
info->mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
|
||||
printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
|
||||
"make sense with value 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_target ip6t_HL = {
|
||||
.name = "HL",
|
||||
.target = ip6t_hl_target,
|
||||
.targetsize = sizeof(struct ip6t_HL_info),
|
||||
.table = "mangle",
|
||||
.checkentry = ip6t_hl_checkentry,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
@ -455,29 +455,22 @@ static int ip6t_log_checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_log_info *loginfo = targinfo;
|
||||
|
||||
if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_log_info))) {
|
||||
DEBUGP("LOG: targinfosize %u != %u\n",
|
||||
targinfosize, IP6T_ALIGN(sizeof(struct ip6t_log_info)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (loginfo->level >= 8) {
|
||||
DEBUGP("LOG: level %u >= 8\n", loginfo->level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
|
||||
DEBUGP("LOG: prefix term %i\n",
|
||||
loginfo->prefix[sizeof(loginfo->prefix)-1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_target ip6t_log_reg = {
|
||||
.name = "LOG",
|
||||
.target = ip6t_log_target,
|
||||
.targetsize = sizeof(struct ip6t_log_info),
|
||||
.checkentry = ip6t_log_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
@ -228,24 +228,6 @@ static int check(const char *tablename,
|
||||
const struct ip6t_reject_info *rejinfo = targinfo;
|
||||
const struct ip6t_entry *e = entry;
|
||||
|
||||
if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
|
||||
DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only allow these for packet filtering. */
|
||||
if (strcmp(tablename, "filter") != 0) {
|
||||
DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
|
||||
| (1 << NF_IP6_FORWARD)
|
||||
| (1 << NF_IP6_LOCAL_OUT))) != 0) {
|
||||
DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
|
||||
printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
|
||||
return 0;
|
||||
@ -257,13 +239,16 @@ static int check(const char *tablename,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_target ip6t_reject_reg = {
|
||||
.name = "REJECT",
|
||||
.target = reject6_target,
|
||||
.targetsize = sizeof(struct ip6t_reject_info),
|
||||
.table = "filter",
|
||||
.hooks = (1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) |
|
||||
(1 << NF_IP6_LOCAL_OUT),
|
||||
.checkentry = check,
|
||||
.me = THIS_MODULE
|
||||
};
|
||||
|
@ -105,11 +105,6 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_ah *ahinfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
|
||||
DEBUGP("ip6t_ah: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
|
||||
return 0;
|
||||
}
|
||||
if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
|
||||
DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
|
||||
return 0;
|
||||
@ -119,8 +114,9 @@ checkentry(const char *tablename,
|
||||
|
||||
static struct ip6t_match ah_match = {
|
||||
.name = "ah",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_ah),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -185,16 +185,10 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_opts *optsinfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
|
||||
DEBUGP("ip6t_opts: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
|
||||
return 0;
|
||||
}
|
||||
if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
|
||||
DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -204,8 +198,9 @@ static struct ip6t_match opts_match = {
|
||||
#else
|
||||
.name = "dst",
|
||||
#endif
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_opts),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -83,11 +83,6 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_esp *espinfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_esp))) {
|
||||
DEBUGP("ip6t_esp: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_esp)));
|
||||
return 0;
|
||||
}
|
||||
if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
|
||||
DEBUGP("ip6t_esp: unknown flags %X\n",
|
||||
espinfo->invflags);
|
||||
@ -98,8 +93,9 @@ checkentry(const char *tablename,
|
||||
|
||||
static struct ip6t_match esp_match = {
|
||||
.name = "esp",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_esp),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -60,30 +60,12 @@ match(const struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ip6t_eui64_checkentry(const char *tablename,
|
||||
const void *ip,
|
||||
void *matchinfo,
|
||||
unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
if (hook_mask
|
||||
& ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
|
||||
(1 << NF_IP6_FORWARD))) {
|
||||
printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matchsize != IP6T_ALIGN(sizeof(int)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_match eui64_match = {
|
||||
.name = "eui64",
|
||||
.match = &match,
|
||||
.checkentry = &ip6t_eui64_checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(int),
|
||||
.hooks = (1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
|
||||
(1 << NF_IP6_FORWARD),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -122,23 +122,18 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_frag *fraginfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) {
|
||||
DEBUGP("ip6t_frag: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag)));
|
||||
return 0;
|
||||
}
|
||||
if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
|
||||
DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_match frag_match = {
|
||||
.name = "frag",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_frag),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -185,16 +185,10 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_opts *optsinfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
|
||||
DEBUGP("ip6t_opts: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
|
||||
return 0;
|
||||
}
|
||||
if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
|
||||
DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -204,8 +198,9 @@ static struct ip6t_match opts_match = {
|
||||
#else
|
||||
.name = "dst",
|
||||
#endif
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_opts),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -48,20 +48,10 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int checkentry(const char *tablename, const void *entry,
|
||||
void *matchinfo, unsigned int matchsize,
|
||||
unsigned int hook_mask)
|
||||
{
|
||||
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_hl_info)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_match hl_match = {
|
||||
.name = "hl",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_hl_info),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -131,11 +131,6 @@ ipv6header_checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_ipv6header_info *info = matchinfo;
|
||||
|
||||
/* Check for obvious errors */
|
||||
/* This match is valid in all hooks! */
|
||||
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)))
|
||||
return 0;
|
||||
|
||||
/* invflags is 0 or 0xff in hard mode */
|
||||
if ((!info->modeflag) && info->invflags != 0x00 &&
|
||||
info->invflags != 0xFF)
|
||||
@ -147,6 +142,7 @@ ipv6header_checkentry(const char *tablename,
|
||||
static struct ip6t_match ip6t_ipv6header_match = {
|
||||
.name = "ipv6header",
|
||||
.match = &ipv6header_match,
|
||||
.matchsize = sizeof(struct ip6t_ipv6header_info),
|
||||
.checkentry = &ipv6header_checkentry,
|
||||
.destroy = NULL,
|
||||
.me = THIS_MODULE,
|
||||
|
@ -92,13 +92,9 @@ checkentry(const char *tablename,
|
||||
const struct ip6t_ip6 *ip = info;
|
||||
const struct ip6t_multiport *multiinfo = matchinfo;
|
||||
|
||||
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
|
||||
return 0;
|
||||
|
||||
/* Must specify proto == TCP/UDP, no unknown flags or bad count */
|
||||
return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
|
||||
&& !(ip->invflags & IP6T_INV_PROTO)
|
||||
&& matchsize == IP6T_ALIGN(sizeof(struct ip6t_multiport))
|
||||
&& (multiinfo->flags == IP6T_MULTIPORT_SOURCE
|
||||
|| multiinfo->flags == IP6T_MULTIPORT_DESTINATION
|
||||
|| multiinfo->flags == IP6T_MULTIPORT_EITHER)
|
||||
@ -107,8 +103,9 @@ checkentry(const char *tablename,
|
||||
|
||||
static struct ip6t_match multiport_match = {
|
||||
.name = "multiport",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_multiport),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -60,28 +60,20 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_owner_info *info = matchinfo;
|
||||
|
||||
if (hook_mask
|
||||
& ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
|
||||
printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
|
||||
return 0;
|
||||
|
||||
if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
|
||||
printk("ipt_owner: pid and sid matching "
|
||||
"not supported anymore\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct ip6t_match owner_match = {
|
||||
.name = "owner",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_owner_info),
|
||||
.hooks = (1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
@ -125,11 +125,6 @@ static int checkentry(const char *tablename, const void *ip_void,
|
||||
{
|
||||
struct ip6t_policy_info *info = matchinfo;
|
||||
|
||||
if (matchsize != IP6T_ALIGN(sizeof(*info))) {
|
||||
printk(KERN_ERR "ip6t_policy: matchsize %u != %zu\n",
|
||||
matchsize, IP6T_ALIGN(sizeof(*info)));
|
||||
return 0;
|
||||
}
|
||||
if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))) {
|
||||
printk(KERN_ERR "ip6t_policy: neither incoming nor "
|
||||
"outgoing policy selected\n");
|
||||
@ -158,6 +153,7 @@ static int checkentry(const char *tablename, const void *ip_void,
|
||||
static struct ip6t_match policy_match = {
|
||||
.name = "policy",
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_policy_info),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
@ -200,11 +200,6 @@ checkentry(const char *tablename,
|
||||
{
|
||||
const struct ip6t_rt *rtinfo = matchinfo;
|
||||
|
||||
if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) {
|
||||
DEBUGP("ip6t_rt: matchsize %u != %u\n",
|
||||
matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt)));
|
||||
return 0;
|
||||
}
|
||||
if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
|
||||
DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
|
||||
return 0;
|
||||
@ -222,8 +217,9 @@ checkentry(const char *tablename,
|
||||
|
||||
static struct ip6t_match rt_match = {
|
||||
.name = "rt",
|
||||
.match = &match,
|
||||
.checkentry = &checkentry,
|
||||
.match = match,
|
||||
.matchsize = sizeof(struct ip6t_rt),
|
||||
.checkentry = checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user