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

net_sched: act_ct: use RCU in tcf_ct_dump()

Also storing tcf_action into struct tcf_ct_params
makes sure there is no discrepancy in tcf_ct_act().

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250709090204.797558-5-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
554e66ba ba9dc9c1

+16 -16
+1 -1
include/net/tc_act/tc_ct.h
··· 13 13 struct nf_conntrack_helper *helper; 14 14 struct nf_conn *tmpl; 15 15 u16 zone; 16 - 16 + int action; 17 17 u32 mark; 18 18 u32 mark_mask; 19 19
+15 -15
net/sched/act_ct.c
··· 977 977 978 978 p = rcu_dereference_bh(c->params); 979 979 980 - retval = READ_ONCE(c->tcf_action); 980 + retval = p->action; 981 981 commit = p->ct_action & TCA_CT_ACT_COMMIT; 982 982 clear = p->ct_action & TCA_CT_ACT_CLEAR; 983 983 tmpl = p->tmpl; ··· 1409 1409 if (err) 1410 1410 goto cleanup; 1411 1411 1412 + params->action = parm->action; 1412 1413 spin_lock_bh(&c->tcf_lock); 1413 1414 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); 1414 1415 params = rcu_replace_pointer(c->params, params, ··· 1443 1442 } 1444 1443 1445 1444 static int tcf_ct_dump_key_val(struct sk_buff *skb, 1446 - void *val, int val_type, 1447 - void *mask, int mask_type, 1445 + const void *val, int val_type, 1446 + const void *mask, int mask_type, 1448 1447 int len) 1449 1448 { 1450 1449 int err; ··· 1465 1464 return 0; 1466 1465 } 1467 1466 1468 - static int tcf_ct_dump_nat(struct sk_buff *skb, struct tcf_ct_params *p) 1467 + static int tcf_ct_dump_nat(struct sk_buff *skb, const struct tcf_ct_params *p) 1469 1468 { 1470 - struct nf_nat_range2 *range = &p->range; 1469 + const struct nf_nat_range2 *range = &p->range; 1471 1470 1472 1471 if (!(p->ct_action & TCA_CT_ACT_NAT)) 1473 1472 return 0; ··· 1505 1504 return 0; 1506 1505 } 1507 1506 1508 - static int tcf_ct_dump_helper(struct sk_buff *skb, struct nf_conntrack_helper *helper) 1507 + static int tcf_ct_dump_helper(struct sk_buff *skb, 1508 + const struct nf_conntrack_helper *helper) 1509 1509 { 1510 1510 if (!helper) 1511 1511 return 0; ··· 1523 1521 int bind, int ref) 1524 1522 { 1525 1523 unsigned char *b = skb_tail_pointer(skb); 1526 - struct tcf_ct *c = to_ct(a); 1527 - struct tcf_ct_params *p; 1528 - 1524 + const struct tcf_ct *c = to_ct(a); 1525 + const struct tcf_ct_params *p; 1529 1526 struct tc_ct opt = { 1530 1527 .index = c->tcf_index, 1531 1528 .refcnt = refcount_read(&c->tcf_refcnt) - ref, ··· 1532 1531 }; 1533 1532 struct tcf_t t; 1534 1533 1535 - spin_lock_bh(&c->tcf_lock); 1536 - p = rcu_dereference_protected(c->params, 1537 - lockdep_is_held(&c->tcf_lock)); 1538 - opt.action = c->tcf_action; 1534 + rcu_read_lock(); 1535 + p = rcu_dereference(c->params); 1536 + opt.action = p->action; 1539 1537 1540 1538 if (tcf_ct_dump_key_val(skb, 1541 1539 &p->ct_action, TCA_CT_ACTION, ··· 1579 1579 tcf_tm_dump(&t, &c->tcf_tm); 1580 1580 if (nla_put_64bit(skb, TCA_CT_TM, sizeof(t), &t, TCA_CT_PAD)) 1581 1581 goto nla_put_failure; 1582 - spin_unlock_bh(&c->tcf_lock); 1582 + rcu_read_unlock(); 1583 1583 1584 1584 return skb->len; 1585 1585 nla_put_failure: 1586 - spin_unlock_bh(&c->tcf_lock); 1586 + rcu_read_unlock(); 1587 1587 nlmsg_trim(skb, b); 1588 1588 return -1; 1589 1589 }