1
0
mirror of https://gitlab.com/qemu-project/qemu synced 2024-07-08 20:17:27 +00:00

bsd-user: Next round of syscalls

Implement the next round of system calls. These are open, openat, close,
 fdatasync, fsync, close_from, revoke, access, eacccess, facccessat, chdir,
 fchdir, rename, renameat, mkdir, mkdirat, rmdir, _getcwd, dup, dup2, truncate,
 ftruncate, acct and sync. In addition, the helper functions needed for these to
 work are included. With the helper functions, all of these system calls are the
 'obvious' wrapper...
 -----BEGIN PGP SIGNATURE-----
 Comment: GPGTools - https://gpgtools.org
 
 iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmKvZSwACgkQbBzRKH2w
 EQCrdxAA0UeXmh/l1znPSrX4lif7Vhe4H5TdmHavGQX0p7B+dMd160SMLfKFJt7J
 HHXuQZbPFNuwqE5qiFPTcXIFjT5tq2WSjd9ZC/ZexfzBJIICwcUWuWvG2WfCA3fD
 hth/Ru2fX0vUwoUwvYw7lTPnhb9o52Z1rf5AEFu85E3UjKWEcARHCakm7n8a+Cg+
 PkF1qZ/qFic+bkBZkZLWyHB5qR2p2sIp+VHwlG1ew39Xim457kynQOoF8etIXc1Y
 g5PrjePUsVhPR7qm4CFplM4UOyGOOqIykHERppaXKtk2+kP8dp9HWog9Z/IFVOKc
 z3huDtf03UtmohjdJBYkpCcCzmd2EETRPgkFaVT5ciVGMb3Nom1b2/DOnndpS9qb
 TdE7J6Ek1vp4Mr386QHzm6AfdoHGZc4tH+SpDQZrsWbnugklYnQd3++GCqj8D2rA
 LJ8oWInviZP8xWDn5q1sXCNw/lgVup9ZNrMl7TcXmQDZXHSW1tElIAT2PZCebman
 rSwg/umr7fPOXdIAkLhF77bAt3J3kAzxhuYwHEstB3kRXEJ2VinLMf3BJBrGLnuK
 kr6kJy6hw7luIT5nUNLrrNtwsAAwEu6S7OSGhEiGaUSIhiER96k/tX2u/KOBtwGC
 VzIP7vK5V2xYPepyj4tXkVRHkjxxw3s8fYRXf73IsaZ6Avot8pg=
 =JmJY
 -----END PGP SIGNATURE-----

Merge tag 'bsd-user-syscall-2022q2-pull-request' of ssh://github.com/qemu-bsd-user/qemu-bsd-user into staging

bsd-user: Next round of syscalls

Implement the next round of system calls. These are open, openat, close,
fdatasync, fsync, close_from, revoke, access, eacccess, facccessat, chdir,
fchdir, rename, renameat, mkdir, mkdirat, rmdir, _getcwd, dup, dup2, truncate,
ftruncate, acct and sync. In addition, the helper functions needed for these to
work are included. With the helper functions, all of these system calls are the
'obvious' wrapper...

