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

Commit 60eb1894 authored by Patrick McHardy's avatar Patrick McHardy Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: handle more than 8 * PAGE_SIZE set name allocations



We currently have a limit of 8 * PAGE_SIZE anonymous sets. Lift that limit
by continuing the scan if the entire page is exhausted.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d60ce62f
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -2049,7 +2049,7 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
	const struct nft_set *i;
	const char *p;
	unsigned long *inuse;
	unsigned int n = 0;
	unsigned int n = 0, min = 0;

	p = strnchr(name, IFNAMSIZ, '%');
	if (p != NULL) {
@@ -2059,23 +2059,28 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
		inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
		if (inuse == NULL)
			return -ENOMEM;

cont:
		list_for_each_entry(i, &ctx->table->sets, list) {
			int tmp;

			if (!sscanf(i->name, name, &tmp))
				continue;
			if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE)
			if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
				continue;

			set_bit(tmp, inuse);
			set_bit(tmp - min, inuse);
		}

		n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
		if (n >= BITS_PER_BYTE * PAGE_SIZE) {
			min += BITS_PER_BYTE * PAGE_SIZE;
			memset(inuse, 0, PAGE_SIZE);
			goto cont;
		}
		free_page((unsigned long)inuse);
	}

	snprintf(set->name, sizeof(set->name), name, n);
	snprintf(set->name, sizeof(set->name), name, min + n);
	list_for_each_entry(i, &ctx->table->sets, list) {
		if (!strcmp(set->name, i->name))
			return -ENFILE;