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

Commit ef5b6e12 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: ipset: fix interface comparision in hash-netiface sets



ifname_compare() assumes that skb->dev is zero-padded,
e.g 'eth1\0\0\0\0\0...'. This isn't always the case. e1000 driver does

strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);

in e1000_probe(), so once device is registered dev->name memory contains
'eth1\0:0:3\0\0\0' (or something like that), which makes eth1 compare
fail.

Use plain strcmp() instead.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 8b8e4bc0
Loading
Loading
Loading
Loading
+4 −28
Original line number Original line Diff line number Diff line
@@ -38,30 +38,6 @@ struct iface_node {


#define iface_data(n)	(rb_entry(n, struct iface_node, node)->iface)
#define iface_data(n)	(rb_entry(n, struct iface_node, node)->iface)


static inline long
ifname_compare(const char *_a, const char *_b)
{
	const long *a = (const long *)_a;
	const long *b = (const long *)_b;

	BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
	if (a[0] != b[0])
		return a[0] - b[0];
	if (IFNAMSIZ > sizeof(long)) {
		if (a[1] != b[1])
			return a[1] - b[1];
	}
	if (IFNAMSIZ > 2 * sizeof(long)) {
		if (a[2] != b[2])
			return a[2] - b[2];
	}
	if (IFNAMSIZ > 3 * sizeof(long)) {
		if (a[3] != b[3])
			return a[3] - b[3];
	}
	return 0;
}

static void
static void
rbtree_destroy(struct rb_root *root)
rbtree_destroy(struct rb_root *root)
{
{
@@ -99,7 +75,7 @@ iface_test(struct rb_root *root, const char **iface)


	while (n) {
	while (n) {
		const char *d = iface_data(n);
		const char *d = iface_data(n);
		long res = ifname_compare(*iface, d);
		int res = strcmp(*iface, d);


		if (res < 0)
		if (res < 0)
			n = n->rb_left;
			n = n->rb_left;
@@ -121,7 +97,7 @@ iface_add(struct rb_root *root, const char **iface)


	while (*n) {
	while (*n) {
		char *ifname = iface_data(*n);
		char *ifname = iface_data(*n);
		long res = ifname_compare(*iface, ifname);
		int res = strcmp(*iface, ifname);


		p = *n;
		p = *n;
		if (res < 0)
		if (res < 0)
@@ -366,7 +342,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
	struct hash_netiface4_elem data = { .cidr = HOST_MASK };
	struct hash_netiface4_elem data = { .cidr = HOST_MASK };
	u32 ip = 0, ip_to, last;
	u32 ip = 0, ip_to, last;
	u32 timeout = h->timeout;
	u32 timeout = h->timeout;
	char iface[IFNAMSIZ] = {};
	char iface[IFNAMSIZ];
	int ret;
	int ret;


	if (unlikely(!tb[IPSET_ATTR_IP] ||
	if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -663,7 +639,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
	ipset_adtfn adtfn = set->variant->adt[adt];
	ipset_adtfn adtfn = set->variant->adt[adt];
	struct hash_netiface6_elem data = { .cidr = HOST_MASK };
	struct hash_netiface6_elem data = { .cidr = HOST_MASK };
	u32 timeout = h->timeout;
	u32 timeout = h->timeout;
	char iface[IFNAMSIZ] = {};
	char iface[IFNAMSIZ];
	int ret;
	int ret;


	if (unlikely(!tb[IPSET_ATTR_IP] ||
	if (unlikely(!tb[IPSET_ATTR_IP] ||