Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d5cd909 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: Convert ip_tables matches/targets to centralized error checking

parent 3cdc7c95
Loading
Loading
Loading
Loading
+6 −35
Original line number Diff line number Diff line
@@ -181,23 +181,6 @@ static int ipt_snat_checkentry(const char *tablename,
		printk("SNAT: multiple ranges no longer supported\n");
		return 0;
	}

	if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
		DEBUGP("SNAT: Target size %u wrong for %u ranges\n",
		       targinfosize, mr->rangesize);
		return 0;
	}

	/* Only allow these for NAT. */
	if (strcmp(tablename, "nat") != 0) {
		DEBUGP("SNAT: wrong table %s\n", tablename);
		return 0;
	}

	if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
		DEBUGP("SNAT: hook mask 0x%x bad\n", hook_mask);
		return 0;
	}
	return 1;
}

@@ -214,24 +197,6 @@ static int ipt_dnat_checkentry(const char *tablename,
		printk("DNAT: multiple ranges no longer supported\n");
		return 0;
	}

	if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) {
		DEBUGP("DNAT: Target size %u wrong for %u ranges\n",
		       targinfosize, mr->rangesize);
		return 0;
	}

	/* Only allow these for NAT. */
	if (strcmp(tablename, "nat") != 0) {
		DEBUGP("DNAT: wrong table %s\n", tablename);
		return 0;
	}

	if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))) {
		DEBUGP("DNAT: hook mask 0x%x bad\n", hook_mask);
		return 0;
	}
	
	return 1;
}

@@ -299,12 +264,18 @@ int ip_nat_rule_find(struct sk_buff **pskb,
static struct ipt_target ipt_snat_reg = {
	.name		= "SNAT",
	.target		= ipt_snat_target,
	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
	.table		= "nat",
	.hooks		= 1 << NF_IP_POST_ROUTING,
	.checkentry	= ipt_snat_checkentry,
};

static struct ipt_target ipt_dnat_reg = {
	.name		= "DNAT",
	.target		= ipt_dnat_target,
	.targetsize	= sizeof(struct ip_nat_multi_range_compat),
	.table		= "nat",
	.hooks		= 1 << NF_IP_PRE_ROUTING,
	.checkentry	= ipt_dnat_checkentry,
};

+8 −17
Original line number Diff line number Diff line
@@ -477,21 +477,12 @@ standard_check(const struct ipt_entry_target *t,
	struct ipt_standard_target *targ = (void *)t;

	/* Check standard info. */
	if (t->u.target_size
	    != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
		duprintf("standard_check: target size %u != %u\n",
			 t->u.target_size,
			 IPT_ALIGN(sizeof(struct ipt_standard_target)));
		return 0;
	}

	if (targ->verdict >= 0
	    && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
		duprintf("ipt_standard_check: bad verdict (%i)\n",
			 targ->verdict);
		return 0;
	}

	if (targ->verdict < -NF_MAX_VERDICT - 1) {
		duprintf("ipt_standard_check: bad negative verdict (%i)\n",
			 targ->verdict);
@@ -1330,24 +1321,22 @@ icmp_checkentry(const char *tablename,
	   unsigned int matchsize,
	   unsigned int hook_mask)
{
	const struct ipt_ip *ip = info;
	const struct ipt_icmp *icmpinfo = matchinfo;

	/* Must specify proto == ICMP, and no unknown invflags */
	return ip->proto == IPPROTO_ICMP
		&& !(ip->invflags & IPT_INV_PROTO)
		&& matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
		&& !(icmpinfo->invflags & ~IPT_ICMP_INV);
	/* Must specify no unknown invflags */
	return !(icmpinfo->invflags & ~IPT_ICMP_INV);
}

/* The built-in targets: standard (NULL) and error. */
static struct ipt_target ipt_standard_target = {
	.name		= IPT_STANDARD_TARGET,
	.targetsize	= sizeof(int),
};

static struct ipt_target ipt_error_target = {
	.name		= IPT_ERROR_TARGET,
	.target		= ipt_error,
	.targetsize	= IPT_FUNCTION_MAXNAMELEN,
};

static struct nf_sockopt_ops ipt_sockopts = {
@@ -1362,8 +1351,10 @@ static struct nf_sockopt_ops ipt_sockopts = {

static struct ipt_match icmp_matchstruct = {
	.name		= "icmp",
	.match		= &icmp_match,
	.checkentry	= &icmp_checkentry,
	.match		= icmp_match,
	.matchsize	= sizeof(struct ipt_icmp),
	.proto		= IPPROTO_ICMP,
	.checkentry	= icmp_checkentry,
};

static int __init init(void)
+7 −13
Original line number Diff line number Diff line
@@ -389,13 +389,6 @@ checkentry(const char *tablename,

	struct clusterip_config *config;

	if (targinfosize != IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info))) {
		printk(KERN_WARNING "CLUSTERIP: targinfosize %u != %Zu\n",
		       targinfosize,
		       IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)));
		return 0;
	}

	if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
	    cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
	    cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
@@ -478,9 +471,10 @@ static void destroy(void *matchinfo, unsigned int matchinfosize)

static struct ipt_target clusterip_tgt = {
	.name		= "CLUSTERIP",
	.target = &target, 
	.checkentry = &checkentry, 
	.destroy = &destroy,
	.target		= target,
	.targetsize	= sizeof(struct ipt_clusterip_tgt_info),
	.checkentry	= checkentry,
	.destroy	= destroy,
	.me		= THIS_MODULE
};

+2 −13
Original line number Diff line number Diff line
@@ -64,29 +64,18 @@ checkentry(const char *tablename,
{
	const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp;

	if (targinfosize != IPT_ALIGN(sizeof(struct ipt_DSCP_info))) {
		printk(KERN_WARNING "DSCP: targinfosize %u != %Zu\n",
		       targinfosize,
		       IPT_ALIGN(sizeof(struct ipt_DSCP_info)));
		return 0;
	}

	if (strcmp(tablename, "mangle") != 0) {
		printk(KERN_WARNING "DSCP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
		return 0;
	}

	if ((dscp > IPT_DSCP_MAX)) {
		printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
		return 0;
	}

	return 1;
}

static struct ipt_target ipt_dscp_reg = {
	.name		= "DSCP",
	.target		= target,
	.targetsize	= sizeof(struct ipt_DSCP_info),
	.table		= "mangle",
	.checkentry	= checkentry,
	.me		= THIS_MODULE,
};
+2 −14
Original line number Diff line number Diff line
@@ -121,18 +121,6 @@ checkentry(const char *tablename,
	const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
	const struct ipt_entry *e = e_void;

	if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
		printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
		       targinfosize,
		       IPT_ALIGN(sizeof(struct ipt_ECN_info)));
		return 0;
	}

	if (strcmp(tablename, "mangle") != 0) {
		printk(KERN_WARNING "ECN: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
		return 0;
	}

	if (einfo->operation & IPT_ECN_OP_MASK) {
		printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
			einfo->operation);
@@ -143,20 +131,20 @@ checkentry(const char *tablename,
			einfo->ip_ect);
		return 0;
	}

	if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
	    && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) {
		printk(KERN_WARNING "ECN: cannot use TCP operations on a "
		       "non-tcp rule\n");
		return 0;
	}

	return 1;
}

static struct ipt_target ipt_ecn_reg = {
	.name		= "ECN",
	.target		= target,
	.targetsize	= sizeof(struct ipt_ECN_info),
	.table		= "mangle",
	.checkentry	= checkentry,
	.me		= THIS_MODULE,
};
Loading