[PATCH v1 3/4] um: Add full asm/syscall.h support

2015-12-20 Thread Mickaël Salaün
Add subarchitecture-independent implementation of asm-generic/syscall.h
allowing access to user system call parameters and results:
* syscall_get_nr()
* syscall_rollback()
* syscall_get_error()
* syscall_get_return_value()
* syscall_set_return_value()
* syscall_get_arguments()
* syscall_set_arguments()
* syscall_get_arch() provided by arch/x86/um/asm/syscall.h

This provides the necessary syscall helpers needed by
HAVE_ARCH_SECCOMP_FILTER plus syscall_get_error().

This is inspired from Meredydd Luff's patch
(https://gerrit.chromium.org/gerrit/21425).

Signed-off-by: Mickaël Salaün 
Cc: Jeff Dike 
Cc: Richard Weinberger 
Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: H. Peter Anvin 
Cc: x...@kernel.org
Cc: Kees Cook 
Cc: Andy Lutomirski 
Cc: Will Drewry 
Cc: linux-kernel@vger.kernel.org
Cc: user-mode-linux-de...@lists.sourceforge.net
Cc: user-mode-linux-u...@lists.sourceforge.net
Cc: Meredydd Luff 
Cc: David Drysdale 
---
 arch/um/include/asm/syscall-generic.h | 138 ++
 arch/x86/um/asm/syscall.h |   1 +
 2 files changed, 139 insertions(+)
 create mode 100644 arch/um/include/asm/syscall-generic.h

diff --git a/arch/um/include/asm/syscall-generic.h 
b/arch/um/include/asm/syscall-generic.h
new file mode 100644
index 000..9fb9cf8
--- /dev/null
+++ b/arch/um/include/asm/syscall-generic.h
@@ -0,0 +1,138 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for function descriptions.
+ *
+ * Copyright (C) 2015 Mickaël Salaün 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __UM_SYSCALL_GENERIC_H
+#define __UM_SYSCALL_GENERIC_H
+
+#include 
+#include 
+#include 
+#include 
+
+static inline int syscall_get_nr(struct task_struct *task, struct pt_regs 
*regs)
+{
+
+   return PT_REGS_SYSCALL_NR(regs);
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+   struct pt_regs *regs)
+{
+   /* do nothing */
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+struct pt_regs *regs)
+{
+   const long error = regs_return_value(regs);
+
+   return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+   struct pt_regs *regs)
+{
+   return regs_return_value(regs);
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+   struct pt_regs *regs,
+   int error, long val)
+{
+   PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val);
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+struct pt_regs *regs,
+unsigned int i, unsigned int n,
+unsigned long *args)
+{
+   const struct uml_pt_regs *r = >regs;
+
+   switch (i) {
+   case 0:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG1(r);
+   case 1:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG2(r);
+   case 2:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG3(r);
+   case 3:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG4(r);
+   case 4:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG5(r);
+   case 5:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG6(r);
+   case 6:
+   if (!n--)
+   break;
+   default:
+   BUG();
+   break;
+   }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+struct pt_regs *regs,
+unsigned int i, unsigned int n,
+const unsigned long *args)
+{
+   struct uml_pt_regs *r = >regs;
+
+   switch (i) {
+   case 0:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG1(r) = *args++;
+   case 1:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG2(r) = *args++;
+   case 2:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG3(r) = *args++;
+   case 3:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG4(r) = *args++;
+   case 4:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG5(r) = *args++;
+   case 5:
+   if 

[PATCH v1 3/4] um: Add full asm/syscall.h support

2015-12-20 Thread Mickaël Salaün
Add subarchitecture-independent implementation of asm-generic/syscall.h
allowing access to user system call parameters and results:
* syscall_get_nr()
* syscall_rollback()
* syscall_get_error()
* syscall_get_return_value()
* syscall_set_return_value()
* syscall_get_arguments()
* syscall_set_arguments()
* syscall_get_arch() provided by arch/x86/um/asm/syscall.h

This provides the necessary syscall helpers needed by
HAVE_ARCH_SECCOMP_FILTER plus syscall_get_error().

This is inspired from Meredydd Luff's patch
(https://gerrit.chromium.org/gerrit/21425).

Signed-off-by: Mickaël Salaün 
Cc: Jeff Dike 
Cc: Richard Weinberger 
Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: H. Peter Anvin 
Cc: x...@kernel.org
Cc: Kees Cook 
Cc: Andy Lutomirski 
Cc: Will Drewry 
Cc: linux-kernel@vger.kernel.org
Cc: user-mode-linux-de...@lists.sourceforge.net
Cc: user-mode-linux-u...@lists.sourceforge.net
Cc: Meredydd Luff 
Cc: David Drysdale 
---
 arch/um/include/asm/syscall-generic.h | 138 ++
 arch/x86/um/asm/syscall.h |   1 +
 2 files changed, 139 insertions(+)
 create mode 100644 arch/um/include/asm/syscall-generic.h

diff --git a/arch/um/include/asm/syscall-generic.h 
b/arch/um/include/asm/syscall-generic.h
new file mode 100644
index 000..9fb9cf8
--- /dev/null
+++ b/arch/um/include/asm/syscall-generic.h
@@ -0,0 +1,138 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for function descriptions.
+ *
+ * Copyright (C) 2015 Mickaël Salaün 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __UM_SYSCALL_GENERIC_H
+#define __UM_SYSCALL_GENERIC_H
+
+#include 
+#include 
+#include 
+#include 
+
+static inline int syscall_get_nr(struct task_struct *task, struct pt_regs 
*regs)
+{
+
+   return PT_REGS_SYSCALL_NR(regs);
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+   struct pt_regs *regs)
+{
+   /* do nothing */
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+struct pt_regs *regs)
+{
+   const long error = regs_return_value(regs);
+
+   return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+   struct pt_regs *regs)
+{
+   return regs_return_value(regs);
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+   struct pt_regs *regs,
+   int error, long val)
+{
+   PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val);
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+struct pt_regs *regs,
+unsigned int i, unsigned int n,
+unsigned long *args)
+{
+   const struct uml_pt_regs *r = >regs;
+
+   switch (i) {
+   case 0:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG1(r);
+   case 1:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG2(r);
+   case 2:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG3(r);
+   case 3:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG4(r);
+   case 4:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG5(r);
+   case 5:
+   if (!n--)
+   break;
+   *args++ = UPT_SYSCALL_ARG6(r);
+   case 6:
+   if (!n--)
+   break;
+   default:
+   BUG();
+   break;
+   }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+struct pt_regs *regs,
+unsigned int i, unsigned int n,
+const unsigned long *args)
+{
+   struct uml_pt_regs *r = >regs;
+
+   switch (i) {
+   case 0:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG1(r) = *args++;
+   case 1:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG2(r) = *args++;
+   case 2:
+   if (!n--)
+   break;
+   UPT_SYSCALL_ARG3(r) = *args++;
+   case 3:
+   if