net: mscc: ocelot: validate netdev belongs to switch in .netdev_to_port()

The .netdev_to_port() currently takes only a net_device and returns the
port index, without verifying the netdev actually belongs to the switch
being operated on. This can cause flower rule parsing to silently
resolve to a wrong port on the local hardware.

Update both implementations felix_netdev_to_port() and
ocelot_netdev_to_port() to validate ownership. Also update the callers
in ocelot_flower.c to pass through the ocelot context.

Signed-off-by: David Yang <mmyangfl@gmail.com>
Link: https://patch.msgid.link/20260606125247.305167-1-mmyangfl@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
David Yang
2026-06-06 20:52:44 +08:00
committed by Jakub Kicinski
parent 53a65db20a
commit ea07514700
6 changed files with 12 additions and 8 deletions

View File

@@ -2446,12 +2446,14 @@ struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port)
}
EXPORT_SYMBOL_GPL(felix_port_to_netdev);
int felix_netdev_to_port(struct net_device *dev)
int felix_netdev_to_port(struct ocelot *ocelot, struct net_device *dev)
{
struct felix *felix = ocelot_to_felix(ocelot);
struct dsa_switch *ds = felix->ds;
struct dsa_port *dp;
dp = dsa_port_from_netdev(dev);
if (IS_ERR(dp))
if (IS_ERR(dp) || dp->ds != ds)
return -EINVAL;
return dp->index;

View File

@@ -104,6 +104,6 @@ int felix_register_switch(struct device *dev, resource_size_t switch_base,
enum dsa_tag_protocol init_tag_proto,
const struct felix_info *info);
struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port);
int felix_netdev_to_port(struct net_device *dev);
int felix_netdev_to_port(struct ocelot *ocelot, struct net_device *dev);
#endif

View File

@@ -92,7 +92,7 @@ int ocelot_mact_learn(struct ocelot *ocelot, int port,
int ocelot_mact_forget(struct ocelot *ocelot,
const unsigned char mac[ETH_ALEN], unsigned int vid);
struct net_device *ocelot_port_to_netdev(struct ocelot *ocelot, int port);
int ocelot_netdev_to_port(struct net_device *dev);
int ocelot_netdev_to_port(struct ocelot *ocelot, struct net_device *dev);
int ocelot_probe_port(struct ocelot *ocelot, int port, struct regmap *target,
struct device_node *portnp);

View File

@@ -233,8 +233,8 @@ ocelot_flower_parse_egress_port(struct ocelot *ocelot, struct flow_cls_offload *
const struct flow_action_entry *a, bool mirror,
struct netlink_ext_ack *extack)
{
int egress_port = ocelot->ops->netdev_to_port(ocelot, a->dev);
const char *act_string = mirror ? "mirror" : "redirect";
int egress_port = ocelot->ops->netdev_to_port(a->dev);
enum flow_action_id offloadable_act_id;
offloadable_act_id = mirror ? FLOW_ACTION_MIRRED : FLOW_ACTION_REDIRECT;
@@ -580,7 +580,7 @@ static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
return -ENOENT;
}
ingress_port = ocelot->ops->netdev_to_port(indev);
ingress_port = ocelot->ops->netdev_to_port(ocelot, indev);
if (ingress_port < 0) {
NL_SET_ERR_MSG_MOD(extack,
"Can only offload an ocelot ingress port");

View File

@@ -984,7 +984,7 @@ static bool ocelot_netdevice_dev_check(const struct net_device *dev)
return dev->netdev_ops == &ocelot_port_netdev_ops;
}
int ocelot_netdev_to_port(struct net_device *dev)
int ocelot_netdev_to_port(struct ocelot *ocelot, struct net_device *dev)
{
struct ocelot_port_private *priv;
@@ -992,6 +992,8 @@ int ocelot_netdev_to_port(struct net_device *dev)
return -EINVAL;
priv = netdev_priv(dev);
if (priv->port.ocelot != ocelot)
return -EINVAL;
return priv->port.index;
}

View File

@@ -650,7 +650,7 @@ struct device_node;
struct ocelot_ops {
struct net_device *(*port_to_netdev)(struct ocelot *ocelot, int port);
int (*netdev_to_port)(struct net_device *dev);
int (*netdev_to_port)(struct ocelot *ocelot, struct net_device *dev);
int (*reset)(struct ocelot *ocelot);
u16 (*wm_enc)(u16 value);
u16 (*wm_dec)(u16 value);