# -----BEGIN PGP SIGNATURE-----
# Comment: GPGTools - https://gpgtools.org
#
# iQIzBAABCgAdFiEEIDX4lLAKo898zeG3bBzRKH2wEQAFAmKvZSwACgkQbBzRKH2w
# EQCrdxAA0UeXmh/l1znPSrX4lif7Vhe4H5TdmHavGQX0p7B+dMd160SMLfKFJt7J
# HHXuQZbPFNuwqE5qiFPTcXIFjT5tq2WSjd9ZC/ZexfzBJIICwcUWuWvG2WfCA3fD
# hth/Ru2fX0vUwoUwvYw7lTPnhb9o52Z1rf5AEFu85E3UjKWEcARHCakm7n8a+Cg+
# PkF1qZ/qFic+bkBZkZLWyHB5qR2p2sIp+VHwlG1ew39Xim457kynQOoF8etIXc1Y
# g5PrjePUsVhPR7qm4CFplM4UOyGOOqIykHERppaXKtk2+kP8dp9HWog9Z/IFVOKc
# z3huDtf03UtmohjdJBYkpCcCzmd2EETRPgkFaVT5ciVGMb3Nom1b2/DOnndpS9qb
# TdE7J6Ek1vp4Mr386QHzm6AfdoHGZc4tH+SpDQZrsWbnugklYnQd3++GCqj8D2rA
# LJ8oWInviZP8xWDn5q1sXCNw/lgVup9ZNrMl7TcXmQDZXHSW1tElIAT2PZCebman
# rSwg/umr7fPOXdIAkLhF77bAt3J3kAzxhuYwHEstB3kRXEJ2VinLMf3BJBrGLnuK
# kr6kJy6hw7luIT5nUNLrrNtwsAAwEu6S7OSGhEiGaUSIhiER96k/tX2u/KOBtwGC
# VzIP7vK5V2xYPepyj4tXkVRHkjxxw3s8fYRXf73IsaZ6Avot8pg=
# =JmJY
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 19 Jun 2022 11:04:28 AM PDT
# gpg:                using RSA key 2035F894B00AA3CF7CCDE1B76C1CD1287DB01100
# gpg: Good signature from "Warner Losh <wlosh@netflix.com>" [unknown]
# gpg:                 aka "Warner Losh <imp@bsdimp.com>" [unknown]
# gpg:                 aka "Warner Losh <imp@freebsd.org>" [unknown]
# gpg:                 aka "Warner Losh <imp@village.org>" [unknown]
# gpg:                 aka "Warner Losh <wlosh@bsdimp.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2035 F894 B00A A3CF 7CCD  E1B7 6C1C D128 7DB0 1100

* tag 'bsd-user-syscall-2022q2-pull-request' of ssh://github.com/qemu-bsd-user/qemu-bsd-user:
  bsd-user: Implement acct and sync
  bsd-user: Implement trunctate and ftruncate
  bsd-user: Implement dup and dup2
  bsd-user: Implement rmdir and undocumented __getcwd
  bsd-user: Implement mkdir and mkdirat
  bsd-user: Implement link, linkat, unlink and unlinkat
  bsd-user: Implement rename and renameat
  bsd-user: Implement chdir and fchdir
  bsd-user: Implement revoke, access, eaccess and faccessat
  bsd-user: Implement fdatasync, fsync and close_from
  bsd-user: Implement open, openat and close

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-06-19 13:56:13 -07:00
commit c8b2d41376
3 changed files with 479 additions and 0 deletions

View File

