net: macsec: fix net device access prior to holding a lock
authorEmeel Hakim <ehakim@nvidia.com>
Sun, 11 Dec 2022 07:55:32 +0000 (09:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 31 Dec 2022 12:32:53 +0000 (13:32 +0100)
[ Upstream commit f3b4a00f0f62da252c598310698dfc82ef2f2e2e ]

Currently macsec offload selection update routine accesses
the net device prior to holding the relevant lock.
Fix by holding the lock prior to the device access.

Fixes: dcb780fb2795 ("net: macsec: add nla support for changing the offloading selection")
Reviewed-by: Raed Salem <raeds@nvidia.com>
Signed-off-by: Emeel Hakim <ehakim@nvidia.com>
Link: https://lore.kernel.org/r/20221211075532.28099-1-ehakim@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/macsec.c

index 2fbac51..038a787 100644 (file)
@@ -2593,7 +2593,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
        const struct macsec_ops *ops;
        struct macsec_context ctx;
        struct macsec_dev *macsec;
-       int ret;
+       int ret = 0;
 
        if (!attrs[MACSEC_ATTR_IFINDEX])
                return -EINVAL;
@@ -2606,28 +2606,36 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
                                        macsec_genl_offload_policy, NULL))
                return -EINVAL;
 
+       rtnl_lock();
+
        dev = get_dev_from_nl(genl_info_net(info), attrs);
-       if (IS_ERR(dev))
-               return PTR_ERR(dev);
+       if (IS_ERR(dev)) {
+               ret = PTR_ERR(dev);
+               goto out;
+       }
        macsec = macsec_priv(dev);
 
-       if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE])
-               return -EINVAL;
+       if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]);
        if (macsec->offload == offload)
-               return 0;
+               goto out;
 
        /* Check if the offloading mode is supported by the underlying layers */
        if (offload != MACSEC_OFFLOAD_OFF &&
-           !macsec_check_offload(offload, macsec))
-               return -EOPNOTSUPP;
+           !macsec_check_offload(offload, macsec)) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
 
        /* Check if the net device is busy. */
-       if (netif_running(dev))
-               return -EBUSY;
-
-       rtnl_lock();
+       if (netif_running(dev)) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        prev_offload = macsec->offload;
        macsec->offload = offload;
@@ -2662,7 +2670,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
 
 rollback:
        macsec->offload = prev_offload;
-
+out:
        rtnl_unlock();
        return ret;
 }