summaryrefslogtreecommitdiff
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2025-04-17 11:52:07 +0300
committerSteffen Klassert <steffen.klassert@secunet.com>2025-04-17 11:52:07 +0300
commit197c2974cb49495925783220b07f5cd0c5ceec08 (patch)
treee8e20a650ca7aeb55410b9e00ce8f034924ae3c8 /net/xfrm/xfrm_state.c
parent20eb35da409fa60fa03ea828cd3d1d9c8a51e103 (diff)
parentd2fddbd3479928e52061e1c8dd302006b6283ce8 (diff)
downloadlinux-197c2974cb49495925783220b07f5cd0c5ceec08.tar.xz
Merge branch 'xfrm & bonding: Correct use of xso.real_dev'
Cosmin Ratiu says: ==================== This patch series was motivated by fixing a few bugs in the bonding driver related to xfrm state migration on device failover. struct xfrm_dev_offload has two net_device pointers: dev and real_dev. The first one is the device the xfrm_state is offloaded on and the second one is used by the bonding driver to manage the underlying device xfrm_states are actually offloaded on. When bonding isn't used, the two pointers are the same. This causes confusion in drivers: Which device pointer should they use? If they want to support bonding, they need to only use real_dev and never look at dev. Furthermore, real_dev is used without proper locking from multiple code paths and changing it is dangerous. See commit [1] for example. This patch series clears things out by removing all uses of real_dev from outside the bonding driver. Then, the bonding driver is refactored to fix a couple of long standing races and the original bug which motivated this patch series. [1] commit f8cde9805981 ("bonding: fix xfrm real_dev null pointer dereference") v2 -> v3: Added a comment with locking expectations for real_dev. Removed unnecessary bond variable from bond_ipsec_del_sa(). v1 -> v2: Added missing kdoc for various functions. Made bond_ipsec_del_sa() use xso.real_dev instead of curr_active_slave. ==================== Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 341d79ecb5c2..3c2e27e5a1e3 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -767,7 +767,7 @@ void xfrm_dev_state_delete(struct xfrm_state *x)
struct net_device *dev = READ_ONCE(xso->dev);
if (dev) {
- dev->xfrmdev_ops->xdo_dev_state_delete(x);
+ dev->xfrmdev_ops->xdo_dev_state_delete(dev, x);
spin_lock_bh(&xfrm_state_dev_gc_lock);
hlist_add_head(&x->dev_gclist, &xfrm_state_dev_gc_list);
spin_unlock_bh(&xfrm_state_dev_gc_lock);
@@ -789,7 +789,7 @@ void xfrm_dev_state_free(struct xfrm_state *x)
spin_unlock_bh(&xfrm_state_dev_gc_lock);
if (dev->xfrmdev_ops->xdo_dev_state_free)
- dev->xfrmdev_ops->xdo_dev_state_free(x);
+ dev->xfrmdev_ops->xdo_dev_state_free(dev, x);
WRITE_ONCE(xso->dev, NULL);
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
netdev_put(dev, &xso->dev_tracker);
@@ -1551,19 +1551,19 @@ found:
if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) {
struct xfrm_dev_offload *xdo = &pol->xdo;
struct xfrm_dev_offload *xso = &x->xso;
+ struct net_device *dev = xdo->dev;
xso->type = XFRM_DEV_OFFLOAD_PACKET;
xso->dir = xdo->dir;
- xso->dev = xdo->dev;
- xso->real_dev = xdo->real_dev;
+ xso->dev = dev;
xso->flags = XFRM_DEV_OFFLOAD_FLAG_ACQ;
- netdev_hold(xso->dev, &xso->dev_tracker, GFP_ATOMIC);
- error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x, NULL);
+ netdev_hold(dev, &xso->dev_tracker, GFP_ATOMIC);
+ error = dev->xfrmdev_ops->xdo_dev_state_add(dev, x,
+ NULL);
if (error) {
xso->dir = 0;
- netdev_put(xso->dev, &xso->dev_tracker);
+ netdev_put(dev, &xso->dev_tracker);
xso->dev = NULL;
- xso->real_dev = NULL;
xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
x->km.state = XFRM_STATE_DEAD;
to_put = x;