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

net_user.c (5370B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
      4 */
      5
      6#include <stdio.h>
      7#include <unistd.h>
      8#include <stdarg.h>
      9#include <errno.h>
     10#include <stddef.h>
     11#include <string.h>
     12#include <sys/socket.h>
     13#include <sys/wait.h>
     14#include <net_user.h>
     15#include <os.h>
     16#include <um_malloc.h>
     17
     18int tap_open_common(void *dev, char *gate_addr)
     19{
     20	int tap_addr[4];
     21
     22	if (gate_addr == NULL)
     23		return 0;
     24	if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
     25		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) {
     26		printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n",
     27		       gate_addr);
     28		return -EINVAL;
     29	}
     30	return 0;
     31}
     32
     33void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
     34{
     35	int tap_addr[4];
     36
     37	if ((gate_addr != NULL) &&
     38	    (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
     39		    &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
     40	    (eth_addr[0] == tap_addr[0]) &&
     41	    (eth_addr[1] == tap_addr[1]) &&
     42	    (eth_addr[2] == tap_addr[2]) &&
     43	    (eth_addr[3] == tap_addr[3])) {
     44		printk(UM_KERN_ERR "The tap IP address and the UML eth IP "
     45		       "address must be different\n");
     46	}
     47}
     48
     49/* Do reliable error handling as this fails frequently enough. */
     50void read_output(int fd, char *output, int len)
     51{
     52	int remain, ret, expected;
     53	char c;
     54	char *str;
     55
     56	if (output == NULL) {
     57		output = &c;
     58		len = sizeof(c);
     59	}
     60
     61	*output = '\0';
     62	ret = read(fd, &remain, sizeof(remain));
     63
     64	if (ret != sizeof(remain)) {
     65		if (ret < 0)
     66			ret = -errno;
     67		expected = sizeof(remain);
     68		str = "length";
     69		goto err;
     70	}
     71
     72	while (remain != 0) {
     73		expected = (remain < len) ? remain : len;
     74		ret = read(fd, output, expected);
     75		if (ret != expected) {
     76			if (ret < 0)
     77				ret = -errno;
     78			str = "data";
     79			goto err;
     80		}
     81		remain -= ret;
     82	}
     83
     84	return;
     85
     86err:
     87	if (ret < 0)
     88		printk(UM_KERN_ERR "read_output - read of %s failed, "
     89		       "errno = %d\n", str, -ret);
     90	else
     91		printk(UM_KERN_ERR "read_output - read of %s failed, read only "
     92		       "%d of %d bytes\n", str, ret, expected);
     93}
     94
     95int net_read(int fd, void *buf, int len)
     96{
     97	int n;
     98
     99	n = read(fd,  buf,  len);
    100
    101	if ((n < 0) && (errno == EAGAIN))
    102		return 0;
    103	else if (n == 0)
    104		return -ENOTCONN;
    105	return n;
    106}
    107
    108int net_recvfrom(int fd, void *buf, int len)
    109{
    110	int n;
    111
    112	CATCH_EINTR(n = recvfrom(fd,  buf,  len, 0, NULL, NULL));
    113	if (n < 0) {
    114		if (errno == EAGAIN)
    115			return 0;
    116		return -errno;
    117	}
    118	else if (n == 0)
    119		return -ENOTCONN;
    120	return n;
    121}
    122
    123int net_write(int fd, void *buf, int len)
    124{
    125	int n;
    126
    127	n = write(fd, buf, len);
    128
    129	if ((n < 0) && (errno == EAGAIN))
    130		return 0;
    131	else if (n == 0)
    132		return -ENOTCONN;
    133	return n;
    134}
    135
    136int net_send(int fd, void *buf, int len)
    137{
    138	int n;
    139
    140	CATCH_EINTR(n = send(fd, buf, len, 0));
    141	if (n < 0) {
    142		if (errno == EAGAIN)
    143			return 0;
    144		return -errno;
    145	}
    146	else if (n == 0)
    147		return -ENOTCONN;
    148	return n;
    149}
    150
    151int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
    152{
    153	int n;
    154
    155	CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
    156			       sock_len));
    157	if (n < 0) {
    158		if (errno == EAGAIN)
    159			return 0;
    160		return -errno;
    161	}
    162	else if (n == 0)
    163		return -ENOTCONN;
    164	return n;
    165}
    166
    167struct change_pre_exec_data {
    168	int close_me;
    169	int stdout_fd;
    170};
    171
    172static void change_pre_exec(void *arg)
    173{
    174	struct change_pre_exec_data *data = arg;
    175
    176	close(data->close_me);
    177	dup2(data->stdout_fd, 1);
    178}
    179
    180static int change_tramp(char **argv, char *output, int output_len)
    181{
    182	int pid, fds[2], err;
    183	struct change_pre_exec_data pe_data;
    184
    185	err = os_pipe(fds, 1, 0);
    186	if (err < 0) {
    187		printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n",
    188		       -err);
    189		return err;
    190	}
    191	pe_data.close_me = fds[0];
    192	pe_data.stdout_fd = fds[1];
    193	pid = run_helper(change_pre_exec, &pe_data, argv);
    194
    195	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
    196		read_output(fds[0], output, output_len);
    197
    198	close(fds[0]);
    199	close(fds[1]);
    200
    201	if (pid > 0)
    202		helper_wait(pid);
    203	return pid;
    204}
    205
    206static void change(char *dev, char *what, unsigned char *addr,
    207		   unsigned char *netmask)
    208{
    209	char addr_buf[sizeof("255.255.255.255\0")];
    210	char netmask_buf[sizeof("255.255.255.255\0")];
    211	char version[sizeof("nnnnn\0")];
    212	char *argv[] = { "uml_net", version, what, dev, addr_buf,
    213			 netmask_buf, NULL };
    214	char *output;
    215	int output_len, pid;
    216
    217	sprintf(version, "%d", UML_NET_VERSION);
    218	sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
    219	sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
    220		netmask[2], netmask[3]);
    221
    222	output_len = UM_KERN_PAGE_SIZE;
    223	output = uml_kmalloc(output_len, UM_GFP_KERNEL);
    224	if (output == NULL)
    225		printk(UM_KERN_ERR "change : failed to allocate output "
    226		       "buffer\n");
    227
    228	pid = change_tramp(argv, output, output_len);
    229	if (pid < 0) {
    230		kfree(output);
    231		return;
    232	}
    233
    234	if (output != NULL) {
    235		printk("%s", output);
    236		kfree(output);
    237	}
    238}
    239
    240void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
    241{
    242	change(arg, "add", addr, netmask);
    243}
    244
    245void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
    246{
    247	change(arg, "del", addr, netmask);
    248}
    249
    250char *split_if_spec(char *str, ...)
    251{
    252	char **arg, *end, *ret = NULL;
    253	va_list ap;
    254
    255	va_start(ap, str);
    256	while ((arg = va_arg(ap, char **)) != NULL) {
    257		if (*str == '\0')
    258			goto out;
    259		end = strchr(str, ',');
    260		if (end != str)
    261			*arg = str;
    262		if (end == NULL)
    263			goto out;
    264		*end++ = '\0';
    265		str = end;
    266	}
    267	ret = str;
    268out:
    269	va_end(ap);
    270	return ret;
    271}