This series of syscalls replaces the old mount(2) syscall with a series of syscalls that operates around a filesystem context. This series of syscalls is available since Linux 5.2 and glibc 2.36+.
Their users include systemd since v259 and libmount from util-linux, and possibly other widely used projects. Preliminary checks are implemented to ensure the validity of the interface. Signed-off-by: Xinhui Yang <[email protected]> --- linux-user/syscall.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7d7a7b489c..c5c2aa80ec 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -14412,6 +14412,97 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return do_map_shadow_stack(cpu_env, arg1, arg2, arg3); #endif +#if defined(TARGET_NR_fsopen) + case TARGET_NR_fsopen: + { + p = lock_user_string(arg1); + if (!p) { + return -TARGET_EFAULT; + } + ret = get_errno(fsopen(p, arg2)); + unlock_user(p, arg1, 0); + } + return ret; + case TARGET_NR_fsconfig: + { + /* + * fsconfig(int, int, char *, void *, int) + * NOTE: p4 is nullable and its type might not be a string. + */ + void *p3, *p4; + int cmd = (int) arg2; + switch (cmd) { + case FSCONFIG_SET_BINARY: + case FSCONFIG_SET_STRING: + case FSCONFIG_SET_PATH: + case FSCONFIG_SET_PATH_EMPTY: + p3 = lock_user_string(arg3); + if (!p3) { + return -TARGET_EFAULT; + } + if (cmd != FSCONFIG_SET_BINARY) { + /* key and value must be strings. */ + p4 = lock_user_string(arg4); + } else { + /* + * Otherwise the value must be a raw buffer with its + * length specified in arg5 (aux). + */ + p4 = lock_user(VERIFY_READ, arg4, arg5, 1); + } + if (!p4) { + unlock_user(p3, arg3, 0); + return -TARGET_EFAULT; + } + ret = get_errno(fsconfig(arg1, arg2, p3, p4, arg5)); + unlock_user(p3, arg3, 0); + unlock_user(p4, arg4, 0); + break; + + case FSCONFIG_SET_FLAG: + case FSCONFIG_SET_FD: + /* arg4 (value) must be NULL. */ + if (arg4) { + return -TARGET_EFAULT; + } + p3 = lock_user_string(arg3); + if (!p3) { + return -TARGET_EFAULT; + } + ret = get_errno(fsconfig(arg1, arg2, p3, NULL, arg5)); + unlock_user(p3, arg3, 0); + break; + case FSCONFIG_CMD_CREATE: + case FSCONFIG_CMD_RECONFIGURE: +#ifdef FSCONFIG_CMD_CREATE_EXCL + /* + * FSCONFIG_CMD_CREATE_EXCL is only available since Linux + * 6.6. Guarding it to allow building with pre-6.6 headers. + */ + case FSCONFIG_CMD_CREATE_EXCL: +#endif + /* key and value must be NULL, aux must be 0. */ + if (arg3 || arg4 || arg5) { + return -TARGET_EFAULT; + } + ret = get_errno(fsconfig(arg1, arg2, NULL, NULL, 0)); + break; + default: + return -TARGET_EFAULT; + } + } + return ret; + case TARGET_NR_fsmount: + ret = get_errno(fsmount(arg1, arg2, arg3)); + return ret; + case TARGET_NR_fspick: + { + p = lock_user_string(arg2); + ret = get_errno(fspick(arg1, p, arg3)); + unlock_user(p, arg2, 0); + } + return ret; +#endif default: qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num); return -TARGET_ENOSYS; -- 2.52.0
