Commit 1e13f27e authored by Anders Grahn's avatar Anders Grahn Committed by Florian Westphal
Browse files

netfilter: nft_counter: fix reset of counters on 32bit archs



nft_counter_reset() calls u64_stats_add() with a negative value to reset
the counter. This will work on 64bit archs, hence the negative value
added will wrap as a 64bit value which then can wrap the stat counter as
well.

On 32bit archs, the added negative value will wrap as a 32bit value and
_not_ wrapping the stat counter properly. In most cases, this would just
lead to a very large 32bit value being added to the stat counter.

Fix by introducing u64_stats_sub().

Fixes: 4a1d3acd ("netfilter: nft_counter: Use u64_stats_t for statistic.")
Signed-off-by: default avatarAnders Grahn <anders.grahn@gmail.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
parent 2f635adb
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -97,6 +97,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsigned long val)
	local64_add(val, &p->v);
}

static inline void u64_stats_sub(u64_stats_t *p, s64 val)
{
	local64_sub(val, &p->v);
}

static inline void u64_stats_inc(u64_stats_t *p)
{
	local64_inc(&p->v);
@@ -145,6 +150,11 @@ static inline void u64_stats_add(u64_stats_t *p, unsigned long val)
	p->v += val;
}

static inline void u64_stats_sub(u64_stats_t *p, s64 val)
{
	p->v -= val;
}

static inline void u64_stats_inc(u64_stats_t *p)
{
	p->v++;
+2 −2
Original line number Diff line number Diff line
@@ -117,8 +117,8 @@ static void nft_counter_reset(struct nft_counter_percpu_priv *priv,
	nft_sync = this_cpu_ptr(&nft_counter_sync);

	u64_stats_update_begin(nft_sync);
	u64_stats_add(&this_cpu->packets, -total->packets);
	u64_stats_add(&this_cpu->bytes, -total->bytes);
	u64_stats_sub(&this_cpu->packets, total->packets);
	u64_stats_sub(&this_cpu->bytes, total->bytes);
	u64_stats_update_end(nft_sync);

	local_bh_enable();