lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sat, 19 Sep 2020 06:48:31 +0100
From:   Christoph Hellwig <hch@...radead.org>
To:     Arnd Bergmann <arnd@...db.de>
Cc:     "David S. Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>,
        Christoph Hellwig <hch@...radead.org>,
        Jiri Pirko <jiri@...lanox.com>,
        Taehee Yoo <ap420073@...il.com>,
        Eric Dumazet <edumazet@...gle.com>,
        Alexei Starovoitov <ast@...nel.org>,
        Andrew Lunn <andrew@...n.ch>, Jens Axboe <axboe@...nel.dk>,
        netdev@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] dev_ioctl: split out SIOC?IFMAP ioctls

> diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
> index 797ba2c1562a..a332d6ae4dc6 100644
> --- a/include/uapi/linux/if.h
> +++ b/include/uapi/linux/if.h
> @@ -247,7 +247,13 @@ struct ifreq {
>  		short	ifru_flags;
>  		int	ifru_ivalue;
>  		int	ifru_mtu;
> +#ifndef __KERNEL__
> +		/*
> +		 * ifru_map is rarely used but causes the incompatibility
> +		 * between native and compat mode.
> +		 */
>  		struct  ifmap ifru_map;
> +#endif

Do we need a way to verify that this never changes the struct size?

> +int dev_ifmap(struct net *net, struct ifreq __user *ifr, unsigned int cmd)
> +{
> +	struct net_device *dev;
> +	char ifname[IFNAMSIZ];
> +	char *colon;
> +	struct compat_ifmap cifmap;
> +	struct ifmap ifmap;
> +	int ret;
> +
> +	if (copy_from_user(ifname, ifr->ifr_name, sizeof(ifname)))
> +		return -EFAULT;
> +	ifname[IFNAMSIZ-1] = 0;
> +	colon = strchr(ifname, ':');
> +	if (colon)
> +		*colon = 0;
> +	dev_load(net, ifname);
> +
> +	switch (cmd) {
> +	case SIOCGIFMAP:
> +		rcu_read_lock();
> +		dev = dev_get_by_name_rcu(net, ifname);
> +		if (!dev) {
> +			rcu_read_unlock();
> +			return -ENODEV;
> +		}
> +
> +		if (in_compat_syscall()) {
> +			cifmap.mem_start = dev->mem_start;
> +			cifmap.mem_end   = dev->mem_end;
> +			cifmap.base_addr = dev->base_addr;
> +			cifmap.irq       = dev->irq;
> +			cifmap.dma       = dev->dma;
> +			cifmap.port      = dev->if_port;
> +			rcu_read_unlock();
> +
> +			ret = copy_to_user(&ifr->ifr_data,
> +					   &cifmap, sizeof(cifmap));
> +		} else {
> +			ifmap.mem_start  = dev->mem_start;
> +			ifmap.mem_end    = dev->mem_end;
> +			ifmap.base_addr  = dev->base_addr;
> +			ifmap.irq        = dev->irq;
> +			ifmap.dma        = dev->dma;
> +			ifmap.port       = dev->if_port;
> +			rcu_read_unlock();
> +
> +			ret = copy_to_user(&ifr->ifr_data,
> +					   &ifmap, sizeof(ifmap));
> +		}
> +		ret = ret ? -EFAULT : 0;
> +		break;
> +
> +	case SIOCSIFMAP:
> +		if (!capable(CAP_NET_ADMIN) ||
> +		    !ns_capable(net->user_ns, CAP_NET_ADMIN))
> +			return -EPERM;
> +
> +		if (in_compat_syscall()) {
> +			if (copy_from_user(&cifmap, &ifr->ifr_data,
> +					   sizeof(cifmap)))
> +				return -EFAULT;
> +
> +			ifmap.mem_start  = cifmap.mem_start;
> +			ifmap.mem_end    = cifmap.mem_end;
> +			ifmap.base_addr  = cifmap.base_addr;
> +			ifmap.irq        = cifmap.irq;
> +			ifmap.dma        = cifmap.dma;
> +			ifmap.port       = cifmap.port;
> +		} else {
> +			if (copy_from_user(&ifmap, &ifr->ifr_data,
> +					   sizeof(ifmap)))
> +				return -EFAULT;
> +		}
> +
> +		rtnl_lock();
> +		dev = __dev_get_by_name(net, ifname);
> +		if (!dev || !netif_device_present(dev))
> +			ret = -ENODEV;
> +		else if (!dev->netdev_ops->ndo_set_config)
> +			ret = -EOPNOTSUPP;
> +		else
> +			ret = dev->netdev_ops->ndo_set_config(dev, &ifmap);
> +		rtnl_unlock();
> +		break;
> +	}
> +	return ret;

I'd rather split this into a separate hepers for each ioctl command
instead of having anothr multiplexer here, maybe with another helper
for the common code.

I also find the rcu unlock inside the branches rather strange, but
I can't think of a good alternative.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