1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4   */
5  
6  #include <stdio.h>
7  #include <unistd.h>
8  #include <stdlib.h>
9  #include <string.h>
10  #include <errno.h>
11  #include <fcntl.h>
12  #include <signal.h>
13  #include <linux/falloc.h>
14  #include <sys/ioctl.h>
15  #include <sys/mount.h>
16  #include <sys/socket.h>
17  #include <sys/stat.h>
18  #include <sys/sysmacros.h>
19  #include <sys/un.h>
20  #include <sys/mman.h>
21  #include <sys/types.h>
22  #include <sys/eventfd.h>
23  #include <poll.h>
24  #include <os.h>
25  
copy_stat(struct uml_stat * dst,const struct stat64 * src)26  static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
27  {
28  	*dst = ((struct uml_stat) {
29  		.ust_dev     = src->st_dev,     /* device */
30  		.ust_ino     = src->st_ino,     /* inode */
31  		.ust_mode    = src->st_mode,    /* protection */
32  		.ust_nlink   = src->st_nlink,   /* number of hard links */
33  		.ust_uid     = src->st_uid,     /* user ID of owner */
34  		.ust_gid     = src->st_gid,     /* group ID of owner */
35  		.ust_size    = src->st_size,    /* total size, in bytes */
36  		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
37  		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
38  		.ust_atime   = src->st_atime,   /* time of last access */
39  		.ust_mtime   = src->st_mtime,   /* time of last modification */
40  		.ust_ctime   = src->st_ctime,   /* time of last change */
41  	});
42  }
43  
os_stat_fd(const int fd,struct uml_stat * ubuf)44  int os_stat_fd(const int fd, struct uml_stat *ubuf)
45  {
46  	struct stat64 sbuf;
47  	int err;
48  
49  	CATCH_EINTR(err = fstat64(fd, &sbuf));
50  	if (err < 0)
51  		return -errno;
52  
53  	if (ubuf != NULL)
54  		copy_stat(ubuf, &sbuf);
55  	return err;
56  }
57  
os_stat_file(const char * file_name,struct uml_stat * ubuf)58  int os_stat_file(const char *file_name, struct uml_stat *ubuf)
59  {
60  	struct stat64 sbuf;
61  	int err;
62  
63  	CATCH_EINTR(err = stat64(file_name, &sbuf));
64  	if (err < 0)
65  		return -errno;
66  
67  	if (ubuf != NULL)
68  		copy_stat(ubuf, &sbuf);
69  	return err;
70  }
71  
os_access(const char * file,int mode)72  int os_access(const char *file, int mode)
73  {
74  	int amode, err;
75  
76  	amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
77  		(mode & OS_ACC_W_OK ? W_OK : 0) |
78  		(mode & OS_ACC_X_OK ? X_OK : 0) |
79  		(mode & OS_ACC_F_OK ? F_OK : 0);
80  
81  	err = access(file, amode);
82  	if (err < 0)
83  		return -errno;
84  
85  	return 0;
86  }
87  
88  /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
os_ioctl_generic(int fd,unsigned int cmd,unsigned long arg)89  int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
90  {
91  	int err;
92  
93  	err = ioctl(fd, cmd, arg);
94  	if (err < 0)
95  		return -errno;
96  
97  	return err;
98  }
99  
100  /* FIXME: ensure namebuf in os_get_if_name is big enough */
os_get_ifname(int fd,char * namebuf)101  int os_get_ifname(int fd, char* namebuf)
102  {
103  	if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
104  		return -errno;
105  
106  	return 0;
107  }
108  
os_set_slip(int fd)109  int os_set_slip(int fd)
110  {
111  	int disc, sencap;
112  
113  	disc = N_SLIP;
114  	if (ioctl(fd, TIOCSETD, &disc) < 0)
115  		return -errno;
116  
117  	sencap = 0;
118  	if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
119  		return -errno;
120  
121  	return 0;
122  }
123  
os_mode_fd(int fd,int mode)124  int os_mode_fd(int fd, int mode)
125  {
126  	int err;
127  
128  	CATCH_EINTR(err = fchmod(fd, mode));
129  	if (err < 0)
130  		return -errno;
131  
132  	return 0;
133  }
134  
os_file_type(char * file)135  int os_file_type(char *file)
136  {
137  	struct uml_stat buf;
138  	int err;
139  
140  	err = os_stat_file(file, &buf);
141  	if (err < 0)
142  		return err;
143  
144  	if (S_ISDIR(buf.ust_mode))
145  		return OS_TYPE_DIR;
146  	else if (S_ISLNK(buf.ust_mode))
147  		return OS_TYPE_SYMLINK;
148  	else if (S_ISCHR(buf.ust_mode))
149  		return OS_TYPE_CHARDEV;
150  	else if (S_ISBLK(buf.ust_mode))
151  		return OS_TYPE_BLOCKDEV;
152  	else if (S_ISFIFO(buf.ust_mode))
153  		return OS_TYPE_FIFO;
154  	else if (S_ISSOCK(buf.ust_mode))
155  		return OS_TYPE_SOCK;
156  	else return OS_TYPE_FILE;
157  }
158  
os_file_mode(const char * file,struct openflags * mode_out)159  int os_file_mode(const char *file, struct openflags *mode_out)
160  {
161  	int err;
162  
163  	*mode_out = OPENFLAGS();
164  
165  	err = access(file, W_OK);
166  	if (err && (errno != EACCES))
167  		return -errno;
168  	else if (!err)
169  		*mode_out = of_write(*mode_out);
170  
171  	err = access(file, R_OK);
172  	if (err && (errno != EACCES))
173  		return -errno;
174  	else if (!err)
175  		*mode_out = of_read(*mode_out);
176  
177  	return err;
178  }
179  
os_open_file(const char * file,struct openflags flags,int mode)180  int os_open_file(const char *file, struct openflags flags, int mode)
181  {
182  	int fd, err, f = 0;
183  
184  	if (flags.r && flags.w)
185  		f = O_RDWR;
186  	else if (flags.r)
187  		f = O_RDONLY;
188  	else if (flags.w)
189  		f = O_WRONLY;
190  	else f = 0;
191  
192  	if (flags.s)
193  		f |= O_SYNC;
194  	if (flags.c)
195  		f |= O_CREAT;
196  	if (flags.t)
197  		f |= O_TRUNC;
198  	if (flags.e)
199  		f |= O_EXCL;
200  	if (flags.a)
201  		f |= O_APPEND;
202  
203  	fd = open64(file, f, mode);
204  	if (fd < 0)
205  		return -errno;
206  
207  	if (flags.cl && fcntl(fd, F_SETFD, 1)) {
208  		err = -errno;
209  		close(fd);
210  		return err;
211  	}
212  
213  	return fd;
214  }
215  
os_connect_socket(const char * name)216  int os_connect_socket(const char *name)
217  {
218  	struct sockaddr_un sock;
219  	int fd, err;
220  
221  	sock.sun_family = AF_UNIX;
222  	snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
223  
224  	fd = socket(AF_UNIX, SOCK_STREAM, 0);
225  	if (fd < 0) {
226  		err = -errno;
227  		goto out;
228  	}
229  
230  	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
231  	if (err) {
232  		err = -errno;
233  		goto out_close;
234  	}
235  
236  	return fd;
237  
238  out_close:
239  	close(fd);
240  out:
241  	return err;
242  }
243  
os_dup_file(int fd)244  int os_dup_file(int fd)
245  {
246  	int new_fd = dup(fd);
247  
248  	if (new_fd < 0)
249  		return -errno;
250  
251  	return new_fd;
252  }
253  
os_close_file(int fd)254  void os_close_file(int fd)
255  {
256  	close(fd);
257  }
os_fsync_file(int fd)258  int os_fsync_file(int fd)
259  {
260  	if (fsync(fd) < 0)
261  	    return -errno;
262  	return 0;
263  }
264  
os_seek_file(int fd,unsigned long long offset)265  int os_seek_file(int fd, unsigned long long offset)
266  {
267  	unsigned long long actual;
268  
269  	actual = lseek64(fd, offset, SEEK_SET);
270  	if (actual != offset)
271  		return -errno;
272  	return 0;
273  }
274  
os_read_file(int fd,void * buf,int len)275  int os_read_file(int fd, void *buf, int len)
276  {
277  	int n = read(fd, buf, len);
278  
279  	if (n < 0)
280  		return -errno;
281  	return n;
282  }
283  
os_pread_file(int fd,void * buf,int len,unsigned long long offset)284  int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
285  {
286  	int n = pread(fd, buf, len, offset);
287  
288  	if (n < 0)
289  		return -errno;
290  	return n;
291  }
292  
os_write_file(int fd,const void * buf,int len)293  int os_write_file(int fd, const void *buf, int len)
294  {
295  	int n = write(fd, (void *) buf, len);
296  
297  	if (n < 0)
298  		return -errno;
299  	return n;
300  }
301  
os_sync_file(int fd)302  int os_sync_file(int fd)
303  {
304  	int n = fdatasync(fd);
305  
306  	if (n < 0)
307  		return -errno;
308  	return n;
309  }
310  
os_pwrite_file(int fd,const void * buf,int len,unsigned long long offset)311  int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
312  {
313  	int n = pwrite(fd, (void *) buf, len, offset);
314  
315  	if (n < 0)
316  		return -errno;
317  	return n;
318  }
319  
320  
os_file_size(const char * file,unsigned long long * size_out)321  int os_file_size(const char *file, unsigned long long *size_out)
322  {
323  	struct uml_stat buf;
324  	int err;
325  
326  	err = os_stat_file(file, &buf);
327  	if (err < 0) {
328  		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
329  		       -err);
330  		return err;
331  	}
332  
333  	if (S_ISBLK(buf.ust_mode)) {
334  		int fd;
335  		long blocks;
336  
337  		fd = open(file, O_RDONLY, 0);
338  		if (fd < 0) {
339  			err = -errno;
340  			printk(UM_KERN_ERR "Couldn't open \"%s\", "
341  			       "errno = %d\n", file, errno);
342  			return err;
343  		}
344  		if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
345  			err = -errno;
346  			printk(UM_KERN_ERR "Couldn't get the block size of "
347  			       "\"%s\", errno = %d\n", file, errno);
348  			close(fd);
349  			return err;
350  		}
351  		*size_out = ((long long) blocks) * 512;
352  		close(fd);
353  	}
354  	else *size_out = buf.ust_size;
355  
356  	return 0;
357  }
358  
os_file_modtime(const char * file,long long * modtime)359  int os_file_modtime(const char *file, long long *modtime)
360  {
361  	struct uml_stat buf;
362  	int err;
363  
364  	err = os_stat_file(file, &buf);
365  	if (err < 0) {
366  		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
367  		       -err);
368  		return err;
369  	}
370  
371  	*modtime = buf.ust_mtime;
372  	return 0;
373  }
374  
os_set_exec_close(int fd)375  int os_set_exec_close(int fd)
376  {
377  	int err;
378  
379  	CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
380  
381  	if (err < 0)
382  		return -errno;
383  	return err;
384  }
385  
os_pipe(int * fds,int stream,int close_on_exec)386  int os_pipe(int *fds, int stream, int close_on_exec)
387  {
388  	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
389  
390  	err = socketpair(AF_UNIX, type, 0, fds);
391  	if (err < 0)
392  		return -errno;
393  
394  	if (!close_on_exec)
395  		return 0;
396  
397  	err = os_set_exec_close(fds[0]);
398  	if (err < 0)
399  		goto error;
400  
401  	err = os_set_exec_close(fds[1]);
402  	if (err < 0)
403  		goto error;
404  
405  	return 0;
406  
407   error:
408  	printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
409  	       -err);
410  	close(fds[1]);
411  	close(fds[0]);
412  	return err;
413  }
414  
os_set_fd_async(int fd)415  int os_set_fd_async(int fd)
416  {
417  	int err, flags;
418  
419  	flags = fcntl(fd, F_GETFL);
420  	if (flags < 0)
421  		return -errno;
422  
423  	flags |= O_ASYNC | O_NONBLOCK;
424  	if (fcntl(fd, F_SETFL, flags) < 0) {
425  		err = -errno;
426  		printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
427  		       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
428  		return err;
429  	}
430  
431  	if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
432  	    (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
433  		err = -errno;
434  		printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
435  		       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
436  		return err;
437  	}
438  
439  	return 0;
440  }
441  
os_clear_fd_async(int fd)442  int os_clear_fd_async(int fd)
443  {
444  	int flags;
445  
446  	flags = fcntl(fd, F_GETFL);
447  	if (flags < 0)
448  		return -errno;
449  
450  	flags &= ~(O_ASYNC | O_NONBLOCK);
451  	if (fcntl(fd, F_SETFL, flags) < 0)
452  		return -errno;
453  	return 0;
454  }
455  
os_set_fd_block(int fd,int blocking)456  int os_set_fd_block(int fd, int blocking)
457  {
458  	int flags;
459  
460  	flags = fcntl(fd, F_GETFL);
461  	if (flags < 0)
462  		return -errno;
463  
464  	if (blocking)
465  		flags &= ~O_NONBLOCK;
466  	else
467  		flags |= O_NONBLOCK;
468  
469  	if (fcntl(fd, F_SETFL, flags) < 0)
470  		return -errno;
471  
472  	return 0;
473  }
474  
os_accept_connection(int fd)475  int os_accept_connection(int fd)
476  {
477  	int new;
478  
479  	new = accept(fd, NULL, 0);
480  	if (new < 0)
481  		return -errno;
482  	return new;
483  }
484  
485  #ifndef SHUT_RD
486  #define SHUT_RD 0
487  #endif
488  
489  #ifndef SHUT_WR
490  #define SHUT_WR 1
491  #endif
492  
493  #ifndef SHUT_RDWR
494  #define SHUT_RDWR 2
495  #endif
496  
os_shutdown_socket(int fd,int r,int w)497  int os_shutdown_socket(int fd, int r, int w)
498  {
499  	int what, err;
500  
501  	if (r && w)
502  		what = SHUT_RDWR;
503  	else if (r)
504  		what = SHUT_RD;
505  	else if (w)
506  		what = SHUT_WR;
507  	else
508  		return -EINVAL;
509  
510  	err = shutdown(fd, what);
511  	if (err < 0)
512  		return -errno;
513  	return 0;
514  }
515  
516  /**
517   * os_rcv_fd_msg - receive message with (optional) FDs
518   * @fd: the FD to receive from
519   * @fds: the array for FDs to write to
520   * @n_fds: number of FDs to receive (@fds array size)
521   * @data: the message buffer
522   * @data_len: the size of the message to receive
523   *
524   * Receive a message with FDs.
525   *
526   * Returns: the size of the received message, or an error code
527   */
os_rcv_fd_msg(int fd,int * fds,unsigned int n_fds,void * data,size_t data_len)528  ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
529  		      void *data, size_t data_len)
530  {
531  #define MAX_RCV_FDS	2
532  	char buf[CMSG_SPACE(sizeof(*fds) * MAX_RCV_FDS)];
533  	struct cmsghdr *cmsg;
534  	struct iovec iov = {
535  		.iov_base = data,
536  		.iov_len = data_len,
537  	};
538  	struct msghdr msg = {
539  		.msg_iov = &iov,
540  		.msg_iovlen = 1,
541  		.msg_control = buf,
542  		.msg_controllen = CMSG_SPACE(sizeof(*fds) * n_fds),
543  	};
544  	int n;
545  
546  	if (n_fds > MAX_RCV_FDS)
547  		return -EINVAL;
548  
549  	n = recvmsg(fd, &msg, 0);
550  	if (n < 0)
551  		return -errno;
552  
553  	cmsg = CMSG_FIRSTHDR(&msg);
554  	if (!cmsg ||
555  	    cmsg->cmsg_level != SOL_SOCKET ||
556  	    cmsg->cmsg_type != SCM_RIGHTS)
557  		return n;
558  
559  	memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len);
560  	return n;
561  }
562  
os_create_unix_socket(const char * file,int len,int close_on_exec)563  int os_create_unix_socket(const char *file, int len, int close_on_exec)
564  {
565  	struct sockaddr_un addr;
566  	int sock, err;
567  
568  	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
569  	if (sock < 0)
570  		return -errno;
571  
572  	if (close_on_exec) {
573  		err = os_set_exec_close(sock);
574  		if (err < 0)
575  			printk(UM_KERN_ERR "create_unix_socket : "
576  			       "close_on_exec failed, err = %d", -err);
577  	}
578  
579  	addr.sun_family = AF_UNIX;
580  
581  	snprintf(addr.sun_path, len, "%s", file);
582  
583  	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
584  	if (err < 0)
585  		return -errno;
586  
587  	return sock;
588  }
589  
os_flush_stdout(void)590  void os_flush_stdout(void)
591  {
592  	fflush(stdout);
593  }
594  
os_lock_file(int fd,int excl)595  int os_lock_file(int fd, int excl)
596  {
597  	int type = excl ? F_WRLCK : F_RDLCK;
598  	struct flock lock = ((struct flock) { .l_type	= type,
599  					      .l_whence	= SEEK_SET,
600  					      .l_start	= 0,
601  					      .l_len	= 0 } );
602  	int err, save;
603  
604  	err = fcntl(fd, F_SETLK, &lock);
605  	if (!err)
606  		goto out;
607  
608  	save = -errno;
609  	err = fcntl(fd, F_GETLK, &lock);
610  	if (err) {
611  		err = -errno;
612  		goto out;
613  	}
614  
615  	printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
616  	       lock.l_pid);
617  	err = save;
618   out:
619  	return err;
620  }
621  
os_major(unsigned long long dev)622  unsigned os_major(unsigned long long dev)
623  {
624  	return major(dev);
625  }
626  
os_minor(unsigned long long dev)627  unsigned os_minor(unsigned long long dev)
628  {
629  	return minor(dev);
630  }
631  
os_makedev(unsigned major,unsigned minor)632  unsigned long long os_makedev(unsigned major, unsigned minor)
633  {
634  	return makedev(major, minor);
635  }
636  
os_falloc_punch(int fd,unsigned long long offset,int len)637  int os_falloc_punch(int fd, unsigned long long offset, int len)
638  {
639  	int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
640  
641  	if (n < 0)
642  		return -errno;
643  	return n;
644  }
645  
os_falloc_zeroes(int fd,unsigned long long offset,int len)646  int os_falloc_zeroes(int fd, unsigned long long offset, int len)
647  {
648  	int n = fallocate(fd, FALLOC_FL_ZERO_RANGE|FALLOC_FL_KEEP_SIZE, offset, len);
649  
650  	if (n < 0)
651  		return -errno;
652  	return n;
653  }
654  
os_eventfd(unsigned int initval,int flags)655  int os_eventfd(unsigned int initval, int flags)
656  {
657  	int fd = eventfd(initval, flags);
658  
659  	if (fd < 0)
660  		return -errno;
661  	return fd;
662  }
663  
os_sendmsg_fds(int fd,const void * buf,unsigned int len,const int * fds,unsigned int fds_num)664  int os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
665  		   unsigned int fds_num)
666  {
667  	struct iovec iov = {
668  		.iov_base = (void *) buf,
669  		.iov_len = len,
670  	};
671  	union {
672  		char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
673  		struct cmsghdr align;
674  	} u;
675  	unsigned int fds_size = sizeof(*fds) * fds_num;
676  	struct msghdr msg = {
677  		.msg_iov = &iov,
678  		.msg_iovlen = 1,
679  		.msg_control = u.control,
680  		.msg_controllen = CMSG_SPACE(fds_size),
681  	};
682  	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
683  	int err;
684  
685  	if (fds_num > OS_SENDMSG_MAX_FDS)
686  		return -EINVAL;
687  	memset(u.control, 0, sizeof(u.control));
688  	cmsg->cmsg_level = SOL_SOCKET;
689  	cmsg->cmsg_type = SCM_RIGHTS;
690  	cmsg->cmsg_len = CMSG_LEN(fds_size);
691  	memcpy(CMSG_DATA(cmsg), fds, fds_size);
692  	err = sendmsg(fd, &msg, 0);
693  
694  	if (err < 0)
695  		return -errno;
696  	return err;
697  }
698  
os_poll(unsigned int n,const int * fds)699  int os_poll(unsigned int n, const int *fds)
700  {
701  	/* currently need 2 FDs at most so avoid dynamic allocation */
702  	struct pollfd pollfds[2] = {};
703  	unsigned int i;
704  	int ret;
705  
706  	if (n > ARRAY_SIZE(pollfds))
707  		return -EINVAL;
708  
709  	for (i = 0; i < n; i++) {
710  		pollfds[i].fd = fds[i];
711  		pollfds[i].events = POLLIN;
712  	}
713  
714  	ret = poll(pollfds, n, -1);
715  	if (ret < 0)
716  		return -errno;
717  
718  	/* Return the index of the available FD */
719  	for (i = 0; i < n; i++) {
720  		if (pollfds[i].revents)
721  			return i;
722  	}
723  
724  	return -EIO;
725  }
726  
os_mmap_rw_shared(int fd,size_t size)727  void *os_mmap_rw_shared(int fd, size_t size)
728  {
729  	void *res = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
730  
731  	if (res == MAP_FAILED)
732  		return NULL;
733  
734  	return res;
735  }
736  
os_mremap_rw_shared(void * old_addr,size_t old_size,size_t new_size)737  void *os_mremap_rw_shared(void *old_addr, size_t old_size, size_t new_size)
738  {
739  	void *res;
740  
741  	res = mremap(old_addr, old_size, new_size, MREMAP_MAYMOVE, NULL);
742  
743  	if (res == MAP_FAILED)
744  		return NULL;
745  
746  	return res;
747  }
748