Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 4a1d3acd6ea8 ("netfilter: nft_counter: Use u64_stats_t for statistic.")
Signed-off-by: Anders Grahn <anders.grahn@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>

authored by

Anders Grahn and committed by
Florian Westphal
1e13f27e 2f635adb

+12 -2
+10
include/linux/u64_stats_sync.h
··· 97 97 local64_add(val, &p->v); 98 98 } 99 99 100 + static inline void u64_stats_sub(u64_stats_t *p, s64 val) 101 + { 102 + local64_sub(val, &p->v); 103 + } 104 + 100 105 static inline void u64_stats_inc(u64_stats_t *p) 101 106 { 102 107 local64_inc(&p->v); ··· 148 143 static inline void u64_stats_add(u64_stats_t *p, unsigned long val) 149 144 { 150 145 p->v += val; 146 + } 147 + 148 + static inline void u64_stats_sub(u64_stats_t *p, s64 val) 149 + { 150 + p->v -= val; 151 151 } 152 152 153 153 static inline void u64_stats_inc(u64_stats_t *p)
+2 -2
net/netfilter/nft_counter.c
··· 117 117 nft_sync = this_cpu_ptr(&nft_counter_sync); 118 118 119 119 u64_stats_update_begin(nft_sync); 120 - u64_stats_add(&this_cpu->packets, -total->packets); 121 - u64_stats_add(&this_cpu->bytes, -total->bytes); 120 + u64_stats_sub(&this_cpu->packets, total->packets); 121 + u64_stats_sub(&this_cpu->bytes, total->bytes); 122 122 u64_stats_update_end(nft_sync); 123 123 124 124 local_bh_enable();