diff options
Diffstat (limited to 'net/core/net-sysfs.c')
| -rw-r--r-- | net/core/net-sysfs.c | 61 | 
1 files changed, 58 insertions, 3 deletions
| diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index f6197774048b..9c01c642cf9e 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -175,6 +175,14 @@ static int change_carrier(struct net_device *dev, unsigned long new_carrier)  static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,  			     const char *buf, size_t len)  { +	struct net_device *netdev = to_net_dev(dev); + +	/* The check is also done in change_carrier; this helps returning early +	 * without hitting the trylock/restart in netdev_store. +	 */ +	if (!netdev->netdev_ops->ndo_change_carrier) +		return -EOPNOTSUPP; +  	return netdev_store(dev, attr, buf, len, change_carrier);  } @@ -196,6 +204,12 @@ static ssize_t speed_show(struct device *dev,  	struct net_device *netdev = to_net_dev(dev);  	int ret = -EINVAL; +	/* The check is also done in __ethtool_get_link_ksettings; this helps +	 * returning early without hitting the trylock/restart below. +	 */ +	if (!netdev->ethtool_ops->get_link_ksettings) +		return ret; +  	if (!rtnl_trylock())  		return restart_syscall(); @@ -216,6 +230,12 @@ static ssize_t duplex_show(struct device *dev,  	struct net_device *netdev = to_net_dev(dev);  	int ret = -EINVAL; +	/* The check is also done in __ethtool_get_link_ksettings; this helps +	 * returning early without hitting the trylock/restart below. +	 */ +	if (!netdev->ethtool_ops->get_link_ksettings) +		return ret; +  	if (!rtnl_trylock())  		return restart_syscall(); @@ -468,6 +488,14 @@ static ssize_t proto_down_store(struct device *dev,  				struct device_attribute *attr,  				const char *buf, size_t len)  { +	struct net_device *netdev = to_net_dev(dev); + +	/* The check is also done in change_proto_down; this helps returning +	 * early without hitting the trylock/restart in netdev_store. +	 */ +	if (!netdev->netdev_ops->ndo_change_proto_down) +		return -EOPNOTSUPP; +  	return netdev_store(dev, attr, buf, len, change_proto_down);  }  NETDEVICE_SHOW_RW(proto_down, fmt_dec); @@ -478,6 +506,12 @@ static ssize_t phys_port_id_show(struct device *dev,  	struct net_device *netdev = to_net_dev(dev);  	ssize_t ret = -EINVAL; +	/* The check is also done in dev_get_phys_port_id; this helps returning +	 * early without hitting the trylock/restart below. +	 */ +	if (!netdev->netdev_ops->ndo_get_phys_port_id) +		return -EOPNOTSUPP; +  	if (!rtnl_trylock())  		return restart_syscall(); @@ -500,6 +534,13 @@ static ssize_t phys_port_name_show(struct device *dev,  	struct net_device *netdev = to_net_dev(dev);  	ssize_t ret = -EINVAL; +	/* The checks are also done in dev_get_phys_port_name; this helps +	 * returning early without hitting the trylock/restart below. +	 */ +	if (!netdev->netdev_ops->ndo_get_phys_port_name && +	    !netdev->netdev_ops->ndo_get_devlink_port) +		return -EOPNOTSUPP; +  	if (!rtnl_trylock())  		return restart_syscall(); @@ -522,6 +563,14 @@ static ssize_t phys_switch_id_show(struct device *dev,  	struct net_device *netdev = to_net_dev(dev);  	ssize_t ret = -EINVAL; +	/* The checks are also done in dev_get_phys_port_name; this helps +	 * returning early without hitting the trylock/restart below. This works +	 * because recurse is false when calling dev_get_port_parent_id. +	 */ +	if (!netdev->netdev_ops->ndo_get_port_parent_id && +	    !netdev->netdev_ops->ndo_get_devlink_port) +		return -EOPNOTSUPP; +  	if (!rtnl_trylock())  		return restart_syscall(); @@ -1226,6 +1275,12 @@ static ssize_t tx_maxrate_store(struct netdev_queue *queue,  	if (!capable(CAP_NET_ADMIN))  		return -EPERM; +	/* The check is also done later; this helps returning early without +	 * hitting the trylock/restart below. +	 */ +	if (!dev->netdev_ops->ndo_set_tx_maxrate) +		return -EOPNOTSUPP; +  	err = kstrtou32(buf, 10, &rate);  	if (err < 0)  		return err; @@ -1869,7 +1924,7 @@ static struct class net_class __ro_after_init = {  	.get_ownership = net_get_ownership,  }; -#ifdef CONFIG_OF_NET +#ifdef CONFIG_OF  static int of_dev_node_match(struct device *dev, const void *data)  {  	for (; dev; dev = dev->parent) { @@ -1973,9 +2028,9 @@ int netdev_register_kobject(struct net_device *ndev)  int netdev_change_owner(struct net_device *ndev, const struct net *net_old,  			const struct net *net_new)  { +	kuid_t old_uid = GLOBAL_ROOT_UID, new_uid = GLOBAL_ROOT_UID; +	kgid_t old_gid = GLOBAL_ROOT_GID, new_gid = GLOBAL_ROOT_GID;  	struct device *dev = &ndev->dev; -	kuid_t old_uid, new_uid; -	kgid_t old_gid, new_gid;  	int error;  	net_ns_get_ownership(net_old, &old_uid, &old_gid); |