diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-03-19 14:14:15 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-03-19 14:14:15 +0000 |
commit | 4c8821d13405056776d0255bb78925dac91996c3 (patch) | |
tree | eebc05d5f8c8609a31f9bcc5181e4d20b684360e | |
parent | c1b94a0ed2332b08ea7799c003c3ee9996782a3c (diff) | |
parent | e0eb210ec0c1cd262e3f642133ee93acdaf60aa0 (diff) |
Merge remote-tracking branch 'remotes/riku/linux-user-for-upstream' into staging
* remotes/riku/linux-user-for-upstream:
linux-user: Implement capget, capset
linux-user: Don't allow guest to block SIGSEGV
signal: added a wrapper for sigprocmask function
linux-user: Don't reserve space for commpage for AArch64
linux-user: implement F_[GS]ETOWN_EX
linux-user: Don't return uninitialized value for atomic_barrier syscall
linux-user/signal.c: Correct error path for AArch64 do_rt_sigreturn
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | linux-user/elfload.c | 5 | ||||
-rw-r--r-- | linux-user/qemu.h | 2 | ||||
-rw-r--r-- | linux-user/signal.c | 120 | ||||
-rw-r--r-- | linux-user/syscall.c | 126 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 18 |
5 files changed, 236 insertions, 35 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 6bc799957b..99a2c586eb 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -352,6 +352,9 @@ enum ARM_HWCAP_ARM_VFPv3D16 = 1 << 13, }; +#ifndef TARGET_AARCH64 +/* The commpage only exists for 32 bit kernels */ + #define TARGET_HAS_VALIDATE_GUEST_SPACE /* Return 1 if the proposed guest space is suitable for the guest. * Return 0 if the proposed guest space isn't suitable, but another @@ -411,7 +414,7 @@ static int validate_guest_space(unsigned long guest_base, return 1; /* All good */ } - +#endif #define ELF_HWCAP get_elf_hwcap() diff --git a/linux-user/qemu.h b/linux-user/qemu.h index c2f74f33d6..36d4a738ea 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -126,6 +126,7 @@ typedef struct TaskState { #endif uint32_t stack_base; int used; /* non zero if used */ + bool sigsegv_blocked; /* SIGSEGV blocked by guest */ struct image_info *info; struct linux_binprm *bprm; @@ -235,6 +236,7 @@ int host_to_target_signal(int sig); long do_sigreturn(CPUArchState *env); long do_rt_sigreturn(CPUArchState *env); abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); #ifdef TARGET_I386 /* vm86.c */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 24c91f37d9..e5fb9332e3 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -197,6 +197,55 @@ void target_to_host_old_sigset(sigset_t *sigset, target_to_host_sigset(sigset, &d); } +/* Wrapper for sigprocmask function + * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset + * are host signal set, not guest ones. This wraps the sigprocmask host calls + * that should be protected (calls originated from guest) + */ +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +{ + int ret; + sigset_t val; + sigset_t *temp = NULL; + CPUState *cpu = thread_cpu; + TaskState *ts = (TaskState *)cpu->opaque; + bool segv_was_blocked = ts->sigsegv_blocked; + + if (set) { + bool has_sigsegv = sigismember(set, SIGSEGV); + val = *set; + temp = &val; + + sigdelset(temp, SIGSEGV); + + switch (how) { + case SIG_BLOCK: + if (has_sigsegv) { + ts->sigsegv_blocked = true; + } + break; + case SIG_UNBLOCK: + if (has_sigsegv) { + ts->sigsegv_blocked = false; + } + break; + case SIG_SETMASK: + ts->sigsegv_blocked = has_sigsegv; + break; + default: + g_assert_not_reached(); + } + } + + ret = sigprocmask(how, temp, oldset); + + if (oldset && segv_was_blocked) { + sigaddset(oldset, SIGSEGV); + } + + return ret; +} + /* siginfo conversion */ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, @@ -458,6 +507,19 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) k = &ts->sigtab[sig - 1]; queue = gdb_queuesig (); handler = sigact_table[sig - 1]._sa_handler; + + if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { + /* Guest has blocked SIGSEGV but we got one anyway. Assume this + * is a forced SIGSEGV (ie one the kernel handles via force_sig_info + * because it got a real MMU fault). A blocked SIGSEGV in that + * situation is treated as if using the default handler. This is + * not correct if some other process has randomly sent us a SIGSEGV + * via kill(), but that is not easy to distinguish at this point, + * so we assume it doesn't happen. + */ + handler = TARGET_SIG_DFL; + } + if (!queue && handler == TARGET_SIG_DFL) { if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { kill(getpid(),SIGSTOP); @@ -1056,7 +1118,7 @@ long do_sigreturn(CPUX86State *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ if (restore_sigcontext(env, &frame->sc, &eax)) @@ -1081,7 +1143,7 @@ long do_rt_sigreturn(CPUX86State *env) if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) goto badframe; target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) goto badframe; @@ -1220,7 +1282,7 @@ static int target_restore_sigframe(CPUARMState *env, uint64_t pstate; target_to_host_sigset(&set, &sf->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); for (i = 0; i < 31; i++) { __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); @@ -1340,7 +1402,7 @@ static void setup_frame(int sig, struct target_sigaction *ka, long do_rt_sigreturn(CPUARMState *env) { - struct target_rt_sigframe *frame; + struct target_rt_sigframe *frame = NULL; abi_ulong frame_addr = env->xregs[31]; if (frame_addr & 15) { @@ -1861,7 +1923,7 @@ static long do_sigreturn_v1(CPUARMState *env) } target_to_host_sigset_internal(&host_set, &set); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &frame->sc)) goto badframe; @@ -1942,7 +2004,7 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr, abi_ulong *regspace; target_to_host_sigset(&host_set, &uc->tuc_sigmask); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &uc->tuc_mcontext)) return 1; @@ -2033,7 +2095,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env) goto badframe; target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) goto badframe; @@ -2444,7 +2506,7 @@ long do_sigreturn(CPUSPARCState *env) } target_to_host_sigset_internal(&host_set, &set); - sigprocmask(SIG_SETMASK, &host_set, NULL); + do_sigprocmask(SIG_SETMASK, &host_set, NULL); if (err) goto segv_and_exit; @@ -2567,7 +2629,7 @@ void sparc64_set_context(CPUSPARCState *env) goto do_sigsegv; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); } env->pc = pc; env->npc = npc; @@ -2656,7 +2718,7 @@ void sparc64_get_context(CPUSPARCState *env) err = 0; - sigprocmask(0, NULL, &set); + do_sigprocmask(0, NULL, &set); host_to_target_sigset_internal(&target_set, &set); if (TARGET_NSIG_WORDS == 1) { err |= __put_user(target_set.sig[0], @@ -2991,7 +3053,7 @@ long do_sigreturn(CPUMIPSState *regs) } target_to_host_sigset_internal(&blocked, &target_set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->sf_sc)) goto badframe; @@ -3095,7 +3157,7 @@ long do_rt_sigreturn(CPUMIPSState *env) goto badframe; target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext)) goto badframe; @@ -3385,7 +3447,7 @@ long do_sigreturn(CPUSH4State *regs) goto badframe; target_to_host_sigset_internal(&blocked, &target_set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; @@ -3414,7 +3476,7 @@ long do_rt_sigreturn(CPUSH4State *regs) goto badframe; target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0)) goto badframe; @@ -3644,7 +3706,7 @@ long do_sigreturn(CPUMBState *env) goto badframe; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); restore_sigcontext(&frame->uc.tuc_mcontext, env); /* We got here through a sigreturn syscall, our path back is via an @@ -3819,7 +3881,7 @@ long do_sigreturn(CPUCRISState *env) goto badframe; } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); restore_sigcontext(&frame->sc, env); unlock_user_struct(frame, frame_addr, 0); @@ -4350,7 +4412,7 @@ long do_sigreturn(CPUS390XState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ if (restore_sigregs(env, &frame->sregs)) { goto badframe; @@ -4378,7 +4440,7 @@ long do_rt_sigreturn(CPUS390XState *env) } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { goto badframe; @@ -4906,7 +4968,7 @@ long do_sigreturn(CPUPPCState *env) goto sigsegv; #endif target_to_host_sigset_internal(&blocked, &set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (__get_user(sr_addr, &sc->regs)) goto sigsegv; @@ -4950,7 +5012,7 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) return 1; target_to_host_sigset_internal(&blocked, &set); - sigprocmask(SIG_SETMASK, &blocked, NULL); + do_sigprocmask(SIG_SETMASK, &blocked, NULL); if (restore_user_regs(env, mcp, sig)) goto sigsegv; @@ -5324,7 +5386,7 @@ long do_sigreturn(CPUM68KState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ @@ -5352,7 +5414,7 @@ long do_rt_sigreturn(CPUM68KState *env) goto badframe; target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ @@ -5599,7 +5661,7 @@ long do_sigreturn(CPUAlphaState *env) } target_to_host_sigset_internal(&set, &target_set); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, sc)) { goto badframe; @@ -5622,7 +5684,7 @@ long do_rt_sigreturn(CPUAlphaState *env) goto badframe; } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - sigprocmask(SIG_SETMASK, &set, NULL); + do_sigprocmask(SIG_SETMASK, &set, NULL); if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) { goto badframe; @@ -5716,6 +5778,14 @@ void process_pending_signals(CPUArchState *cpu_env) handler = sa->_sa_handler; } + if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { + /* Guest has blocked SIGSEGV but we got one anyway. Assume this + * is a forced SIGSEGV (ie one the kernel handles via force_sig_info + * because it got a real MMU fault), and treat as if default handler. + */ + handler = TARGET_SIG_DFL; + } + if (handler == TARGET_SIG_DFL) { /* default handler : ignore some signal. The other are job control or fatal */ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { @@ -5739,7 +5809,7 @@ void process_pending_signals(CPUArchState *cpu_env) sigaddset(&set, target_to_host_signal(sig)); /* block signals in the handler using Linux */ - sigprocmask(SIG_BLOCK, &set, &old_set); + do_sigprocmask(SIG_BLOCK, &set, &old_set); /* save the previous blocked signal state to restore it at the end of the signal execution (see do_sigreturn) */ host_to_target_sigset_internal(&target_old_set, &old_set); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ffc11de4b7..366b6951e9 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -43,6 +43,7 @@ #include <sys/resource.h> #include <sys/mman.h> #include <sys/swap.h> +#include <linux/capability.h> #include <signal.h> #include <sched.h> #ifdef __ia64__ @@ -243,6 +244,10 @@ _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); _syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, void *, arg); +_syscall2(int, capget, struct __user_cap_header_struct *, header, + struct __user_cap_data_struct *, data); +_syscall2(int, capset, struct __user_cap_header_struct *, header, + struct __user_cap_data_struct *, data); static bitmask_transtbl fcntl_flags_tbl[] = { { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, @@ -4421,6 +4426,14 @@ static int target_to_host_fcntl_cmd(int cmd) #endif case TARGET_F_NOTIFY: return F_NOTIFY; +#ifdef F_GETOWN_EX + case TARGET_F_GETOWN_EX: + return F_GETOWN_EX; +#endif +#ifdef F_SETOWN_EX + case TARGET_F_SETOWN_EX: + return F_SETOWN_EX; +#endif default: return -TARGET_EINVAL; } @@ -4443,6 +4456,10 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) struct target_flock *target_fl; struct flock64 fl64; struct target_flock64 *target_fl64; +#ifdef F_GETOWN_EX + struct f_owner_ex fox; + struct target_f_owner_ex *target_fox; +#endif abi_long ret; int host_cmd = target_to_host_fcntl_cmd(cmd); @@ -4536,6 +4553,30 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl))); break; +#ifdef F_GETOWN_EX + case TARGET_F_GETOWN_EX: + ret = get_errno(fcntl(fd, host_cmd, &fox)); + if (ret >= 0) { + if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0)) + return -TARGET_EFAULT; + target_fox->type = tswap32(fox.type); + target_fox->pid = tswap32(fox.pid); + unlock_user_struct(target_fox, arg, 1); + } + break; +#endif + +#ifdef F_SETOWN_EX + case TARGET_F_SETOWN_EX: + if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1)) + return -TARGET_EFAULT; + fox.type = tswap32(target_fox->type); + fox.pid = tswap32(target_fox->pid); + unlock_user_struct(target_fox, arg, 0); + ret = get_errno(fcntl(fd, host_cmd, &fox)); + break; +#endif + case TARGET_F_SETOWN: case TARGET_F_GETOWN: case TARGET_F_SETSIG: @@ -5993,7 +6034,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { sigset_t cur_set; abi_ulong target_set; - sigprocmask(0, NULL, &cur_set); + do_sigprocmask(0, NULL, &cur_set); host_to_target_old_sigset(&target_set, &cur_set); ret = target_set; } @@ -6004,10 +6045,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { sigset_t set, oset, cur_set; abi_ulong target_set = arg1; - sigprocmask(0, NULL, &cur_set); + do_sigprocmask(0, NULL, &cur_set); target_to_host_old_sigset(&set, &target_set); sigorset(&set, &set, &cur_set); - sigprocmask(SIG_SETMASK, &set, &oset); + do_sigprocmask(SIG_SETMASK, &set, &oset); host_to_target_old_sigset(&target_set, &oset); ret = target_set; } @@ -6038,7 +6079,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, mask = arg2; target_to_host_old_sigset(&set, &mask); - ret = get_errno(sigprocmask(how, &set, &oldset)); + ret = get_errno(do_sigprocmask(how, &set, &oldset)); if (!is_error(ret)) { host_to_target_old_sigset(&mask, &oldset); ret = mask; @@ -6072,7 +6113,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, how = 0; set_ptr = NULL; } - ret = get_errno(sigprocmask(how, set_ptr, &oldset)); + ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); if (!is_error(ret) && arg3) { if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) goto efault; @@ -6112,7 +6153,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, how = 0; set_ptr = NULL; } - ret = get_errno(sigprocmask(how, set_ptr, &oldset)); + ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); if (!is_error(ret) && arg3) { if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) goto efault; @@ -7641,9 +7682,75 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, ret); break; case TARGET_NR_capget: - goto unimplemented; case TARGET_NR_capset: - goto unimplemented; + { + struct target_user_cap_header *target_header; + struct target_user_cap_data *target_data = NULL; + struct __user_cap_header_struct header; + struct __user_cap_data_struct data[2]; + struct __user_cap_data_struct *dataptr = NULL; + int i, target_datalen; + int data_items = 1; + + if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) { + goto efault; + } + header.version = tswap32(target_header->version); + header.pid = tswap32(target_header->pid); + + if (header.version != _LINUX_CAPABILITY_VERSION_1) { + /* Version 2 and up takes pointer to two user_data structs */ + data_items = 2; + } + + target_datalen = sizeof(*target_data) * data_items; + + if (arg2) { + if (num == TARGET_NR_capget) { + target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0); + } else { + target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1); + } + if (!target_data) { + unlock_user_struct(target_header, arg1, 0); + goto efault; + } + + if (num == TARGET_NR_capset) { + for (i = 0; i < data_items; i++) { + data[i].effective = tswap32(target_data[i].effective); + data[i].permitted = tswap32(target_data[i].permitted); + data[i].inheritable = tswap32(target_data[i].inheritable); + } + } + + dataptr = data; + } + + if (num == TARGET_NR_capget) { + ret = get_errno(capget(&header, dataptr)); + } else { + ret = get_errno(capset(&header, dataptr)); + } + + /* The kernel always updates version for both capget and capset */ + target_header->version = tswap32(header.version); + unlock_user_struct(target_header, arg1, 1); + + if (arg2) { + if (num == TARGET_NR_capget) { + for (i = 0; i < data_items; i++) { + target_data[i].effective = tswap32(data[i].effective); + target_data[i].permitted = tswap32(data[i].permitted); + target_data[i].inheritable = tswap32(data[i].inheritable); + } + unlock_user(target_data, arg2, target_datalen); + } else { + unlock_user(target_data, arg2, 0); + } + } + break; + } case TARGET_NR_sigaltstack: #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ @@ -8125,7 +8232,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } mask = arg2; target_to_host_old_sigset(&set, &mask); - sigprocmask(how, &set, &oldset); + do_sigprocmask(how, &set, &oldset); host_to_target_old_sigset(&mask, &oldset); ret = mask; } @@ -9148,6 +9255,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_atomic_barrier: { /* Like the kernel implementation and the qemu arm barrier, no-op this? */ + ret = 0; break; } #endif diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 732c9e3dbb..fdf9a47595 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2123,6 +2123,8 @@ struct target_statfs64 { #define TARGET_F_SETOWN 8 /* for sockets. */ #define TARGET_F_GETOWN 9 /* for sockets. */ #endif +#define TARGET_F_SETOWN_EX 15 +#define TARGET_F_GETOWN_EX 16 #ifndef TARGET_F_RDLCK #define TARGET_F_RDLCK 0 @@ -2305,6 +2307,11 @@ struct target_eabi_flock64 { } QEMU_PACKED; #endif +struct target_f_owner_ex { + int type; /* Owner type of ID. */ + int pid; /* ID of owner. */ +}; + /* soundcard defines */ /* XXX: convert them all to arch indepedent entries */ #define TARGET_SNDCTL_COPR_HALT TARGET_IOWR('C', 7, int); @@ -2559,3 +2566,14 @@ struct target_sigevent { } _sigev_thread; } _sigev_un; }; + +struct target_user_cap_header { + uint32_t version; + int pid; +}; + +struct target_user_cap_data { + uint32_t effective; + uint32_t permitted; + uint32_t inheritable; +}; |