[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PULL for-2.0 7/7] linux-user: Implement capget, capset
From: |
Laurent Desnogues |
Subject: |
Re: [Qemu-devel] [PULL for-2.0 7/7] linux-user: Implement capget, capset |
Date: |
Wed, 19 Mar 2014 16:10:59 +0100 |
Hello,
On Wed, Mar 19, 2014 at 3:03 PM, <address@hidden> wrote:
> From: Peter Maydell <address@hidden>
>
> Implement the capget and capset syscalls. This is useful because
> simple programs like 'ls' try to use it in AArch64, and otherwise
> we emit a lot of noise about it being unimplemented.
>
> Signed-off-by: Peter Maydell <address@hidden>
> Signed-off-by: Riku Voipio <address@hidden>
> ---
> linux-user/syscall.c | 75
> +++++++++++++++++++++++++++++++++++++++++++++--
> linux-user/syscall_defs.h | 11 +++++++
> 2 files changed, 84 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index e404a32..366b695 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, },
> @@ -7677,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) {
Sorry for spotting this late, but older kernels (in my case
2.6.18-238.el5, CentOS 5.6) don't have
_LINUX_CAPABILITY_VERSION_1 defined. I think
_LINUX_CAPABILITY_VERSION should be used instead
in that case.
Thanks,
Laurent
> + /* 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) ||
> \
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 2a7d1db..fdf9a47 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -2566,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;
> +};
> --
> 1.8.1.2
>
>
- [Qemu-devel] [PULL for-2.0 0/7] linux-user patches, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 3/7] linux-user: implement F_[GS]ETOWN_EX, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 2/7] linux-user: Don't return uninitialized value for atomic_barrier syscall, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 1/7] linux-user/signal.c: Correct error path for AArch64 do_rt_sigreturn, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 4/7] linux-user: Don't reserve space for commpage for AArch64, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 5/7] signal: added a wrapper for sigprocmask function, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 6/7] linux-user: Don't allow guest to block SIGSEGV, riku . voipio, 2014/03/19
- [Qemu-devel] [PULL for-2.0 7/7] linux-user: Implement capget, capset, riku . voipio, 2014/03/19
- Re: [Qemu-devel] [PULL for-2.0 7/7] linux-user: Implement capget, capset,
Laurent Desnogues <=
- Re: [Qemu-devel] [PULL for-2.0 0/7] linux-user patches, Peter Maydell, 2014/03/19