Skip to content

Commit

Permalink
netfilter: xt_hashlimit: fix build error caused by 64bit division
Browse files Browse the repository at this point in the history
64bit division causes build/link errors on 32bit architectures. It
prints out error messages like:

ERROR: "__aeabi_uldivmod" [net/netfilter/xt_hashlimit.ko] undefined!

The value of avg passed through by userspace in BYTE mode cannot exceed
U32_MAX. Which means 64bit division in user2rate_bytes is unnecessary.
To fix this I have changed the type of param 'user' to u32.

Since anything greater than U32_MAX is an invalid input we error out in
hashlimit_mt_check_common() when this is the case.

Changes in v2:
	Making return type as u32 would cause an overflow for small
	values of 'user' (for example 2, 3 etc). To avoid this I bumped up
	'r' to u64 again as well as the return type. This is OK since the
	variable that stores the result is u64. We still avoid 64bit
	division here since 'user' is u32.

Fixes: bea7464 ("netfilter: xt_hashlimit: add rate match mode")
Signed-off-by: Vishwanath Pai <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
  • Loading branch information
Vishwanath Pai authored and ummakynes committed Sep 8, 2017
1 parent 05d0eae commit 90c4ae4
Showing 1 changed file with 7 additions and 5 deletions.
12 changes: 7 additions & 5 deletions net/netfilter/xt_hashlimit.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter/xt_hashlimit.h>
#include <linux/mutex.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <[email protected]>");
Expand Down Expand Up @@ -527,12 +528,12 @@ static u64 user2rate(u64 user)
}
}

static u64 user2rate_bytes(u64 user)
static u64 user2rate_bytes(u32 user)
{
u64 r;

r = user ? 0xFFFFFFFFULL / user : 0xFFFFFFFFULL;
r = (r - 1) << 4;
r = user ? U32_MAX / user : U32_MAX;
r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
return r;
}

Expand Down Expand Up @@ -588,7 +589,8 @@ static void rateinfo_init(struct dsthash_ent *dh,
dh->rateinfo.prev_window = 0;
dh->rateinfo.current_rate = 0;
if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
dh->rateinfo.rate = user2rate_bytes(hinfo->cfg.avg);
dh->rateinfo.rate =
user2rate_bytes((u32)hinfo->cfg.avg);
if (hinfo->cfg.burst)
dh->rateinfo.burst =
hinfo->cfg.burst * dh->rateinfo.rate;
Expand Down Expand Up @@ -870,7 +872,7 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,

/* Check for overflow. */
if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
if (cfg->avg == 0) {
if (cfg->avg == 0 || cfg->avg > U32_MAX) {
pr_info("hashlimit invalid rate\n");
return -ERANGE;
}
Expand Down

0 comments on commit 90c4ae4

Please sign in to comment.