diff options
author | Jakub Kicinski <kuba@kernel.org> | 2024-07-10 10:40:42 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2024-07-11 14:41:41 -0700 |
commit | 2899d58462ba868287d6ff3acad3675e7adf934f (patch) | |
tree | d515db667d5280f1e8b0a5d904c0365e3d6639a7 /net/ethtool/common.c | |
parent | 7c8267275de6989a9b682a07d75e89395457ee01 (diff) | |
download | linux-stable-2899d58462ba868287d6ff3acad3675e7adf934f.tar.gz linux-stable-2899d58462ba868287d6ff3acad3675e7adf934f.tar.bz2 linux-stable-2899d58462ba868287d6ff3acad3675e7adf934f.zip |
ethtool: fail closed if we can't get max channel used in indirection tables
Commit 0d1b7d6c9274 ("bnxt: fix crashes when reducing ring count with
active RSS contexts") proves that allowing indirection table to contain
channels with out of bounds IDs may lead to crashes. Currently the
max channel check in the core gets skipped if driver can't fetch
the indirection table or when we can't allocate memory.
Both of those conditions should be extremely rare but if they do
happen we should try to be safe and fail the channel change.
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20240710174043.754664-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ethtool/common.c')
-rw-r--r-- | net/ethtool/common.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 6b2a360dcdf0..8a62375ebd1f 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -587,35 +587,39 @@ err_free_info: return err; } -int ethtool_get_max_rxfh_channel(struct net_device *dev, u32 *max) +u32 ethtool_get_max_rxfh_channel(struct net_device *dev) { struct ethtool_rxfh_param rxfh = {}; - u32 dev_size, current_max = 0; + u32 dev_size, current_max; int ret; + if (!netif_is_rxfh_configured(dev)) + return 0; + if (!dev->ethtool_ops->get_rxfh_indir_size || !dev->ethtool_ops->get_rxfh) - return -EOPNOTSUPP; + return 0; dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev); if (dev_size == 0) - return -EOPNOTSUPP; + return 0; rxfh.indir = kcalloc(dev_size, sizeof(rxfh.indir[0]), GFP_USER); if (!rxfh.indir) - return -ENOMEM; + return U32_MAX; ret = dev->ethtool_ops->get_rxfh(dev, &rxfh); - if (ret) - goto out; + if (ret) { + current_max = U32_MAX; + goto out_free; + } + current_max = 0; while (dev_size--) current_max = max(current_max, rxfh.indir[dev_size]); - *max = current_max; - -out: +out_free: kfree(rxfh.indir); - return ret; + return current_max; } int ethtool_check_ops(const struct ethtool_ops *ops) |