mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
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:
committed by
Jakub Kicinski
parent
53a65db20a
commit
ea07514700
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user