@@ -52,6 +52,7 @@ typedef enum {
/* These print as sets of flags. */
ARG_ATDIRFD,
+ ARG_ATFLAG,
ARG_MODEFLAG,
ARG_OPENFLAG,
@@ -780,7 +780,7 @@ UNUSED static struct flags access_flags[] = {
FLAG_END,
};
-UNUSED static struct flags at_file_flags[] = {
+static struct flags const at_file_flags[] = {
#ifdef AT_EACCESS
FLAG_GENERIC(AT_EACCESS),
#endif
@@ -2693,6 +2693,9 @@ static void print_syscall_def1(const SyscallDef *def, int64_t args[6])
case ARG_ATDIRFD:
len = add_atdirfd(b, rest, arg);
break;
+ case ARG_ATFLAG:
+ len = add_flags(b, rest, at_file_flags, arg, false);
+ break;
case ARG_MODEFLAG:
len = add_flags(b, rest, mode_flags, arg, true);
break;
@@ -7151,93 +7151,6 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
return -TARGET_ENOSYS;
}
}
-#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
- abi_long handle, abi_long mount_id,
- abi_long flags)
-{
- struct file_handle *target_fh;
- struct file_handle *fh;
- int mid = 0;
- abi_long ret;
- char *name;
- unsigned int size, total_size;
-
- if (get_user_s32(size, handle)) {
- return -TARGET_EFAULT;
- }
-
- name = lock_user_string(pathname);
- if (!name) {
- return -TARGET_EFAULT;
- }
-
- total_size = sizeof(struct file_handle) + size;
- target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
- if (!target_fh) {
- unlock_user(name, pathname, 0);
- return -TARGET_EFAULT;
- }
-
- fh = g_malloc0(total_size);
- fh->handle_bytes = size;
-
- ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
- unlock_user(name, pathname, 0);
-
- /* man name_to_handle_at(2):
- * Other than the use of the handle_bytes field, the caller should treat
- * the file_handle structure as an opaque data type
- */
-
- memcpy(target_fh, fh, total_size);
- target_fh->handle_bytes = tswap32(fh->handle_bytes);
- target_fh->handle_type = tswap32(fh->handle_type);
- g_free(fh);
- unlock_user(target_fh, handle, total_size);
-
- if (put_user_s32(mid, mount_id)) {
- return -TARGET_EFAULT;
- }
-
- return ret;
-
-}
-#endif
-
-#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
-static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
- abi_long flags)
-{
- struct file_handle *target_fh;
- struct file_handle *fh;
- unsigned int size, total_size;
- abi_long ret;
-
- if (get_user_s32(size, handle)) {
- return -TARGET_EFAULT;
- }
-
- total_size = sizeof(struct file_handle) + size;
- target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
- if (!target_fh) {
- return -TARGET_EFAULT;
- }
-
- fh = g_memdup(target_fh, total_size);
- fh->handle_bytes = size;
- fh->handle_type = tswap32(target_fh->handle_type);
-
- ret = get_errno(open_by_handle_at(mount_fd, fh,
- target_to_host_bitmask(flags, fcntl_flags_tbl)));
-
- g_free(fh);
-
- unlock_user(target_fh, handle, total_size);
-
- return ret;
-}
-#endif
#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
@@ -7533,17 +7446,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
gdb_exit(cpu_env, arg1);
_exit(arg1);
return 0; /* avoid warning */
-#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
- case TARGET_NR_name_to_handle_at:
- ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
- return ret;
-#endif
-#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
- case TARGET_NR_open_by_handle_at:
- ret = do_open_by_handle_at(arg1, arg2, arg3);
- fd_trans_unregister(ret);
- return ret;
-#endif
case TARGET_NR_brk:
return do_brk(arg1);
#ifdef TARGET_NR_fork
@@ -24,8 +24,12 @@
#include <linux/unistd.h>
+safe_syscall5(int, name_to_handle_at, int, dirfd, const char *, pathname,
+ struct file_handle *, handle, int *, mount_id, int, flags)
safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
int, flags, mode_t, mode)
+safe_syscall3(int, open_by_handle_at, int, mount_fd,
+ struct file_handle *, handle, int, flags)
safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov,
int, iovcnt, unsigned long, pos_l, unsigned long, pos_h)
safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov,
@@ -76,6 +80,90 @@ bitmask_transtbl const fcntl_flags_tbl[] = {
* Helpers for do_openat, manipulating /proc/self/foo.
*/
+SYSCALL_IMPL(name_to_handle_at)
+{
+ struct file_handle *target_fh;
+ struct file_handle *fh;
+ int mid = 0;
+ abi_long ret;
+ char *name;
+ uint32_t size, total_size;
+
+ if (get_user_s32(size, arg3)) {
+ return -TARGET_EFAULT;
+ }
+ total_size = sizeof(struct file_handle) + size;
+ target_fh = lock_user(VERIFY_WRITE, arg3, total_size, 0);
+ if (!target_fh) {
+ return -TARGET_EFAULT;
+ }
+
+ name = lock_user_string(arg2);
+ if (!name) {
+ unlock_user(target_fh, arg3, 0);
+ return -TARGET_EFAULT;
+ }
+
+
+ fh = g_malloc0(total_size);
+ fh->handle_bytes = size;
+
+ ret = get_errno(safe_name_to_handle_at(arg1, path(name), fh, &mid, arg5));
+ unlock_user(name, arg2, 0);
+
+ /* man name_to_handle_at(2):
+ * Other than the use of the handle_bytes field, the caller should treat
+ * the file_handle structure as an opaque data type
+ */
+ if (!is_error(ret)) {
+ memcpy(target_fh, fh, total_size);
+ target_fh->handle_bytes = tswap32(fh->handle_bytes);
+ target_fh->handle_type = tswap32(fh->handle_type);
+ g_free(fh);
+ unlock_user(target_fh, arg3, total_size);
+
+ if (put_user_s32(mid, arg4)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+SYSCALL_DEF(name_to_handle_at,
+ ARG_ATDIRFD, ARG_STR, ARG_PTR, ARG_PTR, ARG_ATFLAG);
+
+SYSCALL_IMPL(open_by_handle_at)
+{
+ abi_long mount_fd = arg1;
+ abi_long handle = arg2;
+ int host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
+ struct file_handle *target_fh;
+ struct file_handle *fh;
+ unsigned int size, total_size;
+ abi_long ret;
+
+ if (get_user_s32(size, handle)) {
+ return -TARGET_EFAULT;
+ }
+ total_size = sizeof(struct file_handle) + size;
+ target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
+ if (!target_fh) {
+ return -TARGET_EFAULT;
+ }
+
+ fh = g_memdup(target_fh, total_size);
+ fh->handle_bytes = size;
+ fh->handle_type = tswap32(target_fh->handle_type);
+
+ ret = get_errno(safe_open_by_handle_at(mount_fd, fh, host_flags));
+
+ g_free(fh);
+ unlock_user(target_fh, handle, total_size);
+
+ fd_trans_unregister(ret);
+ return ret;
+}
+SYSCALL_DEF(open_by_handle_at, ARG_DEC, ARG_PTR, ARG_OPENFLAG);
+
static int open_self_cmdline(void *cpu_env, int fd)
{
CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
@@ -26,7 +26,9 @@ import sys
# Avoiding ifdefs for these can diagnose typos in $cpu/syscall_nr.h
unconditional_syscalls = [
"close",
+ "name_to_handle_at",
"openat",
+ "open_by_handle_at",
"pread64",
"preadv",
"pwrite64",
@@ -635,9 +635,6 @@
#ifdef TARGET_NR_munmap
{ TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL },
#endif
-#ifdef TARGET_NR_name_to_handle_at
-{ TARGET_NR_name_to_handle_at, "name_to_handle_at" , NULL, NULL, NULL },
-#endif
#ifdef TARGET_NR_nanosleep
{ TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL },
#endif
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/syscall.h | 1 + linux-user/strace.c | 5 +- linux-user/syscall.c | 98 ---------------------------------- linux-user/syscall_file.c | 88 ++++++++++++++++++++++++++++++ linux-user/gen_syscall_list.py | 2 + linux-user/strace.list | 3 -- 6 files changed, 95 insertions(+), 102 deletions(-) -- 2.17.1