On Sat, Mar 08, 2025 at 08:54:51AM +0000, Simon Horman wrote: > On Fri, Mar 07, 2025 at 03:19:01AM +0000, Hangbin Liu wrote: > > ... > > > @@ -616,9 +615,22 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) > > return; > > > > mutex_lock(&bond->ipsec_lock); > > - list_for_each_entry(ipsec, &bond->ipsec_list, list) { > > - if (!ipsec->xs->xso.real_dev) > > + list_for_each_entry_safe(ipsec, tmp_ipsec, &bond->ipsec_list, list) { > > + spin_lock_bh(&ipsec->xs->lock); > > + if (!ipsec->xs->xso.real_dev) { > > + spin_unlock_bh(&ipsec->xs->lock); > > continue; > > + } > > + > > + if (ipsec->xs->km.state == XFRM_STATE_DEAD) { > > + list_del(&ipsec->list); > > + kfree(ipsec); > > Hi Hangbin, > > Apologies if this was covered elsewhere, but ipsec is kfree'd here... Oh.. I need to get the xs with xs = ipsec->xs, then hold the xs lock. Thanks Hangbin > > > > + /* Need to free device here, or the xs->xso.real_dev > > + * may changed in bond_ipsec_add_sa_all and free > > + * on old device will never be called. > > + */ > > + goto next; > > + } > > > > if (!real_dev->xfrmdev_ops || > > !real_dev->xfrmdev_ops->xdo_dev_state_delete || > > @@ -626,11 +638,20 @@ static void bond_ipsec_del_sa_all(struct bonding *bond) > > slave_warn(bond_dev, real_dev, > > "%s: no slave xdo_dev_state_delete\n", > > __func__); > > - } else { > > - real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs); > > - if (real_dev->xfrmdev_ops->xdo_dev_state_free) > > - real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs); > > + spin_unlock_bh(&ipsec->xs->lock); > > + continue; > > } > > + > > + real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs); > > + > > +next: > > + /* set real_dev to NULL in case __xfrm_state_delete() is called in parallel */ > > + ipsec->xs->xso.real_dev = NULL; > > ... and the dereferenced here. > > Flagged by Smatch. > > > + > > + /* Unlock before freeing device state, it could sleep. */ > > + spin_unlock_bh(&ipsec->xs->lock); > > + if (real_dev->xfrmdev_ops->xdo_dev_state_free) > > + real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs); > > } > > mutex_unlock(&bond->ipsec_lock); > > } > > ...