@ -22,11 +22,43 @@
#include "qemu/path.h"
#define LOCK_PATH(p, arg) \
do { \
(p) = lock_user_string(arg); \
if ((p) == NULL) { \
return -TARGET_EFAULT; \
} \
} while (0)
#define UNLOCK_PATH(p, arg) unlock_user(p, arg, 0)
#define LOCK_PATH2(p1, arg1, p2, arg2) \
do { \
(p1) = lock_user_string(arg1); \
if ((p1) == NULL) { \
return -TARGET_EFAULT; \
} \
(p2) = lock_user_string(arg2); \
if ((p2) == NULL) { \
unlock_user(p1, arg1, 0); \
return -TARGET_EFAULT; \
} \
} while (0)
#define UNLOCK_PATH2(p1, arg1, p2, arg2) \
do { \
unlock_user(p2, arg2, 0); \
unlock_user(p1, arg1, 0); \
} while (0)
extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count,
int copy);
extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count,
int copy);
int safe_open(const char *path, int flags, mode_t mode);
int safe_openat(int fd, const char *path, int flags, mode_t mode);
ssize_t safe_read(int fd, void *buf, size_t nbytes);
ssize_t safe_pread(int fd, void *buf, size_t nbytes, off_t offset);
ssize_t safe_readv(int fd, const struct iovec *iov, int iovcnt);
@ -190,4 +222,331 @@ static abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1,
return ret;
}
/* open(2) */
static abi_long do_bsd_open(abi_long arg1, abi_long arg2, abi_long arg3)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(safe_open(path(p), target_to_host_bitmask(arg2,
fcntl_flags_tbl), arg3));
UNLOCK_PATH(p, arg1);
return ret;
}
/* openat(2) */
static abi_long do_bsd_openat(abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg2);
ret = get_errno(safe_openat(arg1, path(p),
target_to_host_bitmask(arg3, fcntl_flags_tbl), arg4));
UNLOCK_PATH(p, arg2);
return ret;
}
/* close(2) */
static inline abi_long do_bsd_close(abi_long arg1)
{
return get_errno(close(arg1));
}
/* fdatasync(2) */
static abi_long do_bsd_fdatasync(abi_long arg1)
{
return get_errno(fdatasync(arg1));
}
/* fsync(2) */
static abi_long do_bsd_fsync(abi_long arg1)
{
return get_errno(fsync(arg1));
}
/* closefrom(2) */
static abi_long do_bsd_closefrom(abi_long arg1)
{
closefrom(arg1); /* returns void */
return get_errno(0);
}
/* revoke(2) */
static abi_long do_bsd_revoke(abi_long arg1)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(revoke(p)); /* XXX path(p)? */
UNLOCK_PATH(p, arg1);
return ret;
}
/* access(2) */
static abi_long do_bsd_access(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(access(path(p), arg2));
UNLOCK_PATH(p, arg1);
return ret;
}
/* eaccess(2) */
static abi_long do_bsd_eaccess(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(eaccess(path(p), arg2));
UNLOCK_PATH(p, arg1);
return ret;
}
/* faccessat(2) */
static abi_long do_bsd_faccessat(abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg2);
ret = get_errno(faccessat(arg1, p, arg3, arg4)); /* XXX path(p)? */
UNLOCK_PATH(p, arg2);
return ret;
}
/* chdir(2) */
static abi_long do_bsd_chdir(abi_long arg1)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(chdir(p)); /* XXX path(p)? */
UNLOCK_PATH(p, arg1);
return ret;
}
/* fchdir(2) */
static abi_long do_bsd_fchdir(abi_long arg1)
{
return get_errno(fchdir(arg1));
}
/* rename(2) */
static abi_long do_bsd_rename(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p1, *p2;
LOCK_PATH2(p1, arg1, p2, arg2);
ret = get_errno(rename(p1, p2)); /* XXX path(p1), path(p2) */
UNLOCK_PATH2(p1, arg1, p2, arg2);
return ret;
}
/* renameat(2) */
static abi_long do_bsd_renameat(abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4)
{
abi_long ret;
void *p1, *p2;
LOCK_PATH2(p1, arg2, p2, arg4);
ret = get_errno(renameat(arg1, p1, arg3, p2));
UNLOCK_PATH2(p1, arg2, p2, arg4);
return ret;
}
/* link(2) */
static abi_long do_bsd_link(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p1, *p2;
LOCK_PATH2(p1, arg1, p2, arg2);
ret = get_errno(link(p1, p2)); /* XXX path(p1), path(p2) */
UNLOCK_PATH2(p1, arg1, p2, arg2);
return ret;
}
/* linkat(2) */
static abi_long do_bsd_linkat(abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
abi_long ret;
void *p1, *p2;
LOCK_PATH2(p1, arg2, p2, arg4);
ret = get_errno(linkat(arg1, p1, arg3, p2, arg5));
UNLOCK_PATH2(p1, arg2, p2, arg4);
return ret;
}
/* unlink(2) */
static abi_long do_bsd_unlink(abi_long arg1)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(unlink(p)); /* XXX path(p) */
UNLOCK_PATH(p, arg1);
return ret;
}
/* unlinkat(2) */
static abi_long do_bsd_unlinkat(abi_long arg1, abi_long arg2,
abi_long arg3)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg2);
ret = get_errno(unlinkat(arg1, p, arg3)); /* XXX path(p) */
UNLOCK_PATH(p, arg2);
return ret;
}
/* mkdir(2) */
static abi_long do_bsd_mkdir(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(mkdir(p, arg2)); /* XXX path(p) */
UNLOCK_PATH(p, arg1);
return ret;
}
/* mkdirat(2) */
static abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2,
abi_long arg3)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg2);
ret = get_errno(mkdirat(arg1, p, arg3));
UNLOCK_PATH(p, arg2);
return ret;
}
/* rmdir(2) */
static abi_long do_bsd_rmdir(abi_long arg1)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
ret = get_errno(rmdir(p)); /* XXX path(p)? */
UNLOCK_PATH(p, arg1);
return ret;
}
/* undocumented __getcwd(char *buf, size_t len) system call */
static abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2)
{
abi_long ret;
void *p;
p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
if (p == NULL) {
return -TARGET_EFAULT;
}
ret = safe_syscall(SYS___getcwd, p, arg2);
unlock_user(p, arg1, ret == 0 ? strlen(p) + 1 : 0);
return get_errno(ret);
}
/* dup(2) */
static abi_long do_bsd_dup(abi_long arg1)
{
return get_errno(dup(arg1));
}
/* dup2(2) */
static abi_long do_bsd_dup2(abi_long arg1, abi_long arg2)
{
return get_errno(dup2(arg1, arg2));
}
/* truncate(2) */
static abi_long do_bsd_truncate(void *cpu_env, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4)
{
abi_long ret;
void *p;
LOCK_PATH(p, arg1);
if (regpairs_aligned(cpu_env) != 0) {
arg2 = arg3;
arg3 = arg4;
}
ret = get_errno(truncate(p, target_arg64(arg2, arg3)));
UNLOCK_PATH(p, arg1);
return ret;
}
/* ftruncate(2) */
static abi_long do_bsd_ftruncate(void *cpu_env, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4)
{
if (regpairs_aligned(cpu_env) != 0) {
arg2 = arg3;
arg3 = arg4;
}
return get_errno(ftruncate(arg1, target_arg64(arg2, arg3)));
}
/* acct(2) */
static abi_long do_bsd_acct(abi_long arg1)
{
abi_long ret;
void *p;
if (arg1 == 0) {
ret = get_errno(acct(NULL));
} else {
LOCK_PATH(p, arg1);
ret = get_errno(acct(path(p)));
UNLOCK_PATH(p, arg1);
}
return ret;
}
/* sync(2) */
static abi_long do_bsd_sync(void)
{
sync();
return 0;
}
#endif /* BSD_FILE_H */

View File

@ -44,6 +44,10 @@
#include "bsd-proc.h"
/* I/O */
safe_syscall3(int, open, const char *, path, int, flags, mode_t, mode);
safe_syscall4(int, openat, int, fd, const char *, path, int, flags, mode_t,
mode);
safe_syscall3(ssize_t, read, int, fd, void *, buf, size_t, nbytes);
safe_syscall4(ssize_t, pread, int, fd, void *, buf, size_t, nbytes, off_t,
offset);
@ -257,6 +261,118 @@ static abi_long freebsd_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_bsd_pwritev(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
break;
case TARGET_FREEBSD_NR_open: /* open(2) */
ret = do_bsd_open(arg1, arg2, arg3);
break;
case TARGET_FREEBSD_NR_openat: /* openat(2) */
ret = do_bsd_openat(arg1, arg2, arg3, arg4);
break;
case TARGET_FREEBSD_NR_close: /* close(2) */
ret = do_bsd_close(arg1);
break;
case TARGET_FREEBSD_NR_fdatasync: /* fdatasync(2) */
ret = do_bsd_fdatasync(arg1);
break;
case TARGET_FREEBSD_NR_fsync: /* fsync(2) */
ret = do_bsd_fsync(arg1);
break;
case TARGET_FREEBSD_NR_freebsd12_closefrom: /* closefrom(2) */
ret = do_bsd_closefrom(arg1);
break;
case TARGET_FREEBSD_NR_revoke: /* revoke(2) */
ret = do_bsd_revoke(arg1);
break;
case TARGET_FREEBSD_NR_access: /* access(2) */
ret = do_bsd_access(arg1, arg2);
break;
case TARGET_FREEBSD_NR_eaccess: /* eaccess(2) */
ret = do_bsd_eaccess(arg1, arg2);
break;
case TARGET_FREEBSD_NR_faccessat: /* faccessat(2) */
ret = do_bsd_faccessat(arg1, arg2, arg3, arg4);
break;
case TARGET_FREEBSD_NR_chdir: /* chdir(2) */
ret = do_bsd_chdir(arg1);
break;
case TARGET_FREEBSD_NR_fchdir: /* fchdir(2) */
ret = do_bsd_fchdir(arg1);
break;
case TARGET_FREEBSD_NR_rename: /* rename(2) */
ret = do_bsd_rename(arg1, arg2);
break;
case TARGET_FREEBSD_NR_renameat: /* renameat(2) */
ret = do_bsd_renameat(arg1, arg2, arg3, arg4);
break;
case TARGET_FREEBSD_NR_link: /* link(2) */
ret = do_bsd_link(arg1, arg2);
break;
case TARGET_FREEBSD_NR_linkat: /* linkat(2) */
ret = do_bsd_linkat(arg1, arg2, arg3, arg4, arg5);
break;
case TARGET_FREEBSD_NR_unlink: /* unlink(2) */
ret = do_bsd_unlink(arg1);
break;
case TARGET_FREEBSD_NR_unlinkat: /* unlinkat(2) */
ret = do_bsd_unlinkat(arg1, arg2, arg3);
break;
case TARGET_FREEBSD_NR_mkdir: /* mkdir(2) */
ret = do_bsd_mkdir(arg1, arg2);
break;
case TARGET_FREEBSD_NR_mkdirat: /* mkdirat(2) */
ret = do_bsd_mkdirat(arg1, arg2, arg3);
break;
case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */
ret = do_bsd_rmdir(arg1);
break;
case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */
ret = do_bsd___getcwd(arg1, arg2);
break;
case TARGET_FREEBSD_NR_dup: /* dup(2) */
ret = do_bsd_dup(arg1);
break;
case TARGET_FREEBSD_NR_dup2: /* dup2(2) */
ret = do_bsd_dup2(arg1, arg2);
break;
case TARGET_FREEBSD_NR_truncate: /* truncate(2) */
ret = do_bsd_truncate(cpu_env, arg1, arg2, arg3, arg4);
break;
case TARGET_FREEBSD_NR_ftruncate: /* ftruncate(2) */
ret = do_bsd_ftruncate(cpu_env, arg1, arg2, arg3, arg4);
break;
case TARGET_FREEBSD_NR_acct: /* acct(2) */
ret = do_bsd_acct(arg1);
break;
case TARGET_FREEBSD_NR_sync: /* sync(2) */
ret = do_bsd_sync();
break;
default:
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
ret = -TARGET_ENOSYS;

View File

@ -226,4 +226,8 @@ type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
return safe_syscall(SYS_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
}
/* So far all target and host bitmasks are the same */
#define target_to_host_bitmask(x, tbl) (x)
#define host_to_target_bitmask(x, tbl) (x)
#endif /* SYSCALL_DEFS_H */