forked from mirrors/linux
		
	netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses
Wrong comparison prevented the hash types to add a range with more than 2^31 addresses but reported as a success. Fixes Netfilter's bugzilla id #1005, reported by Oleg Serditov and Oliver Ford. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
		
							parent
							
								
									89fcbb564f
								
							
						
					
					
						commit
						48596a8ddc
					
				
					 10 changed files with 24 additions and 22 deletions
				
			
		| 
						 | 
					@ -123,13 +123,12 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip &= ip_set_hostmask(h->netmask);
 | 
						ip &= ip_set_hostmask(h->netmask);
 | 
				
			||||||
 | 
						e.ip = htonl(ip);
 | 
				
			||||||
 | 
						if (e.ip == 0)
 | 
				
			||||||
 | 
							return -IPSET_ERR_HASH_ELEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (adt == IPSET_TEST) {
 | 
						if (adt == IPSET_TEST)
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
					 | 
				
			||||||
		if (e.ip == 0)
 | 
					 | 
				
			||||||
			return -IPSET_ERR_HASH_ELEM;
 | 
					 | 
				
			||||||
		return adtfn(set, &e, &ext, &ext, flags);
 | 
							return adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip_to = ip;
 | 
						ip_to = ip;
 | 
				
			||||||
	if (tb[IPSET_ATTR_IP_TO]) {
 | 
						if (tb[IPSET_ATTR_IP_TO]) {
 | 
				
			||||||
| 
						 | 
					@ -148,17 +147,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 | 
						hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried) {
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	for (; !before(ip_to, ip); ip += hosts) {
 | 
					 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		if (e.ip == 0)
 | 
						}
 | 
				
			||||||
			return -IPSET_ERR_HASH_ELEM;
 | 
						for (; ip <= ip_to;) {
 | 
				
			||||||
		ret = adtfn(set, &e, &ext, &ext, flags);
 | 
							ret = adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ret && !ip_set_eexist(ret, flags))
 | 
							if (ret && !ip_set_eexist(ret, flags))
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ip += hosts;
 | 
				
			||||||
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
 | 
							if (e.ip == 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ret = 0;
 | 
							ret = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	for (; !before(ip_to, ip); ip++) {
 | 
						for (; ip <= ip_to; ip++) {
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		ret = adtfn(set, &e, &ext, &ext, flags);
 | 
							ret = adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,7 +178,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	for (; !before(ip_to, ip); ip++) {
 | 
						for (; ip <= ip_to; ip++) {
 | 
				
			||||||
		p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
							p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
				
			||||||
						       : port;
 | 
											       : port;
 | 
				
			||||||
		for (; p <= port_to; p++) {
 | 
							for (; p <= port_to; p++) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	for (; !before(ip_to, ip); ip++) {
 | 
						for (; ip <= ip_to; ip++) {
 | 
				
			||||||
		p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
							p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
				
			||||||
						       : port;
 | 
											       : port;
 | 
				
			||||||
		for (; p <= port_to; p++) {
 | 
							for (; p <= port_to; p++) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,7 +271,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	for (; !before(ip_to, ip); ip++) {
 | 
						for (; ip <= ip_to; ip++) {
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
							p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 | 
				
			||||||
						       : port;
 | 
											       : port;
 | 
				
			||||||
| 
						 | 
					@ -281,7 +281,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
			      ip == ntohl(h->next.ip) &&
 | 
								      ip == ntohl(h->next.ip) &&
 | 
				
			||||||
			      p == ntohs(h->next.port)
 | 
								      p == ntohs(h->next.port)
 | 
				
			||||||
				? ntohl(h->next.ip2) : ip2_from;
 | 
									? ntohl(h->next.ip2) : ip2_from;
 | 
				
			||||||
			while (!after(ip2, ip2_to)) {
 | 
								while (ip2 <= ip2_to) {
 | 
				
			||||||
				e.ip2 = htonl(ip2);
 | 
									e.ip2 = htonl(ip2);
 | 
				
			||||||
				ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
 | 
									ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
 | 
				
			||||||
								&cidr);
 | 
													&cidr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,7 +193,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	while (!after(ip, ip_to)) {
 | 
						while (ip <= ip_to) {
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
 | 
							last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
 | 
				
			||||||
		ret = adtfn(set, &e, &ext, &ext, flags);
 | 
							ret = adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	while (!after(ip, ip_to)) {
 | 
						while (ip <= ip_to) {
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
 | 
							last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
 | 
				
			||||||
		ret = adtfn(set, &e, &ext, &ext, flags);
 | 
							ret = adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,13 +250,13 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip[0]);
 | 
							ip = ntohl(h->next.ip[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!after(ip, ip_to)) {
 | 
						while (ip <= ip_to) {
 | 
				
			||||||
		e.ip[0] = htonl(ip);
 | 
							e.ip[0] = htonl(ip);
 | 
				
			||||||
		last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
 | 
							last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
 | 
				
			||||||
		ip2 = (retried &&
 | 
							ip2 = (retried &&
 | 
				
			||||||
		       ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
 | 
							       ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
 | 
				
			||||||
						   : ip2_from;
 | 
											   : ip2_from;
 | 
				
			||||||
		while (!after(ip2, ip2_to)) {
 | 
							while (ip2 <= ip2_to) {
 | 
				
			||||||
			e.ip[1] = htonl(ip2);
 | 
								e.ip[1] = htonl(ip2);
 | 
				
			||||||
			last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
 | 
								last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
 | 
				
			||||||
			ret = adtfn(set, &e, &ext, &ext, flags);
 | 
								ret = adtfn(set, &e, &ext, &ext, flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,7 +241,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip);
 | 
							ip = ntohl(h->next.ip);
 | 
				
			||||||
	while (!after(ip, ip_to)) {
 | 
						while (ip <= ip_to) {
 | 
				
			||||||
		e.ip = htonl(ip);
 | 
							e.ip = htonl(ip);
 | 
				
			||||||
		last = ip_set_range_to_cidr(ip, ip_to, &cidr);
 | 
							last = ip_set_range_to_cidr(ip, ip_to, &cidr);
 | 
				
			||||||
		e.cidr = cidr - 1;
 | 
							e.cidr = cidr - 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,7 +291,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
	if (retried)
 | 
						if (retried)
 | 
				
			||||||
		ip = ntohl(h->next.ip[0]);
 | 
							ip = ntohl(h->next.ip[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!after(ip, ip_to)) {
 | 
						while (ip <= ip_to) {
 | 
				
			||||||
		e.ip[0] = htonl(ip);
 | 
							e.ip[0] = htonl(ip);
 | 
				
			||||||
		ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
 | 
							ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
 | 
				
			||||||
		p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port)
 | 
							p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port)
 | 
				
			||||||
| 
						 | 
					@ -301,7 +301,7 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 | 
				
			||||||
			ip2 = (retried && ip == ntohl(h->next.ip[0]) &&
 | 
								ip2 = (retried && ip == ntohl(h->next.ip[0]) &&
 | 
				
			||||||
			       p == ntohs(h->next.port)) ? ntohl(h->next.ip[1])
 | 
								       p == ntohs(h->next.port)) ? ntohl(h->next.ip[1])
 | 
				
			||||||
							 : ip2_from;
 | 
												 : ip2_from;
 | 
				
			||||||
			while (!after(ip2, ip2_to)) {
 | 
								while (ip2 <= ip2_to) {
 | 
				
			||||||
				e.ip[1] = htonl(ip2);
 | 
									e.ip[1] = htonl(ip2);
 | 
				
			||||||
				ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
 | 
									ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
 | 
				
			||||||
								&e.cidr[1]);
 | 
													&e.cidr[1]);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue