Message ID | 20240701131801.1227740-13-maxime.chevallier@bootlin.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Introduce PHY listing and link_topology tracking | expand |
On Mon, Jul 01, 2024 at 03:17:58PM +0200, Maxime Chevallier wrote: > The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer > from the ethnl request to allow query phy stats from each PHY on the > link. > > Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> > --- > net/ethtool/strset.c | 24 +++++++++++++++++------- > 1 file changed, 17 insertions(+), 7 deletions(-) > > diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c ... > @@ -279,6 +280,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, > const struct strset_req_info *req_info = STRSET_REQINFO(req_base); > struct strset_reply_data *data = STRSET_REPDATA(reply_base); > struct net_device *dev = reply_base->dev; > + struct nlattr **tb = info->attrs; Hi Maxime, Elsewhere in this function it is assumed that info may be NULL. But here it is dereferenced unconditionally. Flagged by Smatch. > + struct phy_device *phydev; > unsigned int i; > int ret; > ...
Hello Simon, On Tue, 2 Jul 2024 11:54:11 +0100 Simon Horman <horms@kernel.org> wrote: > On Mon, Jul 01, 2024 at 03:17:58PM +0200, Maxime Chevallier wrote: > > The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer > > from the ethnl request to allow query phy stats from each PHY on the > > link. > > > > Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> > > --- > > net/ethtool/strset.c | 24 +++++++++++++++++------- > > 1 file changed, 17 insertions(+), 7 deletions(-) > > > > diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c > > ... > > > @@ -279,6 +280,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, > > const struct strset_req_info *req_info = STRSET_REQINFO(req_base); > > struct strset_reply_data *data = STRSET_REPDATA(reply_base); > > struct net_device *dev = reply_base->dev; > > + struct nlattr **tb = info->attrs; > > Hi Maxime, > > Elsewhere in this function it is assumed that info may be NULL. > But here it is dereferenced unconditionally. Hmm in almst all netlink commands we do dereference the genl_info *info pointer without checks. I've looked into net/netlink/genetlink.c to backtrack call-sites and it looks to be that indeed info can't be NULL (either populated from genl_start() or genl_family_rcv_msg_doit(). Maybe Jakub can confirm this ? If what I say above is correct, I can include a small patch to remove the un-necessary check that makes smatch think the genl_info pointer can be NULL. Thanks for the report, Maxime
On Wed, 3 Jul 2024 08:55:15 +0200 Maxime Chevallier wrote: > > Elsewhere in this function it is assumed that info may be NULL. > > But here it is dereferenced unconditionally. > > Hmm in almst all netlink commands we do dereference the genl_info *info > pointer without checks. > > I've looked into net/netlink/genetlink.c to backtrack call-sites and it > looks to be that indeed info can't be NULL (either populated from > genl_start() or genl_family_rcv_msg_doit(). Maybe Jakub can confirm > this ? > > If what I say above is correct, I can include a small patch to remove > the un-necessary check that makes smatch think the genl_info pointer can > be NULL. The info used to be null during dumps, but I think we fixed that in f946270d05c2 ("ethtool: netlink: always pass genl_info to .prepare_data") Perhaps I should have cleaned up existing code :S
On Wed, Jul 03, 2024 at 08:55:15AM +0200, Maxime Chevallier wrote: > Hello Simon, > > On Tue, 2 Jul 2024 11:54:11 +0100 > Simon Horman <horms@kernel.org> wrote: > > > On Mon, Jul 01, 2024 at 03:17:58PM +0200, Maxime Chevallier wrote: > > > The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer > > > from the ethnl request to allow query phy stats from each PHY on the > > > link. > > > > > > Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> > > > --- > > > net/ethtool/strset.c | 24 +++++++++++++++++------- > > > 1 file changed, 17 insertions(+), 7 deletions(-) > > > > > > diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c > > > > ... > > > > > @@ -279,6 +280,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, > > > const struct strset_req_info *req_info = STRSET_REQINFO(req_base); > > > struct strset_reply_data *data = STRSET_REPDATA(reply_base); > > > struct net_device *dev = reply_base->dev; > > > + struct nlattr **tb = info->attrs; > > > > Hi Maxime, > > > > Elsewhere in this function it is assumed that info may be NULL. > > But here it is dereferenced unconditionally. > > Hmm in almst all netlink commands we do dereference the genl_info *info > pointer without checks. > > I've looked into net/netlink/genetlink.c to backtrack call-sites and it > looks to be that indeed info can't be NULL (either populated from > genl_start() or genl_family_rcv_msg_doit(). Maybe Jakub can confirm > this ? > > If what I say above is correct, I can include a small patch to remove > the un-necessary check that makes smatch think the genl_info pointer can > be NULL. Thanks for following up. Assuming that is true (I did not check yet) then I agree. And I don't think such a change needs to block this patchset.
diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c index c678b484a079..ebc3a7ad0558 100644 --- a/net/ethtool/strset.c +++ b/net/ethtool/strset.c @@ -126,7 +126,7 @@ struct strset_reply_data { const struct nla_policy ethnl_strset_get_policy[] = { [ETHTOOL_A_STRSET_HEADER] = - NLA_POLICY_NESTED(ethnl_header_policy), + NLA_POLICY_NESTED(ethnl_header_policy_phy), [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED }, [ETHTOOL_A_STRSET_COUNTS_ONLY] = { .type = NLA_FLAG }, }; @@ -233,17 +233,18 @@ static void strset_cleanup_data(struct ethnl_reply_data *reply_base) } static int strset_prepare_set(struct strset_info *info, struct net_device *dev, - unsigned int id, bool counts_only) + struct phy_device *phydev, unsigned int id, + bool counts_only) { const struct ethtool_phy_ops *phy_ops = ethtool_phy_ops; const struct ethtool_ops *ops = dev->ethtool_ops; void *strings; int count, ret; - if (id == ETH_SS_PHY_STATS && dev->phydev && + if (id == ETH_SS_PHY_STATS && phydev && !ops->get_ethtool_phy_stats && phy_ops && phy_ops->get_sset_count) - ret = phy_ops->get_sset_count(dev->phydev); + ret = phy_ops->get_sset_count(phydev); else if (ops->get_sset_count && ops->get_strings) ret = ops->get_sset_count(dev, id); else @@ -258,10 +259,10 @@ static int strset_prepare_set(struct strset_info *info, struct net_device *dev, strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL); if (!strings) return -ENOMEM; - if (id == ETH_SS_PHY_STATS && dev->phydev && + if (id == ETH_SS_PHY_STATS && phydev && !ops->get_ethtool_phy_stats && phy_ops && phy_ops->get_strings) - phy_ops->get_strings(dev->phydev, strings); + phy_ops->get_strings(phydev, strings); else ops->get_strings(dev, id, strings); info->strings = strings; @@ -279,6 +280,8 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, const struct strset_req_info *req_info = STRSET_REQINFO(req_base); struct strset_reply_data *data = STRSET_REPDATA(reply_base); struct net_device *dev = reply_base->dev; + struct nlattr **tb = info->attrs; + struct phy_device *phydev; unsigned int i; int ret; @@ -297,6 +300,13 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, return 0; } + phydev = ethnl_req_get_phydev(req_base, tb[ETHTOOL_A_HEADER_FLAGS], + info->extack); + + /* phydev can be NULL, check for errors only */ + if (IS_ERR(phydev)) + return PTR_ERR(phydev); + ret = ethnl_ops_begin(dev); if (ret < 0) goto err_strset; @@ -305,7 +315,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base, !data->sets[i].per_dev) continue; - ret = strset_prepare_set(&data->sets[i], dev, i, + ret = strset_prepare_set(&data->sets[i], dev, phydev, i, req_info->counts_only); if (ret < 0) goto err_ops;
The ETH_SS_PHY_STATS command gets PHY statistics. Use the phydev pointer from the ethnl request to allow query phy stats from each PHY on the link. Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> --- net/ethtool/strset.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)