cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dev_ioctl.c (14280B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/kmod.h>
      3#include <linux/netdevice.h>
      4#include <linux/inetdevice.h>
      5#include <linux/etherdevice.h>
      6#include <linux/rtnetlink.h>
      7#include <linux/net_tstamp.h>
      8#include <linux/wireless.h>
      9#include <linux/if_bridge.h>
     10#include <net/dsa.h>
     11#include <net/wext.h>
     12
     13#include "dev.h"
     14
     15/*
     16 *	Map an interface index to its name (SIOCGIFNAME)
     17 */
     18
     19/*
     20 *	We need this ioctl for efficient implementation of the
     21 *	if_indextoname() function required by the IPv6 API.  Without
     22 *	it, we would have to search all the interfaces to find a
     23 *	match.  --pb
     24 */
     25
     26static int dev_ifname(struct net *net, struct ifreq *ifr)
     27{
     28	ifr->ifr_name[IFNAMSIZ-1] = 0;
     29	return netdev_get_name(net, ifr->ifr_name, ifr->ifr_ifindex);
     30}
     31
     32/*
     33 *	Perform a SIOCGIFCONF call. This structure will change
     34 *	size eventually, and there is nothing I can do about it.
     35 *	Thus we will need a 'compatibility mode'.
     36 */
     37int dev_ifconf(struct net *net, struct ifconf __user *uifc)
     38{
     39	struct net_device *dev;
     40	void __user *pos;
     41	size_t size;
     42	int len, total = 0, done;
     43
     44	/* both the ifconf and the ifreq structures are slightly different */
     45	if (in_compat_syscall()) {
     46		struct compat_ifconf ifc32;
     47
     48		if (copy_from_user(&ifc32, uifc, sizeof(struct compat_ifconf)))
     49			return -EFAULT;
     50
     51		pos = compat_ptr(ifc32.ifcbuf);
     52		len = ifc32.ifc_len;
     53		size = sizeof(struct compat_ifreq);
     54	} else {
     55		struct ifconf ifc;
     56
     57		if (copy_from_user(&ifc, uifc, sizeof(struct ifconf)))
     58			return -EFAULT;
     59
     60		pos = ifc.ifc_buf;
     61		len = ifc.ifc_len;
     62		size = sizeof(struct ifreq);
     63	}
     64
     65	/* Loop over the interfaces, and write an info block for each. */
     66	rtnl_lock();
     67	for_each_netdev(net, dev) {
     68		if (!pos)
     69			done = inet_gifconf(dev, NULL, 0, size);
     70		else
     71			done = inet_gifconf(dev, pos + total,
     72					    len - total, size);
     73		if (done < 0) {
     74			rtnl_unlock();
     75			return -EFAULT;
     76		}
     77		total += done;
     78	}
     79	rtnl_unlock();
     80
     81	return put_user(total, &uifc->ifc_len);
     82}
     83
     84static int dev_getifmap(struct net_device *dev, struct ifreq *ifr)
     85{
     86	struct ifmap *ifmap = &ifr->ifr_map;
     87
     88	if (in_compat_syscall()) {
     89		struct compat_ifmap *cifmap = (struct compat_ifmap *)ifmap;
     90
     91		cifmap->mem_start = dev->mem_start;
     92		cifmap->mem_end   = dev->mem_end;
     93		cifmap->base_addr = dev->base_addr;
     94		cifmap->irq       = dev->irq;
     95		cifmap->dma       = dev->dma;
     96		cifmap->port      = dev->if_port;
     97
     98		return 0;
     99	}
    100
    101	ifmap->mem_start  = dev->mem_start;
    102	ifmap->mem_end    = dev->mem_end;
    103	ifmap->base_addr  = dev->base_addr;
    104	ifmap->irq        = dev->irq;
    105	ifmap->dma        = dev->dma;
    106	ifmap->port       = dev->if_port;
    107
    108	return 0;
    109}
    110
    111static int dev_setifmap(struct net_device *dev, struct ifreq *ifr)
    112{
    113	struct compat_ifmap *cifmap = (struct compat_ifmap *)&ifr->ifr_map;
    114
    115	if (!dev->netdev_ops->ndo_set_config)
    116		return -EOPNOTSUPP;
    117
    118	if (in_compat_syscall()) {
    119		struct ifmap ifmap = {
    120			.mem_start  = cifmap->mem_start,
    121			.mem_end    = cifmap->mem_end,
    122			.base_addr  = cifmap->base_addr,
    123			.irq        = cifmap->irq,
    124			.dma        = cifmap->dma,
    125			.port       = cifmap->port,
    126		};
    127
    128		return dev->netdev_ops->ndo_set_config(dev, &ifmap);
    129	}
    130
    131	return dev->netdev_ops->ndo_set_config(dev, &ifr->ifr_map);
    132}
    133
    134/*
    135 *	Perform the SIOCxIFxxx calls, inside rcu_read_lock()
    136 */
    137static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd)
    138{
    139	int err;
    140	struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name);
    141
    142	if (!dev)
    143		return -ENODEV;
    144
    145	switch (cmd) {
    146	case SIOCGIFFLAGS:	/* Get interface flags */
    147		ifr->ifr_flags = (short) dev_get_flags(dev);
    148		return 0;
    149
    150	case SIOCGIFMETRIC:	/* Get the metric on the interface
    151				   (currently unused) */
    152		ifr->ifr_metric = 0;
    153		return 0;
    154
    155	case SIOCGIFMTU:	/* Get the MTU of a device */
    156		ifr->ifr_mtu = dev->mtu;
    157		return 0;
    158
    159	case SIOCGIFSLAVE:
    160		err = -EINVAL;
    161		break;
    162
    163	case SIOCGIFMAP:
    164		return dev_getifmap(dev, ifr);
    165
    166	case SIOCGIFINDEX:
    167		ifr->ifr_ifindex = dev->ifindex;
    168		return 0;
    169
    170	case SIOCGIFTXQLEN:
    171		ifr->ifr_qlen = dev->tx_queue_len;
    172		return 0;
    173
    174	default:
    175		/* dev_ioctl() should ensure this case
    176		 * is never reached
    177		 */
    178		WARN_ON(1);
    179		err = -ENOTTY;
    180		break;
    181
    182	}
    183	return err;
    184}
    185
    186static int net_hwtstamp_validate(struct ifreq *ifr)
    187{
    188	struct hwtstamp_config cfg;
    189	enum hwtstamp_tx_types tx_type;
    190	enum hwtstamp_rx_filters rx_filter;
    191	int tx_type_valid = 0;
    192	int rx_filter_valid = 0;
    193
    194	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
    195		return -EFAULT;
    196
    197	if (cfg.flags & ~HWTSTAMP_FLAG_MASK)
    198		return -EINVAL;
    199
    200	tx_type = cfg.tx_type;
    201	rx_filter = cfg.rx_filter;
    202
    203	switch (tx_type) {
    204	case HWTSTAMP_TX_OFF:
    205	case HWTSTAMP_TX_ON:
    206	case HWTSTAMP_TX_ONESTEP_SYNC:
    207	case HWTSTAMP_TX_ONESTEP_P2P:
    208		tx_type_valid = 1;
    209		break;
    210	case __HWTSTAMP_TX_CNT:
    211		/* not a real value */
    212		break;
    213	}
    214
    215	switch (rx_filter) {
    216	case HWTSTAMP_FILTER_NONE:
    217	case HWTSTAMP_FILTER_ALL:
    218	case HWTSTAMP_FILTER_SOME:
    219	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
    220	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
    221	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
    222	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
    223	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
    224	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
    225	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
    226	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
    227	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
    228	case HWTSTAMP_FILTER_PTP_V2_EVENT:
    229	case HWTSTAMP_FILTER_PTP_V2_SYNC:
    230	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
    231	case HWTSTAMP_FILTER_NTP_ALL:
    232		rx_filter_valid = 1;
    233		break;
    234	case __HWTSTAMP_FILTER_CNT:
    235		/* not a real value */
    236		break;
    237	}
    238
    239	if (!tx_type_valid || !rx_filter_valid)
    240		return -ERANGE;
    241
    242	return 0;
    243}
    244
    245static int dev_eth_ioctl(struct net_device *dev,
    246			 struct ifreq *ifr, unsigned int cmd)
    247{
    248	const struct net_device_ops *ops = dev->netdev_ops;
    249	int err;
    250
    251	err = dsa_ndo_eth_ioctl(dev, ifr, cmd);
    252	if (err == 0 || err != -EOPNOTSUPP)
    253		return err;
    254
    255	if (ops->ndo_eth_ioctl) {
    256		if (netif_device_present(dev))
    257			err = ops->ndo_eth_ioctl(dev, ifr, cmd);
    258		else
    259			err = -ENODEV;
    260	}
    261
    262	return err;
    263}
    264
    265static int dev_siocbond(struct net_device *dev,
    266			struct ifreq *ifr, unsigned int cmd)
    267{
    268	const struct net_device_ops *ops = dev->netdev_ops;
    269
    270	if (ops->ndo_siocbond) {
    271		if (netif_device_present(dev))
    272			return ops->ndo_siocbond(dev, ifr, cmd);
    273		else
    274			return -ENODEV;
    275	}
    276
    277	return -EOPNOTSUPP;
    278}
    279
    280static int dev_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
    281			      void __user *data, unsigned int cmd)
    282{
    283	const struct net_device_ops *ops = dev->netdev_ops;
    284
    285	if (ops->ndo_siocdevprivate) {
    286		if (netif_device_present(dev))
    287			return ops->ndo_siocdevprivate(dev, ifr, data, cmd);
    288		else
    289			return -ENODEV;
    290	}
    291
    292	return -EOPNOTSUPP;
    293}
    294
    295static int dev_siocwandev(struct net_device *dev, struct if_settings *ifs)
    296{
    297	const struct net_device_ops *ops = dev->netdev_ops;
    298
    299	if (ops->ndo_siocwandev) {
    300		if (netif_device_present(dev))
    301			return ops->ndo_siocwandev(dev, ifs);
    302		else
    303			return -ENODEV;
    304	}
    305
    306	return -EOPNOTSUPP;
    307}
    308
    309/*
    310 *	Perform the SIOCxIFxxx calls, inside rtnl_lock()
    311 */
    312static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
    313		      unsigned int cmd)
    314{
    315	int err;
    316	struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
    317	const struct net_device_ops *ops;
    318	netdevice_tracker dev_tracker;
    319
    320	if (!dev)
    321		return -ENODEV;
    322
    323	ops = dev->netdev_ops;
    324
    325	switch (cmd) {
    326	case SIOCSIFFLAGS:	/* Set interface flags */
    327		return dev_change_flags(dev, ifr->ifr_flags, NULL);
    328
    329	case SIOCSIFMETRIC:	/* Set the metric on the interface
    330				   (currently unused) */
    331		return -EOPNOTSUPP;
    332
    333	case SIOCSIFMTU:	/* Set the MTU of a device */
    334		return dev_set_mtu(dev, ifr->ifr_mtu);
    335
    336	case SIOCSIFHWADDR:
    337		if (dev->addr_len > sizeof(struct sockaddr))
    338			return -EINVAL;
    339		return dev_set_mac_address_user(dev, &ifr->ifr_hwaddr, NULL);
    340
    341	case SIOCSIFHWBROADCAST:
    342		if (ifr->ifr_hwaddr.sa_family != dev->type)
    343			return -EINVAL;
    344		memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
    345		       min(sizeof(ifr->ifr_hwaddr.sa_data),
    346			   (size_t)dev->addr_len));
    347		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
    348		return 0;
    349
    350	case SIOCSIFMAP:
    351		return dev_setifmap(dev, ifr);
    352
    353	case SIOCADDMULTI:
    354		if (!ops->ndo_set_rx_mode ||
    355		    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
    356			return -EINVAL;
    357		if (!netif_device_present(dev))
    358			return -ENODEV;
    359		return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
    360
    361	case SIOCDELMULTI:
    362		if (!ops->ndo_set_rx_mode ||
    363		    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
    364			return -EINVAL;
    365		if (!netif_device_present(dev))
    366			return -ENODEV;
    367		return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);
    368
    369	case SIOCSIFTXQLEN:
    370		if (ifr->ifr_qlen < 0)
    371			return -EINVAL;
    372		return dev_change_tx_queue_len(dev, ifr->ifr_qlen);
    373
    374	case SIOCSIFNAME:
    375		ifr->ifr_newname[IFNAMSIZ-1] = '\0';
    376		return dev_change_name(dev, ifr->ifr_newname);
    377
    378	case SIOCWANDEV:
    379		return dev_siocwandev(dev, &ifr->ifr_settings);
    380
    381	case SIOCBRADDIF:
    382	case SIOCBRDELIF:
    383		if (!netif_device_present(dev))
    384			return -ENODEV;
    385		if (!netif_is_bridge_master(dev))
    386			return -EOPNOTSUPP;
    387		dev_hold_track(dev, &dev_tracker, GFP_KERNEL);
    388		rtnl_unlock();
    389		err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);
    390		dev_put_track(dev, &dev_tracker);
    391		rtnl_lock();
    392		return err;
    393
    394	case SIOCSHWTSTAMP:
    395		err = net_hwtstamp_validate(ifr);
    396		if (err)
    397			return err;
    398		fallthrough;
    399
    400	/*
    401	 *	Unknown or private ioctl
    402	 */
    403	default:
    404		if (cmd >= SIOCDEVPRIVATE &&
    405		    cmd <= SIOCDEVPRIVATE + 15)
    406			return dev_siocdevprivate(dev, ifr, data, cmd);
    407
    408		if (cmd == SIOCGMIIPHY ||
    409		    cmd == SIOCGMIIREG ||
    410		    cmd == SIOCSMIIREG ||
    411		    cmd == SIOCSHWTSTAMP ||
    412		    cmd == SIOCGHWTSTAMP) {
    413			err = dev_eth_ioctl(dev, ifr, cmd);
    414		} else if (cmd == SIOCBONDENSLAVE ||
    415		    cmd == SIOCBONDRELEASE ||
    416		    cmd == SIOCBONDSETHWADDR ||
    417		    cmd == SIOCBONDSLAVEINFOQUERY ||
    418		    cmd == SIOCBONDINFOQUERY ||
    419		    cmd == SIOCBONDCHANGEACTIVE) {
    420			err = dev_siocbond(dev, ifr, cmd);
    421		} else
    422			err = -EINVAL;
    423
    424	}
    425	return err;
    426}
    427
    428/**
    429 *	dev_load 	- load a network module
    430 *	@net: the applicable net namespace
    431 *	@name: name of interface
    432 *
    433 *	If a network interface is not present and the process has suitable
    434 *	privileges this function loads the module. If module loading is not
    435 *	available in this kernel then it becomes a nop.
    436 */
    437
    438void dev_load(struct net *net, const char *name)
    439{
    440	struct net_device *dev;
    441	int no_module;
    442
    443	rcu_read_lock();
    444	dev = dev_get_by_name_rcu(net, name);
    445	rcu_read_unlock();
    446
    447	no_module = !dev;
    448	if (no_module && capable(CAP_NET_ADMIN))
    449		no_module = request_module("netdev-%s", name);
    450	if (no_module && capable(CAP_SYS_MODULE))
    451		request_module("%s", name);
    452}
    453EXPORT_SYMBOL(dev_load);
    454
    455/*
    456 *	This function handles all "interface"-type I/O control requests. The actual
    457 *	'doing' part of this is dev_ifsioc above.
    458 */
    459
    460/**
    461 *	dev_ioctl	-	network device ioctl
    462 *	@net: the applicable net namespace
    463 *	@cmd: command to issue
    464 *	@ifr: pointer to a struct ifreq in user space
    465 *	@need_copyout: whether or not copy_to_user() should be called
    466 *
    467 *	Issue ioctl functions to devices. This is normally called by the
    468 *	user space syscall interfaces but can sometimes be useful for
    469 *	other purposes. The return value is the return from the syscall if
    470 *	positive or a negative errno code on error.
    471 */
    472
    473int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
    474	      void __user *data, bool *need_copyout)
    475{
    476	int ret;
    477	char *colon;
    478
    479	if (need_copyout)
    480		*need_copyout = true;
    481	if (cmd == SIOCGIFNAME)
    482		return dev_ifname(net, ifr);
    483
    484	ifr->ifr_name[IFNAMSIZ-1] = 0;
    485
    486	colon = strchr(ifr->ifr_name, ':');
    487	if (colon)
    488		*colon = 0;
    489
    490	/*
    491	 *	See which interface the caller is talking about.
    492	 */
    493
    494	switch (cmd) {
    495	case SIOCGIFHWADDR:
    496		dev_load(net, ifr->ifr_name);
    497		ret = dev_get_mac_address(&ifr->ifr_hwaddr, net, ifr->ifr_name);
    498		if (colon)
    499			*colon = ':';
    500		return ret;
    501	/*
    502	 *	These ioctl calls:
    503	 *	- can be done by all.
    504	 *	- atomic and do not require locking.
    505	 *	- return a value
    506	 */
    507	case SIOCGIFFLAGS:
    508	case SIOCGIFMETRIC:
    509	case SIOCGIFMTU:
    510	case SIOCGIFSLAVE:
    511	case SIOCGIFMAP:
    512	case SIOCGIFINDEX:
    513	case SIOCGIFTXQLEN:
    514		dev_load(net, ifr->ifr_name);
    515		rcu_read_lock();
    516		ret = dev_ifsioc_locked(net, ifr, cmd);
    517		rcu_read_unlock();
    518		if (colon)
    519			*colon = ':';
    520		return ret;
    521
    522	case SIOCETHTOOL:
    523		dev_load(net, ifr->ifr_name);
    524		ret = dev_ethtool(net, ifr, data);
    525		if (colon)
    526			*colon = ':';
    527		return ret;
    528
    529	/*
    530	 *	These ioctl calls:
    531	 *	- require superuser power.
    532	 *	- require strict serialization.
    533	 *	- return a value
    534	 */
    535	case SIOCGMIIPHY:
    536	case SIOCGMIIREG:
    537	case SIOCSIFNAME:
    538		dev_load(net, ifr->ifr_name);
    539		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
    540			return -EPERM;
    541		rtnl_lock();
    542		ret = dev_ifsioc(net, ifr, data, cmd);
    543		rtnl_unlock();
    544		if (colon)
    545			*colon = ':';
    546		return ret;
    547
    548	/*
    549	 *	These ioctl calls:
    550	 *	- require superuser power.
    551	 *	- require strict serialization.
    552	 *	- do not return a value
    553	 */
    554	case SIOCSIFMAP:
    555	case SIOCSIFTXQLEN:
    556		if (!capable(CAP_NET_ADMIN))
    557			return -EPERM;
    558		fallthrough;
    559	/*
    560	 *	These ioctl calls:
    561	 *	- require local superuser power.
    562	 *	- require strict serialization.
    563	 *	- do not return a value
    564	 */
    565	case SIOCSIFFLAGS:
    566	case SIOCSIFMETRIC:
    567	case SIOCSIFMTU:
    568	case SIOCSIFHWADDR:
    569	case SIOCSIFSLAVE:
    570	case SIOCADDMULTI:
    571	case SIOCDELMULTI:
    572	case SIOCSIFHWBROADCAST:
    573	case SIOCSMIIREG:
    574	case SIOCBONDENSLAVE:
    575	case SIOCBONDRELEASE:
    576	case SIOCBONDSETHWADDR:
    577	case SIOCBONDCHANGEACTIVE:
    578	case SIOCBRADDIF:
    579	case SIOCBRDELIF:
    580	case SIOCSHWTSTAMP:
    581		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
    582			return -EPERM;
    583		fallthrough;
    584	case SIOCBONDSLAVEINFOQUERY:
    585	case SIOCBONDINFOQUERY:
    586		dev_load(net, ifr->ifr_name);
    587		rtnl_lock();
    588		ret = dev_ifsioc(net, ifr, data, cmd);
    589		rtnl_unlock();
    590		if (need_copyout)
    591			*need_copyout = false;
    592		return ret;
    593
    594	case SIOCGIFMEM:
    595		/* Get the per device memory space. We can add this but
    596		 * currently do not support it */
    597	case SIOCSIFMEM:
    598		/* Set the per device memory buffer space.
    599		 * Not applicable in our case */
    600	case SIOCSIFLINK:
    601		return -ENOTTY;
    602
    603	/*
    604	 *	Unknown or private ioctl.
    605	 */
    606	default:
    607		if (cmd == SIOCWANDEV ||
    608		    cmd == SIOCGHWTSTAMP ||
    609		    (cmd >= SIOCDEVPRIVATE &&
    610		     cmd <= SIOCDEVPRIVATE + 15)) {
    611			dev_load(net, ifr->ifr_name);
    612			rtnl_lock();
    613			ret = dev_ifsioc(net, ifr, data, cmd);
    614			rtnl_unlock();
    615			return ret;
    616		}
    617		return -ENOTTY;
    618	}
    619}