Skip to content

Commit 5cfe561

Browse files
Sebastian Andrzej Siewiorummakynes
authored andcommitted
netfilter: nft_ct: Use __refcount_inc() for per-CPU nft_ct_pcpu_template.
nft_ct_pcpu_template is a per-CPU variable and relies on disabled BH for its locking. The refcounter is read and if its value is set to one then the refcounter is incremented and variable is used - otherwise it is already in use and left untouched. Without per-CPU locking in local_bh_disable() on PREEMPT_RT the read-then-increment operation is not atomic and therefore racy. This can be avoided by using unconditionally __refcount_inc() which will increment counter and return the old value as an atomic operation. In case the returned counter is not one, the variable is in use and we need to decrement counter. Otherwise we can use it. Use __refcount_inc() instead of read and a conditional increment. Fixes: edee4f1 ("netfilter: nft_ct: add zone id set support") Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Reviewed-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent a466fd7 commit 5cfe561

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

net/netfilter/nft_ct.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
230230
enum ip_conntrack_info ctinfo;
231231
u16 value = nft_reg_load16(&regs->data[priv->sreg]);
232232
struct nf_conn *ct;
233+
int oldcnt;
233234

234235
ct = nf_ct_get(skb, &ctinfo);
235236
if (ct) /* already tracked */
@@ -250,10 +251,11 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
250251

251252
ct = this_cpu_read(nft_ct_pcpu_template);
252253

253-
if (likely(refcount_read(&ct->ct_general.use) == 1)) {
254-
refcount_inc(&ct->ct_general.use);
254+
__refcount_inc(&ct->ct_general.use, &oldcnt);
255+
if (likely(oldcnt == 1)) {
255256
nf_ct_zone_add(ct, &zone);
256257
} else {
258+
refcount_dec(&ct->ct_general.use);
257259
/* previous skb got queued to userspace, allocate temporary
258260
* one until percpu template can be reused.
259261
*/

0 commit comments

Comments
 (0)