Skip to content

Commit 07b7390

Browse files
author
CKI KWF Bot
committed
Merge: xfrm & bonding: Correct use of xso.real_dev
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/970 JIRA: https://issues.redhat.com/browse/RHEL-73802 JIRA: https://issues.redhat.com/browse/RHEL-97184 This patch set fixes the bonding ipsec offload race conditions. Also backport patchset `Support PMTU in tunnel mode for packet offload` as patch `bonding: Mark active offloaded xfrm_states` need it. Signed-off-by: Hangbin Liu <haliu@redhat.com> Approved-by: Sabrina Dubroca <sdubroca@redhat.com> Approved-by: José Ignacio Tornos Martínez <jtornosm@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 9ff7165 + d31b9f5 commit 07b7390

File tree

17 files changed

+261
-333
lines changed

17 files changed

+261
-333
lines changed

Documentation/networking/xfrm_device.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,13 @@ Callbacks to implement
6565
/* from include/linux/netdevice.h */
6666
struct xfrmdev_ops {
6767
/* Crypto and Packet offload callbacks */
68-
int (*xdo_dev_state_add) (struct xfrm_state *x, struct netlink_ext_ack *extack);
69-
void (*xdo_dev_state_delete) (struct xfrm_state *x);
70-
void (*xdo_dev_state_free) (struct xfrm_state *x);
68+
int (*xdo_dev_state_add)(struct net_device *dev,
69+
struct xfrm_state *x,
70+
struct netlink_ext_ack *extack);
71+
void (*xdo_dev_state_delete)(struct net_device *dev,
72+
struct xfrm_state *x);
73+
void (*xdo_dev_state_free)(struct net_device *dev,
74+
struct xfrm_state *x);
7175
bool (*xdo_dev_offload_ok) (struct sk_buff *skb,
7276
struct xfrm_state *x);
7377
void (*xdo_dev_state_advance_esn) (struct xfrm_state *x);
@@ -126,7 +130,8 @@ been setup for offload, it first calls into xdo_dev_offload_ok() with
126130
the skb and the intended offload state to ask the driver if the offload
127131
will serviceable. This can check the packet information to be sure the
128132
offload can be supported (e.g. IPv4 or IPv6, no IPv4 options, etc) and
129-
return true of false to signify its support.
133+
return true or false to signify its support. In case driver doesn't implement
134+
this callback, the stack provides reasonable defaults.
130135

131136
Crypto offload mode:
132137
When ready to send, the driver needs to inspect the Tx packet for the

drivers/net/bonding/bond_main.c

Lines changed: 63 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -452,13 +452,14 @@ static struct net_device *bond_ipsec_dev(struct xfrm_state *xs)
452452

453453
/**
454454
* bond_ipsec_add_sa - program device with a security association
455+
* @bond_dev: pointer to the bond net device
455456
* @xs: pointer to transformer state struct
456457
* @extack: extack point to fill failure reason
457458
**/
458-
static int bond_ipsec_add_sa(struct xfrm_state *xs,
459+
static int bond_ipsec_add_sa(struct net_device *bond_dev,
460+
struct xfrm_state *xs,
459461
struct netlink_ext_ack *extack)
460462
{
461-
struct net_device *bond_dev = xs->xso.dev;
462463
struct net_device *real_dev;
463464
netdevice_tracker tracker;
464465
struct bond_ipsec *ipsec;
@@ -494,9 +495,9 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
494495
goto out;
495496
}
496497

497-
xs->xso.real_dev = real_dev;
498-
err = real_dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
498+
err = real_dev->xfrmdev_ops->xdo_dev_state_add(real_dev, xs, extack);
499499
if (!err) {
500+
xs->xso.real_dev = real_dev;
500501
ipsec->xs = xs;
501502
INIT_LIST_HEAD(&ipsec->list);
502503
mutex_lock(&bond->ipsec_lock);
@@ -538,66 +539,53 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
538539
if (ipsec->xs->xso.real_dev == real_dev)
539540
continue;
540541

541-
ipsec->xs->xso.real_dev = real_dev;
542-
if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
542+
if (real_dev->xfrmdev_ops->xdo_dev_state_add(real_dev,
543+
ipsec->xs, NULL)) {
543544
slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
544-
ipsec->xs->xso.real_dev = NULL;
545+
continue;
545546
}
547+
548+
spin_lock_bh(&ipsec->xs->lock);
549+
/* xs might have been killed by the user during the migration
550+
* to the new dev, but bond_ipsec_del_sa() should have done
551+
* nothing, as xso.real_dev is NULL.
552+
* Delete it from the device we just added it to. The pending
553+
* bond_ipsec_free_sa() call will do the rest of the cleanup.
554+
*/
555+
if (ipsec->xs->km.state == XFRM_STATE_DEAD &&
556+
real_dev->xfrmdev_ops->xdo_dev_state_delete)
557+
real_dev->xfrmdev_ops->xdo_dev_state_delete(real_dev,
558+
ipsec->xs);
559+
ipsec->xs->xso.real_dev = real_dev;
560+
spin_unlock_bh(&ipsec->xs->lock);
546561
}
547562
out:
548563
mutex_unlock(&bond->ipsec_lock);
549564
}
550565

551566
/**
552567
* bond_ipsec_del_sa - clear out this specific SA
568+
* @bond_dev: pointer to the bond net device
553569
* @xs: pointer to transformer state struct
554570
**/
555-
static void bond_ipsec_del_sa(struct xfrm_state *xs)
571+
static void bond_ipsec_del_sa(struct net_device *bond_dev,
572+
struct xfrm_state *xs)
556573
{
557-
struct net_device *bond_dev = xs->xso.dev;
558574
struct net_device *real_dev;
559-
netdevice_tracker tracker;
560-
struct bond_ipsec *ipsec;
561-
struct bonding *bond;
562-
struct slave *slave;
563575

564-
if (!bond_dev)
576+
if (!bond_dev || !xs->xso.real_dev)
565577
return;
566578

567-
rcu_read_lock();
568-
bond = netdev_priv(bond_dev);
569-
slave = rcu_dereference(bond->curr_active_slave);
570-
real_dev = slave ? slave->dev : NULL;
571-
netdev_hold(real_dev, &tracker, GFP_ATOMIC);
572-
rcu_read_unlock();
573-
574-
if (!slave)
575-
goto out;
576-
577-
if (!xs->xso.real_dev)
578-
goto out;
579-
580-
WARN_ON(xs->xso.real_dev != real_dev);
579+
real_dev = xs->xso.real_dev;
581580

582581
if (!real_dev->xfrmdev_ops ||
583582
!real_dev->xfrmdev_ops->xdo_dev_state_delete ||
584583
netif_is_bond_master(real_dev)) {
585584
slave_warn(bond_dev, real_dev, "%s: no slave xdo_dev_state_delete\n", __func__);
586-
goto out;
585+
return;
587586
}
588587

589-
real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
590-
out:
591-
netdev_put(real_dev, &tracker);
592-
mutex_lock(&bond->ipsec_lock);
593-
list_for_each_entry(ipsec, &bond->ipsec_list, list) {
594-
if (ipsec->xs == xs) {
595-
list_del(&ipsec->list);
596-
kfree(ipsec);
597-
break;
598-
}
599-
}
600-
mutex_unlock(&bond->ipsec_lock);
588+
real_dev->xfrmdev_ops->xdo_dev_state_delete(real_dev, xs);
601589
}
602590

603591
static void bond_ipsec_del_sa_all(struct bonding *bond)
@@ -623,46 +611,55 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
623611
slave_warn(bond_dev, real_dev,
624612
"%s: no slave xdo_dev_state_delete\n",
625613
__func__);
626-
} else {
627-
real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
628-
if (real_dev->xfrmdev_ops->xdo_dev_state_free)
629-
real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
614+
continue;
630615
}
616+
617+
spin_lock_bh(&ipsec->xs->lock);
618+
ipsec->xs->xso.real_dev = NULL;
619+
/* Don't double delete states killed by the user. */
620+
if (ipsec->xs->km.state != XFRM_STATE_DEAD)
621+
real_dev->xfrmdev_ops->xdo_dev_state_delete(real_dev,
622+
ipsec->xs);
623+
spin_unlock_bh(&ipsec->xs->lock);
624+
625+
if (real_dev->xfrmdev_ops->xdo_dev_state_free)
626+
real_dev->xfrmdev_ops->xdo_dev_state_free(real_dev,
627+
ipsec->xs);
631628
}
632629
mutex_unlock(&bond->ipsec_lock);
633630
}
634631

