* [Qemu-devel] [PATCH v2] linux-user: Implement capget, capset
@ 2014-03-17 12:15 Peter Maydell
2014-03-17 14:43 ` Riku Voipio
0 siblings, 1 reply; 2+ messages in thread
From: Peter Maydell @ 2014-03-17 12:15 UTC (permalink / raw)
To: qemu-devel; +Cc: Riku Voipio, patches
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 <peter.maydell@linaro.org>
---
Changes v1->v2: initialize target_data to NULL to suppress a gcc 4.8
warning; roll our own capget() and capset() rather than relying on
the sys/capability.h header that is in an optional package rather
than libc proper.
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 2a8b66c..49244f8 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, },
@@ -7641,9 +7646,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) || \
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 732c9e3..7db878a 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -2559,3 +2559,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.9.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH v2] linux-user: Implement capget, capset
2014-03-17 12:15 [Qemu-devel] [PATCH v2] linux-user: Implement capget, capset Peter Maydell
@ 2014-03-17 14:43 ` Riku Voipio
0 siblings, 0 replies; 2+ messages in thread
From: Riku Voipio @ 2014-03-17 14:43 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-devel
On Mon, Mar 17, 2014 at 12:15:35PM +0000, Peter Maydell wrote:
> 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 <peter.maydell@linaro.org>
> ---
> Changes v1->v2: initialize target_data to NULL to suppress a gcc 4.8
> warning; roll our own capget() and capset() rather than relying on
> the sys/capability.h header that is in an optional package rather
> than libc proper.
Thanks, looks good and passes the ltp tests. Honestly, I think putting
this to 2.0 past freeze is sloppy maintainership from me - but I trust
you would fix any issues caused by this patch rapidly ;)
I've included in the to-be-pull req:
http://git.linaro.org/people/riku.voipio/qemu.git/shortlog/refs/heads/linux-user-for-upstream
If someone protests, I can replace it with nowarn version.
Riku
> 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 2a8b66c..49244f8 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, },
> @@ -7641,9 +7646,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) || \
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 732c9e3..7db878a 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -2559,3 +2559,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.9.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-03-17 14:43 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-17 12:15 [Qemu-devel] [PATCH v2] linux-user: Implement capget, capset Peter Maydell
2014-03-17 14:43 ` Riku Voipio
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).