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

Commit 7cf7899d authored by David S. Miller's avatar David S. Miller
Browse files

ipset: Stop using NLA_PUT*().



These macros contain a hidden goto, and are thus extremely error
prone and make code hard to audit.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c1dd3b6
Loading
Loading
Loading
Loading
+26 −20
Original line number Diff line number Diff line
@@ -411,26 +411,32 @@ ip_set_get_h16(const struct nlattr *attr)
#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
#define ipset_nest_end(skb, start)  nla_nest_end(skb, start)

#define NLA_PUT_IPADDR4(skb, type, ipaddr)			\
do {								\
	struct nlattr *__nested = ipset_nest_start(skb, type);	\
								\
	if (!__nested)						\
		goto nla_put_failure;				\
	NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr);	\
	ipset_nest_end(skb, __nested);				\
} while (0)

#define NLA_PUT_IPADDR6(skb, type, ipaddrptr)			\
do {								\
	struct nlattr *__nested = ipset_nest_start(skb, type);	\
								\
	if (!__nested)						\
		goto nla_put_failure;				\
	NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6,			\
		sizeof(struct in6_addr), ipaddrptr);		\
	ipset_nest_end(skb, __nested);				\
} while (0)
static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr)
{
	struct nlattr *__nested = ipset_nest_start(skb, type);
	int ret;

	if (!__nested)
		return -EMSGSIZE;
	ret = nla_put_net32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr);
	if (!ret)
		ipset_nest_end(skb, __nested);
	return ret;
}

static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, const struct in6_addr *ipaddrptr)
{
	struct nlattr *__nested = ipset_nest_start(skb, type);
	int ret;

	if (!__nested)
		return -EMSGSIZE;
	ret = nla_put(skb, IPSET_ATTR_IPADDR_IPV6,
		      sizeof(struct in6_addr), ipaddrptr);
	if (!ret)
		ipset_nest_end(skb, __nested);
	return ret;
}

/* Get address from skbuff */
static inline __be32
+12 −9
Original line number Diff line number Diff line
@@ -594,17 +594,20 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
	if (!nested)
		goto nla_put_failure;
	NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,
		      htonl(jhash_size(h->table->htable_bits)));
	NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));
	if (nla_put_net32(skb, IPSET_ATTR_HASHSIZE,
			  htonl(jhash_size(h->table->htable_bits))) ||
	    nla_put_net32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem)))
		goto nla_put_failure;
#ifdef IP_SET_HASH_WITH_NETMASK
	if (h->netmask != HOST_MASK)
		NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
	if (h->netmask != HOST_MASK &&
	    nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask))
		goto nla_put_failure;
#endif
	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
	if (with_timeout(h->timeout))
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));
	if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
	    nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
	    (with_timeout(h->timeout) &&
	     nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout))))
		goto nla_put_failure;
	ipset_nest_end(skb, nested);

	return 0;
+18 −15
Original line number Diff line number Diff line
@@ -109,8 +109,9 @@ bitmap_ip_list(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
				htonl(map->first_ip + id * map->hosts));
		if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
				    htonl(map->first_ip + id * map->hosts)))
			goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, atd);
@@ -194,10 +195,11 @@ bitmap_ip_tlist(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
				htonl(map->first_ip + id * map->hosts));
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
			      htonl(ip_set_timeout_get(members[id])));
		if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
				    htonl(map->first_ip + id * map->hosts)) ||
		    nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
				  htonl(ip_set_timeout_get(members[id]))))
			goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, adt);
@@ -334,15 +336,16 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
	if (!nested)
		goto nla_put_failure;
	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
	if (map->netmask != 32)
		NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
		      htonl(sizeof(*map) + map->memsize));
	if (with_timeout(map->timeout))
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
	if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
	    nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
	    (map->netmask != 32 &&
	     nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask)) ||
	    nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
	    nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
			  htonl(sizeof(*map) + map->memsize)) ||
	    (with_timeout(map->timeout) &&
	     nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
		goto nla_put_failure;
	ipset_nest_end(skb, nested);

	return 0;
+24 −19
Original line number Diff line number Diff line
@@ -186,11 +186,12 @@ bitmap_ipmac_list(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
				htonl(map->first_ip + id));
		if (elem->match == MAC_FILLED)
			NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
				elem->ether);
		if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
				    htonl(map->first_ip + id)) ||
		    (elem->match == MAC_FILLED &&
		     nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN,
			     elem->ether)))
			goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, atd);
@@ -314,14 +315,16 @@ bitmap_ipmac_tlist(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
				htonl(map->first_ip + id));
		if (elem->match == MAC_FILLED)
			NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
				elem->ether);
		if (nla_put_ipaddr4(skb, IPSET_ATTR_IP,
				    htonl(map->first_ip + id)) ||
		    (elem->match == MAC_FILLED &&
		     nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN,
			     elem->ether)))
		    goto nla_put_failure;
		timeout = elem->match == MAC_UNSET ? elem->timeout
				: ip_set_timeout_get(elem->timeout);
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
		if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout)))
		    goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, atd);
@@ -438,14 +441,16 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
	if (!nested)
		goto nla_put_failure;
	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
		      htonl(sizeof(*map)
			    + (map->last_ip - map->first_ip + 1) * map->dsize));
	if (with_timeout(map->timeout))
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
	if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
	    nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
	    nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
	    nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
			  htonl(sizeof(*map) +
				((map->last_ip - map->first_ip + 1) *
				 map->dsize))) ||
	    (with_timeout(map->timeout) &&
	     nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
		goto nla_put_failure;
	ipset_nest_end(skb, nested);

	return 0;
+16 −13
Original line number Diff line number Diff line
@@ -96,8 +96,9 @@ bitmap_port_list(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
			      htons(map->first_port + id));
		if (nla_put_net16(skb, IPSET_ATTR_PORT,
				  htons(map->first_port + id)))
			goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, atd);
@@ -183,10 +184,11 @@ bitmap_port_tlist(const struct ip_set *set,
			} else
				goto nla_put_failure;
		}
		NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
			      htons(map->first_port + id));
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
			      htonl(ip_set_timeout_get(members[id])));
		if (nla_put_net16(skb, IPSET_ATTR_PORT,
				  htons(map->first_port + id)) ||
		    nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
				  htonl(ip_set_timeout_get(members[id]))))
			goto nla_put_failure;
		ipset_nest_end(skb, nested);
	}
	ipset_nest_end(skb, adt);
@@ -320,13 +322,14 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
	if (!nested)
		goto nla_put_failure;
	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
	NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
		      htonl(sizeof(*map) + map->memsize));
	if (with_timeout(map->timeout))
		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
	if (nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
	    nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)) ||
	    nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
	    nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
			  htonl(sizeof(*map) + map->memsize)) ||
	    (with_timeout(map->timeout) &&
	     nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
		goto nla_put_failure;
	ipset_nest_end(skb, nested);

	return 0;
Loading