635-
static void bond_ipsec_free_sa(struct xfrm_state *xs)
632+
static void bond_ipsec_free_sa(struct net_device *bond_dev,
633+
struct xfrm_state *xs)
636634
{
637-
struct net_device *bond_dev = xs->xso.dev;
638635
struct net_device *real_dev;
639-
netdevice_tracker tracker;
636+
struct bond_ipsec *ipsec;
640637
struct bonding *bond;
641-
struct slave *slave;
642638

643639
if (!bond_dev)
644640
return;
645641

646-
rcu_read_lock();
647642
bond = netdev_priv(bond_dev);
648-
slave = rcu_dereference(bond->curr_active_slave);
649-
real_dev = slave ? slave->dev : NULL;
650-
netdev_hold(real_dev, &tracker, GFP_ATOMIC);
651-
rcu_read_unlock();
652-
653-
if (!slave)
654-
goto out;
655643

644+
mutex_lock(&bond->ipsec_lock);
656645
if (!xs->xso.real_dev)
657646
goto out;
658647

659-
WARN_ON(xs->xso.real_dev != real_dev);
648+
real_dev = xs->xso.real_dev;
660649

661-
if (real_dev && real_dev->xfrmdev_ops &&
650+
xs->xso.real_dev = NULL;
651+
if (real_dev->xfrmdev_ops &&
662652
real_dev->xfrmdev_ops->xdo_dev_state_free)
663-
real_dev->xfrmdev_ops->xdo_dev_state_free(xs);
653+
real_dev->xfrmdev_ops->xdo_dev_state_free(real_dev, xs);
664654
out:
665-
netdev_put(real_dev, &tracker);
655+
list_for_each_entry(ipsec, &bond->ipsec_list, list) {
656+
if (ipsec->xs == xs) {
657+
list_del(&ipsec->list);
658+
kfree(ipsec);
659+
break;
660+
}
661+
}
662+
mutex_unlock(&bond->ipsec_lock);
666663
}
667664

668665
/**
@@ -673,22 +670,16 @@ static void bond_ipsec_free_sa(struct xfrm_state *xs)
673670
static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
674671
{
675672
struct net_device *real_dev;
676-
bool ok = false;
677673

678674
rcu_read_lock();
679675
real_dev = bond_ipsec_dev(xs);
680-
if (!real_dev)
681-
goto out;
682-
683-
if (!real_dev->xfrmdev_ops ||
684-
!real_dev->xfrmdev_ops->xdo_dev_offload_ok ||
685-
netif_is_bond_master(real_dev))
686-
goto out;
676+
if (!real_dev || netif_is_bond_master(real_dev)) {
677+
rcu_read_unlock();
678+
return false;
679+
}
687680

688-
ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
689-
out:
690681
rcu_read_unlock();
691-
return ok;
682+
return true;
692683
}
693684

694685
/**

drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6489,10 +6489,11 @@ static const struct tlsdev_ops cxgb4_ktls_ops = {
64896489

64906490
#if IS_ENABLED(CONFIG_CHELSIO_IPSEC_INLINE)
64916491

6492-
static int cxgb4_xfrm_add_state(struct xfrm_state *x,
6492+
static int cxgb4_xfrm_add_state(struct net_device *dev,
6493+
struct xfrm_state *x,
64936494
struct netlink_ext_ack *extack)
64946495
{
6495-
struct adapter *adap = netdev2adap(x->xso.dev);
6496+
struct adapter *adap = netdev2adap(dev);
64966497
int ret;
64976498

64986499
if (!mutex_trylock(&uld_mutex)) {
@@ -6503,17 +6504,18 @@ static int cxgb4_xfrm_add_state(struct xfrm_state *x,
65036504
if (ret)
65046505
goto out_unlock;
65056506

6506-
ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_add(x, extack);
6507+
ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_add(dev, x,
6508+
extack);
65076509

65086510
out_unlock:
65096511
mutex_unlock(&uld_mutex);
65106512

65116513
return ret;
65126514
}
65136515

6514-
static void cxgb4_xfrm_del_state(struct xfrm_state *x)
6516+
static void cxgb4_xfrm_del_state(struct net_device *dev, struct xfrm_state *x)
65156517
{
6516-
struct adapter *adap = netdev2adap(x->xso.dev);
6518+
struct adapter *adap = netdev2adap(dev);
65176519

65186520
if (!mutex_trylock(&uld_mutex)) {
65196521
dev_dbg(adap->pdev_dev,
@@ -6523,15 +6525,15 @@ static void cxgb4_xfrm_del_state(struct xfrm_state *x)
65236525
if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
65246526
goto out_unlock;
65256527

6526-
adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_delete(x);
6528+
adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_delete(dev, x);
65276529

65286530
out_unlock:
65296531
mutex_unlock(&uld_mutex);
65306532
}
65316533

6532-
static void cxgb4_xfrm_free_state(struct xfrm_state *x)
6534+
static void cxgb4_xfrm_free_state(struct net_device *dev, struct xfrm_state *x)
65336535
{
6534-
struct adapter *adap = netdev2adap(x->xso.dev);
6536+
struct adapter *adap = netdev2adap(dev);
65356537

65366538
if (!mutex_trylock(&uld_mutex)) {
65376539
dev_dbg(adap->pdev_dev,
@@ -6541,32 +6543,12 @@ static void cxgb4_xfrm_free_state(struct xfrm_state *x)
65416543
if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
65426544
goto out_unlock;
65436545

6544-
adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_free(x);
6546+
adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_free(dev, x);
65456547

65466548
out_unlock:
65476549
mutex_unlock(&uld_mutex);
65486550
}
65496551

6550-
static bool cxgb4_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
6551-
{
6552-
struct adapter *adap = netdev2adap(x->xso.dev);
6553-
bool ret = false;
6554-
6555-
if (!mutex_trylock(&uld_mutex)) {
6556-
dev_dbg(adap->pdev_dev,
6557-
"crypto uld critical resource is under use\n");
6558-
return ret;
6559-
}
6560-
if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
6561-
goto out_unlock;
6562-
6563-
ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_offload_ok(skb, x);
6564-
6565-
out_unlock:
6566-
mutex_unlock(&uld_mutex);
6567-
return ret;
6568-
}
6569-
65706552
static void cxgb4_advance_esn_state(struct xfrm_state *x)
65716553
{
65726554
struct adapter *adap = netdev2adap(x->xso.dev);
@@ -6592,7 +6574,6 @@ static const struct xfrmdev_ops cxgb4_xfrmdev_ops = {
65926574
.xdo_dev_state_add = cxgb4_xfrm_add_state,
65936575
.xdo_dev_state_delete = cxgb4_xfrm_del_state,
65946576
.xdo_dev_state_free = cxgb4_xfrm_free_state,
6595-
.xdo_dev_offload_ok = cxgb4_ipsec_offload_ok,
65966577
.xdo_dev_state_advance_esn = cxgb4_advance_esn_state,
65976578
};
65986579

0 commit comments

Comments
 (0)