[sys-kernel/*] spring cleanup, drop anything <3.0
This commit is contained in:
-122
@@ -1,122 +0,0 @@
|
||||
--- linux-2.6.33-sabayon.orig/arch/ia64/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/ia64/include/asm/compat.h
|
||||
@@ -198,7 +198,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
--- linux-2.6.33-sabayon.orig/arch/mips/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/mips/include/asm/compat.h
|
||||
@@ -144,7 +144,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
--- linux-2.6.33-sabayon.orig/arch/parisc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/parisc/include/asm/compat.h
|
||||
@@ -146,7 +146,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
--- linux-2.6.33-sabayon.orig/arch/powerpc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/powerpc/include/asm/compat.h
|
||||
@@ -133,7 +133,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
--- linux-2.6.33-sabayon.orig/arch/s390/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/s390/include/asm/compat.h
|
||||
@@ -180,7 +180,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
--- linux-2.6.33-sabayon.orig/arch/sparc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/sparc/include/asm/compat.h
|
||||
@@ -166,7 +166,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
--- linux-2.6.33-sabayon.orig/arch/x86/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/x86/include/asm/compat.h
|
||||
@@ -204,7 +204,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
--- linux-2.6.33-sabayon.orig/include/linux/compat.h
|
||||
+++ linux-2.6.33-sabayon/include/linux/compat.h
|
||||
@@ -353,5 +353,7 @@ asmlinkage long compat_sys_newfstatat(un
|
||||
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
|
||||
int flags, int mode);
|
||||
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
--- linux-2.6.33-sabayon.orig/kernel/compat.c
|
||||
+++ linux-2.6.33-sabayon/kernel/compat.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/security.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/migrate.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/times.h>
|
||||
#include <linux/ptrace.h>
|
||||
@@ -1139,3 +1140,24 @@ compat_sys_sysinfo(struct compat_sysinfo
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
|
||||
commit eefdca043e8391dcd719711716492063030b55ac upstream.
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
|
||||
commit 36d001c70d8a0144ac1d038f6876c484849a74de upstream.
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
--- linux-2.6.34-sabayon.orig/arch/ia64/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/ia64/include/asm/compat.h 2010-09-18 17:09:30.728304722 +0200
|
||||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
--- linux-2.6.34-sabayon.orig/arch/mips/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/mips/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
--- linux-2.6.34-sabayon.orig/arch/parisc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/parisc/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
--- linux-2.6.34-sabayon.orig/arch/powerpc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/powerpc/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
--- linux-2.6.34-sabayon.orig/arch/s390/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/s390/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
--- linux-2.6.34-sabayon.orig/arch/sparc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/sparc/include/asm/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
--- linux-2.6.34-sabayon.orig/arch/x86/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/x86/include/asm/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
--- linux-2.6.34-sabayon.orig/include/linux/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/include/linux/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -356,5 +356,7 @@ asmlinkage long compat_sys_newfstatat(un
|
||||
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
|
||||
int flags, int mode);
|
||||
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
--- linux-2.6.34-sabayon.orig/kernel/compat.c 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/kernel/compat.c 2010-09-18 17:09:58.574836565 +0200
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/times.h>
|
||||
#include <linux/ptrace.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
@@ -1140,3 +1141,24 @@ compat_sys_sysinfo(struct compat_sysinfo
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
|
||||
commit eefdca043e8391dcd719711716492063030b55ac upstream.
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
|
||||
commit 36d001c70d8a0144ac1d038f6876c484849a74de upstream.
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: [PATCH] x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: <stable@kernel.org>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index b86feab..84e3a4e 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-190
@@ -1,190 +0,0 @@
|
||||
From c41d68a513c71e35a14f66d71782d27a79a81ea6 Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 7 Sep 2010 16:16:18 -0700
|
||||
Subject: [PATCH] compat: Make compat_alloc_user_space() incorporate the access_ok()
|
||||
|
||||
compat_alloc_user_space() expects the caller to independently call
|
||||
access_ok() to verify the returned area. A missing call could
|
||||
introduce problems on some architectures.
|
||||
|
||||
This patch incorporates the access_ok() check into
|
||||
compat_alloc_user_space() and also adds a sanity check on the length.
|
||||
The existing compat_alloc_user_space() implementations are renamed
|
||||
arch_compat_alloc_user_space() and are used as part of the
|
||||
implementation of the new global function.
|
||||
|
||||
This patch assumes NULL will cause __get_user()/__put_user() to either
|
||||
fail or access userspace on all architectures. This should be
|
||||
followed by checking the return value of compat_access_user_space()
|
||||
for NULL in the callers, at which time the access_ok() in the callers
|
||||
can also be removed.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
|
||||
Acked-by: David S. Miller <davem@davemloft.net>
|
||||
Acked-by: Ingo Molnar <mingo@elte.hu>
|
||||
Acked-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Acked-by: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Fenghua Yu <fenghua.yu@intel.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
|
||||
Cc: Helge Deller <deller@gmx.de>
|
||||
Cc: James Bottomley <jejb@parisc-linux.org>
|
||||
Cc: Kyle McMartin <kyle@mcmartin.ca>
|
||||
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
Cc: Paul Mackerras <paulus@samba.org>
|
||||
Cc: Ralf Baechle <ralf@linux-mips.org>
|
||||
Cc: <stable@kernel.org>
|
||||
---
|
||||
arch/ia64/include/asm/compat.h | 2 +-
|
||||
arch/mips/include/asm/compat.h | 2 +-
|
||||
arch/parisc/include/asm/compat.h | 2 +-
|
||||
arch/powerpc/include/asm/compat.h | 2 +-
|
||||
arch/s390/include/asm/compat.h | 2 +-
|
||||
arch/sparc/include/asm/compat.h | 2 +-
|
||||
arch/tile/include/asm/compat.h | 2 +-
|
||||
arch/x86/include/asm/compat.h | 2 +-
|
||||
include/linux/compat.h | 3 +++
|
||||
kernel/compat.c | 21 +++++++++++++++++++++
|
||||
10 files changed, 32 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
|
||||
index f90edc8..9301a28 100644
|
||||
--- a/arch/ia64/include/asm/compat.h
|
||||
+++ b/arch/ia64/include/asm/compat.h
|
||||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
|
||||
index 613f691..dbc5106 100644
|
||||
--- a/arch/mips/include/asm/compat.h
|
||||
+++ b/arch/mips/include/asm/compat.h
|
||||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
|
||||
index 02b77ba..efa0b60 100644
|
||||
--- a/arch/parisc/include/asm/compat.h
|
||||
+++ b/arch/parisc/include/asm/compat.h
|
||||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
|
||||
index 396d21a..a11d4ea 100644
|
||||
--- a/arch/powerpc/include/asm/compat.h
|
||||
+++ b/arch/powerpc/include/asm/compat.h
|
||||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
|
||||
index 104f200..a875c2f 100644
|
||||
--- a/arch/s390/include/asm/compat.h
|
||||
+++ b/arch/s390/include/asm/compat.h
|
||||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
|
||||
index 5016f76..6f57325 100644
|
||||
--- a/arch/sparc/include/asm/compat.h
|
||||
+++ b/arch/sparc/include/asm/compat.h
|
||||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
|
||||
index 306160e..1d9cd27 100644
|
||||
--- a/arch/x86/include/asm/compat.h
|
||||
+++ b/arch/x86/include/asm/compat.h
|
||||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
diff --git a/include/linux/compat.h b/include/linux/compat.h
|
||||
index 9ddc878..5778b55 100644
|
||||
--- a/include/linux/compat.h
|
||||
+++ b/include/linux/compat.h
|
||||
@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type,
|
||||
const struct compat_iovec __user *uvector, unsigned long nr_segs,
|
||||
unsigned long fast_segs, struct iovec *fast_pointer,
|
||||
struct iovec **ret_pointer);
|
||||
+
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
diff --git a/kernel/compat.c b/kernel/compat.c
|
||||
index e167efc..c9e2ec0 100644
|
||||
--- a/kernel/compat.c
|
||||
+++ b/kernel/compat.c
|
||||
@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: [PATCH] x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 files changed, 7 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index 84e3a4e..518bb99 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-775
@@ -1,775 +0,0 @@
|
||||
From 5d8081e87e00f23132f5d014ad83b105e62f598c Mon Sep 17 00:00:00 2001
|
||||
From: Mitch Harder <mitch.harder@sabayonlinux.org>
|
||||
Date: Sun, 21 Nov 2010 11:10:47 -0600
|
||||
Subject: [v4] sched: automated per session task groups
|
||||
|
||||
On Tue, 2010-11-16 at 18:28 +0100, Ingo Molnar wrote:
|
||||
|
||||
> Mike,
|
||||
>
|
||||
> Mind sending a new patch with a separate v2 announcement in a new thread, once you
|
||||
> have something i could apply to the scheduler tree (for a v2.6.38 merge)?
|
||||
|
||||
Changes since last:
|
||||
- switch to per session vs tty
|
||||
- make autogroups visible in /proc/sched_debug
|
||||
- make autogroups visible in /proc/<pid>/autogroup
|
||||
- add nice level bandwidth tweakability to /proc/<pid>/autogroup
|
||||
|
||||
Modulo "kill it" debate outcome...
|
||||
|
||||
A recurring complaint from CFS users is that parallel kbuild has a negative
|
||||
impact on desktop interactivity. This patch implements an idea from Linus,
|
||||
to automatically create task groups. This patch only per session autogroups,
|
||||
but leaves the way open for enhancement.
|
||||
|
||||
Implementation: each task's signal struct contains an inherited pointer to a
|
||||
refcounted autogroup struct containing a task group pointer, the default for
|
||||
all tasks pointing to the init_task_group. When a task calls setsid(), the
|
||||
process wide reference to the default group is dropped, a new task group is
|
||||
created, and the process is moved into the new task group. Children thereafter
|
||||
inherit this task group, and increase it's refcount. On exit, a reference to the
|
||||
current task group is dropped when the last reference to each signal struct is
|
||||
dropped. The task group is destroyed when the last signal struct referencing
|
||||
it is freed. At runqueue selection time, IFF a task has no cgroup assignment,
|
||||
it's current autogroup is used.
|
||||
|
||||
Autogroup bandwidth is controllable via setting it's nice level through the
|
||||
proc filesystem. cat /proc/<pid>/autogroup displays the task's group and
|
||||
the group's nice level. echo <nice level> > /proc/<pid>/autogroup sets the
|
||||
task group's shares to the weight of nice <level> task. Setting nice level
|
||||
is rate limited for !admin users due to the abuse risk of task group locking.
|
||||
|
||||
The feature is enabled from boot by default if CONFIG_SCHED_AUTOGROUP is
|
||||
selected, but can be disabled via the boot option noautogroup, and can be
|
||||
also be turned on/off on the fly via..
|
||||
echo [01] > /proc/sys/kernel/sched_autogroup_enabled.
|
||||
..which will automatically move tasks to/from the root task group.
|
||||
|
||||
Signed-off-by: Mike Galbraith <efault@gmx.de>
|
||||
---
|
||||
Documentation/kernel-parameters.txt | 2 +
|
||||
fs/proc/base.c | 79 +++++++++++
|
||||
include/linux/sched.h | 23 ++++
|
||||
init/Kconfig | 12 ++
|
||||
kernel/fork.c | 5 +-
|
||||
kernel/sched.c | 13 ++-
|
||||
kernel/sched_autogroup.c | 243 +++++++++++++++++++++++++++++++++++
|
||||
kernel/sched_autogroup.h | 23 ++++
|
||||
kernel/sched_debug.c | 29 ++--
|
||||
kernel/sys.c | 4 +-
|
||||
kernel/sysctl.c | 11 ++
|
||||
11 files changed, 426 insertions(+), 18 deletions(-)
|
||||
create mode 100644 kernel/sched_autogroup.c
|
||||
create mode 100644 kernel/sched_autogroup.h
|
||||
|
||||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
|
||||
index 8dd7248..1e02f1f 100644
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -1608,10 +1608,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
noalign [KNL,ARM]
|
||||
|
||||
noapic [SMP,APIC] Tells the kernel to not make use of any
|
||||
IOAPICs that may be present in the system.
|
||||
|
||||
+ noautogroup Disable scheduler automatic task group creation.
|
||||
+
|
||||
nobats [PPC] Do not use BATs for mapping kernel lowmem
|
||||
on "Classic" PPC cores.
|
||||
|
||||
nocache [ARM]
|
||||
|
||||
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
||||
index 8e4adda..302d94f 100644
|
||||
--- a/fs/proc/base.c
|
||||
+++ b/fs/proc/base.c
|
||||
@@ -1357,10 +1357,86 @@ static const struct file_operations proc_pid_sched_operations = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+/*
|
||||
+ * Print out autogroup related information:
|
||||
+ */
|
||||
+static int sched_autogroup_show(struct seq_file *m, void *v)
|
||||
+{
|
||||
+ struct inode *inode = m->private;
|
||||
+ struct task_struct *p;
|
||||
+
|
||||
+ p = get_proc_task(inode);
|
||||
+ if (!p)
|
||||
+ return -ESRCH;
|
||||
+ proc_sched_autogroup_show_task(p, m);
|
||||
+
|
||||
+ put_task_struct(p);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t
|
||||
+sched_autogroup_write(struct file *file, const char __user *buf,
|
||||
+ size_t count, loff_t *offset)
|
||||
+{
|
||||
+ struct inode *inode = file->f_path.dentry->d_inode;
|
||||
+ struct task_struct *p;
|
||||
+ char buffer[PROC_NUMBUF];
|
||||
+ long nice;
|
||||
+ int err;
|
||||
+
|
||||
+ memset(buffer, 0, sizeof(buffer));
|
||||
+ if (count > sizeof(buffer) - 1)
|
||||
+ count = sizeof(buffer) - 1;
|
||||
+ if (copy_from_user(buffer, buf, count))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ err = strict_strtol(strstrip(buffer), 0, &nice);
|
||||
+ if (err)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ p = get_proc_task(inode);
|
||||
+ if (!p)
|
||||
+ return -ESRCH;
|
||||
+
|
||||
+ err = nice;
|
||||
+ err = proc_sched_autogroup_set_nice(p, &err);
|
||||
+ if (err)
|
||||
+ count = err;
|
||||
+
|
||||
+ put_task_struct(p);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int sched_autogroup_open(struct inode *inode, struct file *filp)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = single_open(filp, sched_autogroup_show, NULL);
|
||||
+ if (!ret) {
|
||||
+ struct seq_file *m = filp->private_data;
|
||||
+
|
||||
+ m->private = inode;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations proc_pid_sched_autogroup_operations = {
|
||||
+ .open = sched_autogroup_open,
|
||||
+ .read = seq_read,
|
||||
+ .write = sched_autogroup_write,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = single_release,
|
||||
+};
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
+
|
||||
static ssize_t comm_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *offset)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct task_struct *p;
|
||||
@@ -2677,10 +2753,13 @@ static const struct pid_entry tgid_base_stuff[] = {
|
||||
ONE("personality", S_IRUSR, proc_pid_personality),
|
||||
INF("limits", S_IRUGO, proc_pid_limits),
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
|
||||
#endif
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
|
||||
+#endif
|
||||
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
|
||||
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
|
||||
INF("syscall", S_IRUSR, proc_pid_syscall),
|
||||
#endif
|
||||
INF("cmdline", S_IRUGO, proc_pid_cmdline),
|
||||
diff --git a/include/linux/sched.h b/include/linux/sched.h
|
||||
index 1e2a6db..2c94373 100644
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -504,10 +504,12 @@ struct thread_group_cputimer {
|
||||
struct task_cputime cputime;
|
||||
int running;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
+struct autogroup;
|
||||
+
|
||||
/*
|
||||
* NOTE! "signal_struct" does not have it's own
|
||||
* locking, because a shared signal_struct always
|
||||
* implies a shared sighand_struct, so locking
|
||||
* sighand_struct is always a proper superset of
|
||||
@@ -571,10 +573,13 @@ struct signal_struct {
|
||||
/* boolean value for session group leader */
|
||||
int leader;
|
||||
|
||||
struct tty_struct *tty; /* NULL if no tty */
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ struct autogroup *autogroup;
|
||||
+#endif
|
||||
/*
|
||||
* Cumulative resource counters for dead threads in the group,
|
||||
* and for reaped dead child processes forked by this group.
|
||||
* Live threads maintain their own counters and add to these
|
||||
* in __exit_signal, except for the group leader.
|
||||
@@ -1898,10 +1903,28 @@ int sched_rt_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
|
||||
extern unsigned int sysctl_sched_compat_yield;
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+extern unsigned int sysctl_sched_autogroup_enabled;
|
||||
+
|
||||
+extern void sched_autogroup_create_attach(struct task_struct *p);
|
||||
+extern void sched_autogroup_detach(struct task_struct *p);
|
||||
+extern void sched_autogroup_fork(struct signal_struct *sig);
|
||||
+extern void sched_autogroup_exit(struct signal_struct *sig);
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+extern void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m);
|
||||
+extern int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice);
|
||||
+#endif
|
||||
+#else
|
||||
+static inline void sched_autogroup_create_attach(struct task_struct *p) { }
|
||||
+static inline void sched_autogroup_detach(struct task_struct *p) { }
|
||||
+static inline void sched_autogroup_fork(struct signal_struct *sig) { }
|
||||
+static inline void sched_autogroup_exit(struct signal_struct *sig) { }
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_RT_MUTEXES
|
||||
extern int rt_mutex_getprio(struct task_struct *p);
|
||||
extern void rt_mutex_setprio(struct task_struct *p, int prio);
|
||||
extern void rt_mutex_adjust_pi(struct task_struct *p);
|
||||
#else
|
||||
diff --git a/init/Kconfig b/init/Kconfig
|
||||
index 2de5b1c..666fc7e 100644
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -650,10 +650,22 @@ config DEBUG_BLK_CGROUP
|
||||
Enable some debugging help. Currently it exports additional stat
|
||||
files in a cgroup which can be useful for debugging.
|
||||
|
||||
endif # CGROUPS
|
||||
|
||||
+config SCHED_AUTOGROUP
|
||||
+ bool "Automatic process group scheduling"
|
||||
+ select CGROUPS
|
||||
+ select CGROUP_SCHED
|
||||
+ select FAIR_GROUP_SCHED
|
||||
+ help
|
||||
+ This option optimizes the scheduler for common desktop workloads by
|
||||
+ automatically creating and populating task groups. This separation
|
||||
+ of workloads isolates aggressive CPU burners (like build jobs) from
|
||||
+ desktop applications. Task group autogeneration is currently based
|
||||
+ upon task session.
|
||||
+
|
||||
config MM_OWNER
|
||||
bool
|
||||
|
||||
config SYSFS_DEPRECATED
|
||||
bool
|
||||
diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
index c445f8c..61f2802 100644
|
||||
--- a/kernel/fork.c
|
||||
+++ b/kernel/fork.c
|
||||
@@ -171,12 +171,14 @@ static inline void free_signal_struct(struct signal_struct *sig)
|
||||
kmem_cache_free(signal_cachep, sig);
|
||||
}
|
||||
|
||||
static inline void put_signal_struct(struct signal_struct *sig)
|
||||
{
|
||||
- if (atomic_dec_and_test(&sig->sigcnt))
|
||||
+ if (atomic_dec_and_test(&sig->sigcnt)) {
|
||||
+ sched_autogroup_exit(sig);
|
||||
free_signal_struct(sig);
|
||||
+ }
|
||||
}
|
||||
|
||||
void __put_task_struct(struct task_struct *tsk)
|
||||
{
|
||||
WARN_ON(!tsk->exit_state);
|
||||
@@ -898,10 +900,11 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
|
||||
task_unlock(current->group_leader);
|
||||
|
||||
posix_cpu_timers_init_group(sig);
|
||||
|
||||
tty_audit_fork(sig);
|
||||
+ sched_autogroup_fork(sig);
|
||||
|
||||
sig->oom_adj = current->signal->oom_adj;
|
||||
sig->oom_score_adj = current->signal->oom_score_adj;
|
||||
|
||||
return 0;
|
||||
diff --git a/kernel/sched.c b/kernel/sched.c
|
||||
index dc85ceb..795e0ec 100644
|
||||
--- a/kernel/sched.c
|
||||
+++ b/kernel/sched.c
|
||||
@@ -76,10 +76,11 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
#include "sched_cpupri.h"
|
||||
#include "workqueue_sched.h"
|
||||
+#include "sched_autogroup.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/sched.h>
|
||||
|
||||
/*
|
||||
@@ -266,10 +267,14 @@ struct task_group {
|
||||
struct list_head list;
|
||||
|
||||
struct task_group *parent;
|
||||
struct list_head siblings;
|
||||
struct list_head children;
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ struct autogroup *autogroup;
|
||||
+#endif
|
||||
};
|
||||
|
||||
#define root_task_group init_task_group
|
||||
|
||||
/* task_group_lock serializes add/remove of task groups and also changes to
|
||||
@@ -610,15 +615,18 @@ static inline int cpu_of(struct rq *rq)
|
||||
* holds that lock for each task it moves into the cgroup. Therefore
|
||||
* by holding that lock, we pin the task to the current cgroup.
|
||||
*/
|
||||
static inline struct task_group *task_group(struct task_struct *p)
|
||||
{
|
||||
+ struct task_group *tg;
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
|
||||
lockdep_is_held(&task_rq(p)->lock));
|
||||
- return container_of(css, struct task_group, css);
|
||||
+ tg = container_of(css, struct task_group, css);
|
||||
+
|
||||
+ return autogroup_task_group(p, tg);
|
||||
}
|
||||
|
||||
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
|
||||
static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
|
||||
{
|
||||
@@ -1918,10 +1926,11 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
|
||||
}
|
||||
|
||||
#include "sched_idletask.c"
|
||||
#include "sched_fair.c"
|
||||
#include "sched_rt.c"
|
||||
+#include "sched_autogroup.c"
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
# include "sched_debug.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -7747,11 +7756,11 @@ void __init sched_init(void)
|
||||
#endif /* CONFIG_RT_GROUP_SCHED */
|
||||
|
||||
#ifdef CONFIG_CGROUP_SCHED
|
||||
list_add(&init_task_group.list, &task_groups);
|
||||
INIT_LIST_HEAD(&init_task_group.children);
|
||||
-
|
||||
+ autogroup_init(&init_task);
|
||||
#endif /* CONFIG_CGROUP_SCHED */
|
||||
|
||||
#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
|
||||
update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
|
||||
__alignof__(unsigned long));
|
||||
diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c
|
||||
new file mode 100644
|
||||
index 0000000..2266b02
|
||||
--- /dev/null
|
||||
+++ b/kernel/sched_autogroup.c
|
||||
@@ -0,0 +1,243 @@
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+
|
||||
+#include <linux/proc_fs.h>
|
||||
+#include <linux/seq_file.h>
|
||||
+#include <linux/kallsyms.h>
|
||||
+#include <linux/utsname.h>
|
||||
+
|
||||
+unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
|
||||
+
|
||||
+struct autogroup {
|
||||
+ struct task_group *tg;
|
||||
+ struct kref kref;
|
||||
+ struct rw_semaphore lock;
|
||||
+ unsigned long id;
|
||||
+ int nice;
|
||||
+};
|
||||
+
|
||||
+static struct autogroup autogroup_default;
|
||||
+static atomic_t autogroup_seq_nr;
|
||||
+
|
||||
+static void autogroup_init(struct task_struct *init_task)
|
||||
+{
|
||||
+ autogroup_default.tg = &init_task_group;
|
||||
+ init_task_group.autogroup = &autogroup_default;
|
||||
+ kref_init(&autogroup_default.kref);
|
||||
+ init_rwsem(&autogroup_default.lock);
|
||||
+ init_task->signal->autogroup = &autogroup_default;
|
||||
+}
|
||||
+
|
||||
+static inline void autogroup_destroy(struct kref *kref)
|
||||
+{
|
||||
+ struct autogroup *ag = container_of(kref, struct autogroup, kref);
|
||||
+ struct task_group *tg = ag->tg;
|
||||
+
|
||||
+ kfree(ag);
|
||||
+ sched_destroy_group(tg);
|
||||
+}
|
||||
+
|
||||
+static inline void autogroup_kref_put(struct autogroup *ag)
|
||||
+{
|
||||
+ kref_put(&ag->kref, autogroup_destroy);
|
||||
+}
|
||||
+
|
||||
+static inline struct autogroup *autogroup_kref_get(struct autogroup *ag)
|
||||
+{
|
||||
+ kref_get(&ag->kref);
|
||||
+ return ag;
|
||||
+}
|
||||
+
|
||||
+static inline struct autogroup *autogroup_create(void)
|
||||
+{
|
||||
+ struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
|
||||
+
|
||||
+ if (!ag)
|
||||
+ goto out_fail;
|
||||
+
|
||||
+ ag->tg = sched_create_group(&init_task_group);
|
||||
+
|
||||
+ if (IS_ERR(ag->tg))
|
||||
+ goto out_fail;
|
||||
+
|
||||
+ ag->tg->autogroup = ag;
|
||||
+ kref_init(&ag->kref);
|
||||
+ init_rwsem(&ag->lock);
|
||||
+ ag->id = atomic_inc_return(&autogroup_seq_nr);
|
||||
+
|
||||
+ return ag;
|
||||
+
|
||||
+out_fail:
|
||||
+ if (ag) {
|
||||
+ kfree(ag);
|
||||
+ WARN_ON(1);
|
||||
+ } else
|
||||
+ WARN_ON(1);
|
||||
+
|
||||
+ return autogroup_kref_get(&autogroup_default);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+task_wants_autogroup(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ if (tg != &root_task_group)
|
||||
+ return false;
|
||||
+
|
||||
+ if (p->sched_class != &fair_sched_class)
|
||||
+ return false;
|
||||
+
|
||||
+ /*
|
||||
+ * We can only assume the task group can't go away on us if
|
||||
+ * autogroup_move_group() can see us on ->thread_group list.
|
||||
+ */
|
||||
+ if (p->flags & PF_EXITING)
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
|
||||
+
|
||||
+ if (enabled && task_wants_autogroup(p, tg))
|
||||
+ return p->signal->autogroup->tg;
|
||||
+
|
||||
+ return tg;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+autogroup_move_group(struct task_struct *p, struct autogroup *ag)
|
||||
+{
|
||||
+ struct autogroup *prev;
|
||||
+ struct task_struct *t;
|
||||
+
|
||||
+ spin_lock(&p->sighand->siglock);
|
||||
+
|
||||
+ prev = p->signal->autogroup;
|
||||
+ if (prev == ag) {
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ p->signal->autogroup = autogroup_kref_get(ag);
|
||||
+ t = p;
|
||||
+
|
||||
+ do {
|
||||
+ sched_move_task(p);
|
||||
+ } while_each_thread(p, t);
|
||||
+
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+
|
||||
+ autogroup_kref_put(prev);
|
||||
+}
|
||||
+
|
||||
+/* Allocates GFP_KERNEL, cannot be called under any spinlock */
|
||||
+void sched_autogroup_create_attach(struct task_struct *p)
|
||||
+{
|
||||
+ struct autogroup *ag = autogroup_create();
|
||||
+
|
||||
+ autogroup_move_group(p, ag);
|
||||
+ /* drop extra refrence added by autogroup_create() */
|
||||
+ autogroup_kref_put(ag);
|
||||
+}
|
||||
+EXPORT_SYMBOL(sched_autogroup_create_attach);
|
||||
+
|
||||
+/* Cannot be called under siglock. Currently has no users */
|
||||
+void sched_autogroup_detach(struct task_struct *p)
|
||||
+{
|
||||
+ autogroup_move_group(p, &autogroup_default);
|
||||
+}
|
||||
+EXPORT_SYMBOL(sched_autogroup_detach);
|
||||
+
|
||||
+void sched_autogroup_fork(struct signal_struct *sig)
|
||||
+{
|
||||
+ struct sighand_struct *sighand = current->sighand;
|
||||
+
|
||||
+ spin_lock(&sighand->siglock);
|
||||
+ sig->autogroup = autogroup_kref_get(current->signal->autogroup);
|
||||
+ spin_unlock(&sighand->siglock);
|
||||
+}
|
||||
+
|
||||
+void sched_autogroup_exit(struct signal_struct *sig)
|
||||
+{
|
||||
+ autogroup_kref_put(sig->autogroup);
|
||||
+}
|
||||
+
|
||||
+static int __init setup_autogroup(char *str)
|
||||
+{
|
||||
+ sysctl_sched_autogroup_enabled = 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+__setup("noautogroup", setup_autogroup);
|
||||
+
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+
|
||||
+static inline struct autogroup *autogroup_get(struct task_struct *p)
|
||||
+{
|
||||
+ struct autogroup *ag;
|
||||
+
|
||||
+ /* task may be moved after we unlock.. tough */
|
||||
+ spin_lock(&p->sighand->siglock);
|
||||
+ ag = autogroup_kref_get(p->signal->autogroup);
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+
|
||||
+ return ag;
|
||||
+}
|
||||
+
|
||||
+int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice)
|
||||
+{
|
||||
+ static unsigned long next = INITIAL_JIFFIES;
|
||||
+ struct autogroup *ag;
|
||||
+ int err;
|
||||
+
|
||||
+ if (*nice < -20 || *nice > 19)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = security_task_setnice(current, *nice);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (*nice < 0 && !can_nice(current, *nice))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ /* this is a heavy operation taking global locks.. */
|
||||
+ if (!capable(CAP_SYS_ADMIN) && time_before(jiffies, next))
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
+ next = HZ / 10 + jiffies;;
|
||||
+ ag = autogroup_get(p);
|
||||
+
|
||||
+ down_write(&ag->lock);
|
||||
+ err = sched_group_set_shares(ag->tg, prio_to_weight[*nice + 20]);
|
||||
+ if (!err)
|
||||
+ ag->nice = *nice;
|
||||
+ up_write(&ag->lock);
|
||||
+
|
||||
+ autogroup_kref_put(ag);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
|
||||
+{
|
||||
+ struct autogroup *ag = autogroup_get(p);
|
||||
+
|
||||
+ down_read(&ag->lock);
|
||||
+ seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice);
|
||||
+ up_read(&ag->lock);
|
||||
+
|
||||
+ autogroup_kref_put(ag);
|
||||
+}
|
||||
+#endif /* CONFIG_PROC_FS */
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_DEBUG
|
||||
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ return snprintf(buf, buflen, "%s-%ld", "/autogroup", tg->autogroup->id);
|
||||
+}
|
||||
+#endif /* CONFIG_SCHED_DEBUG */
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
|
||||
new file mode 100644
|
||||
index 0000000..40deaef
|
||||
--- /dev/null
|
||||
+++ b/kernel/sched_autogroup.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg);
|
||||
+
|
||||
+#else /* !CONFIG_SCHED_AUTOGROUP */
|
||||
+
|
||||
+static inline void autogroup_init(struct task_struct *init_task) { }
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ return tg;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_DEBUG
|
||||
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
|
||||
index 2e1b0d1..94bcabe 100644
|
||||
--- a/kernel/sched_debug.c
|
||||
+++ b/kernel/sched_debug.c
|
||||
@@ -85,10 +85,24 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu,
|
||||
#undef PN
|
||||
#undef P
|
||||
}
|
||||
#endif
|
||||
|
||||
+#if defined(CONFIG_CGROUP_SCHED) && \
|
||||
+ (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED))
|
||||
+static void task_group_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ /* may be NULL if the underlying cgroup isn't fully-created yet */
|
||||
+ if (!tg->css.cgroup) {
|
||||
+ if (!autogroup_path(tg, buf, buflen))
|
||||
+ buf[0] = '\0';
|
||||
+ return;
|
||||
+ }
|
||||
+ cgroup_path(tg->css.cgroup, buf, buflen);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void
|
||||
print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
|
||||
{
|
||||
if (rq->curr == p)
|
||||
SEQ_printf(m, "R");
|
||||
@@ -113,11 +127,11 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
|
||||
#ifdef CONFIG_CGROUP_SCHED
|
||||
{
|
||||
char path[64];
|
||||
|
||||
rcu_read_lock();
|
||||
- cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
|
||||
+ task_group_path(task_group(p), path, sizeof(path));
|
||||
rcu_read_unlock();
|
||||
SEQ_printf(m, " %s", path);
|
||||
}
|
||||
#endif
|
||||
SEQ_printf(m, "\n");
|
||||
@@ -145,23 +159,10 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
|
||||
} while_each_thread(g, p);
|
||||
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
}
|
||||
|
||||
-#if defined(CONFIG_CGROUP_SCHED) && \
|
||||
- (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED))
|
||||
-static void task_group_path(struct task_group *tg, char *buf, int buflen)
|
||||
-{
|
||||
- /* may be NULL if the underlying cgroup isn't fully-created yet */
|
||||
- if (!tg->css.cgroup) {
|
||||
- buf[0] = '\0';
|
||||
- return;
|
||||
- }
|
||||
- cgroup_path(tg->css.cgroup, buf, buflen);
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
|
||||
{
|
||||
s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1,
|
||||
spread, rq0_min_vruntime, spread0;
|
||||
struct rq *rq = cpu_rq(cpu);
|
||||
diff --git a/kernel/sys.c b/kernel/sys.c
|
||||
index 7f5a0cd..2745dcd 100644
|
||||
--- a/kernel/sys.c
|
||||
+++ b/kernel/sys.c
|
||||
@@ -1078,12 +1078,14 @@ SYSCALL_DEFINE0(setsid)
|
||||
proc_clear_tty(group_leader);
|
||||
|
||||
err = session;
|
||||
out:
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
- if (err > 0)
|
||||
+ if (err > 0) {
|
||||
proc_sid_connector(group_leader);
|
||||
+ sched_autogroup_create_attach(group_leader);
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
DECLARE_RWSEM(uts_sem);
|
||||
|
||||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
||||
index 3a45c22..165eb9b 100644
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -382,10 +382,21 @@ static struct ctl_table kern_table[] = {
|
||||
.data = &sysctl_sched_compat_yield,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ {
|
||||
+ .procname = "sched_autogroup_enabled",
|
||||
+ .data = &sysctl_sched_autogroup_enabled,
|
||||
+ .maxlen = sizeof(unsigned int),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_dointvec,
|
||||
+ .extra1 = &zero,
|
||||
+ .extra2 = &one,
|
||||
+ },
|
||||
+#endif
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
{
|
||||
.procname = "prove_locking",
|
||||
.data = &prove_locking,
|
||||
.maxlen = sizeof(int),
|
||||
--
|
||||
1.7.2.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="3"
|
||||
K_KERNEL_PATCH_VER=""
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_KERNEL_PATCH_HOTFIXES="${FILESDIR}/hotfixes/2.6.36/v4-sched-automated-per-session-task-groups.patch"
|
||||
inherit sabayon-kernel
|
||||
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="6"
|
||||
K_KERNEL_PATCH_VER="3"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
# K_KERNEL_PATCH_HOTFIXES="${FILESDIR}/hotfixes/2.6.36/v4-sched-automated-per-session-task-groups.patch"
|
||||
inherit sabayon-kernel
|
||||
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,11 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="1"
|
||||
K_KERNEL_PATCH_VER="6"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
inherit sabayon-kernel
|
||||
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,10 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_REQUIRED_LINUX_FIRMWARE_VER="20110604"
|
||||
inherit sabayon-kernel
|
||||
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel image"
|
||||
RESTRICT="mirror"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
# Copyright 2004-2009 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="12"
|
||||
K_KERNEL_PATCH_VER="10"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_SABKERNEL_LONGTERM="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="10"
|
||||
K_KERNEL_PATCH_VER="14"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_SABKERNEL_LONGTERM="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,11 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="4"
|
||||
K_KERNEL_PATCH_VER="4"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,11 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="7"
|
||||
K_KERNEL_PATCH_VER="6"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,11 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABPATCHES_VER="1"
|
||||
K_KERNEL_PATCH_VER="8"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
@@ -1,10 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_KERNEL_SOURCES_PKG="sys-kernel/server-sources-${PVR}"
|
||||
K_REQUIRED_LINUX_FIRMWARE_VER="20110604"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel image"
|
||||
RESTRICT="mirror"
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
--- linux-2.6.33-sabayon.orig/arch/ia64/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/ia64/include/asm/compat.h
|
||||
@@ -198,7 +198,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
--- linux-2.6.33-sabayon.orig/arch/mips/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/mips/include/asm/compat.h
|
||||
@@ -144,7 +144,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
--- linux-2.6.33-sabayon.orig/arch/parisc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/parisc/include/asm/compat.h
|
||||
@@ -146,7 +146,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
--- linux-2.6.33-sabayon.orig/arch/powerpc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/powerpc/include/asm/compat.h
|
||||
@@ -133,7 +133,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
--- linux-2.6.33-sabayon.orig/arch/s390/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/s390/include/asm/compat.h
|
||||
@@ -180,7 +180,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
--- linux-2.6.33-sabayon.orig/arch/sparc/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/sparc/include/asm/compat.h
|
||||
@@ -166,7 +166,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
--- linux-2.6.33-sabayon.orig/arch/x86/include/asm/compat.h
|
||||
+++ linux-2.6.33-sabayon/arch/x86/include/asm/compat.h
|
||||
@@ -204,7 +204,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
--- linux-2.6.33-sabayon.orig/include/linux/compat.h
|
||||
+++ linux-2.6.33-sabayon/include/linux/compat.h
|
||||
@@ -353,5 +353,7 @@ asmlinkage long compat_sys_newfstatat(un
|
||||
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
|
||||
int flags, int mode);
|
||||
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
--- linux-2.6.33-sabayon.orig/kernel/compat.c
|
||||
+++ linux-2.6.33-sabayon/kernel/compat.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/security.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/migrate.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/times.h>
|
||||
#include <linux/ptrace.h>
|
||||
@@ -1139,3 +1140,24 @@ compat_sys_sysinfo(struct compat_sysinfo
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
|
||||
commit eefdca043e8391dcd719711716492063030b55ac upstream.
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
|
||||
commit 36d001c70d8a0144ac1d038f6876c484849a74de upstream.
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
--- linux-2.6.34-sabayon.orig/arch/ia64/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/ia64/include/asm/compat.h 2010-09-18 17:09:30.728304722 +0200
|
||||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
--- linux-2.6.34-sabayon.orig/arch/mips/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/mips/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
--- linux-2.6.34-sabayon.orig/arch/parisc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/parisc/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
--- linux-2.6.34-sabayon.orig/arch/powerpc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/powerpc/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
--- linux-2.6.34-sabayon.orig/arch/s390/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/s390/include/asm/compat.h 2010-09-18 17:09:30.728822831 +0200
|
||||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
--- linux-2.6.34-sabayon.orig/arch/sparc/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/sparc/include/asm/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
--- linux-2.6.34-sabayon.orig/arch/x86/include/asm/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/arch/x86/include/asm/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compa
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
--- linux-2.6.34-sabayon.orig/include/linux/compat.h 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/include/linux/compat.h 2010-09-18 17:09:30.729822459 +0200
|
||||
@@ -356,5 +356,7 @@ asmlinkage long compat_sys_newfstatat(un
|
||||
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
|
||||
int flags, int mode);
|
||||
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
--- linux-2.6.34-sabayon.orig/kernel/compat.c 2010-05-16 23:17:36.000000000 +0200
|
||||
+++ linux-2.6.34-sabayon/kernel/compat.c 2010-09-18 17:09:58.574836565 +0200
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/times.h>
|
||||
#include <linux/ptrace.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
@@ -1140,3 +1141,24 @@ compat_sys_sysinfo(struct compat_sysinfo
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
|
||||
commit eefdca043e8391dcd719711716492063030b55ac upstream.
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
|
||||
commit 36d001c70d8a0144ac1d038f6876c484849a74de upstream.
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
From 36d001c70d8a0144ac1d038f6876c484849a74de Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 14 Sep 2010 12:42:41 -0700
|
||||
Subject: [PATCH] x86-64, compat: Test %rax for the syscall number, not %eax
|
||||
|
||||
On 64 bits, we always, by necessity, jump through the system call
|
||||
table via %rax. For 32-bit system calls, in theory the system call
|
||||
number is stored in %eax, and the code was testing %eax for a valid
|
||||
system call number. At one point we loaded the stored value back from
|
||||
the stack to enforce zero-extension, but that was removed in checkin
|
||||
d4d67150165df8bf1cc05e532f6efca96f907cab. An actual 32-bit process
|
||||
will not be able to introduce a non-zero-extended number, but it can
|
||||
happen via ptrace.
|
||||
|
||||
Instead of re-introducing the zero-extension, test what we are
|
||||
actually going to use, i.e. %rax. This only adds a handful of REX
|
||||
prefixes to the code.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Cc: <stable@kernel.org>
|
||||
Cc: Roland McGrath <roland@redhat.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 14 +++++++-------
|
||||
1 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index b86feab..84e3a4e 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -153,7 +153,7 @@ ENTRY(ia32_sysenter_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz sysenter_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
sysenter_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -195,7 +195,7 @@ sysexit_from_sys_call:
|
||||
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
|
||||
call audit_syscall_entry
|
||||
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
movl %ebx,%edi /* reload 1st syscall arg */
|
||||
movl RCX-ARGOFFSET(%rsp),%esi /* reload 2nd syscall arg */
|
||||
@@ -248,7 +248,7 @@ sysenter_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
|
||||
jmp sysenter_do_call
|
||||
CFI_ENDPROC
|
||||
@@ -314,7 +314,7 @@ ENTRY(ia32_cstar_target)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
CFI_REMEMBER_STATE
|
||||
jnz cstar_tracesys
|
||||
- cmpl $IA32_NR_syscalls-1,%eax
|
||||
+ cmpq $IA32_NR_syscalls-1,%rax
|
||||
ja ia32_badsys
|
||||
cstar_do_call:
|
||||
IA32_ARG_FIXUP 1
|
||||
@@ -367,7 +367,7 @@ cstar_tracesys:
|
||||
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
xchgl %ebp,%r9d
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
|
||||
jmp cstar_do_call
|
||||
END(ia32_cstar_target)
|
||||
@@ -425,7 +425,7 @@ ENTRY(ia32_syscall)
|
||||
orl $TS_COMPAT,TI_status(%r10)
|
||||
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10)
|
||||
jnz ia32_tracesys
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja ia32_badsys
|
||||
ia32_do_call:
|
||||
IA32_ARG_FIXUP
|
||||
@@ -444,7 +444,7 @@ ia32_tracesys:
|
||||
call syscall_trace_enter
|
||||
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
|
||||
RESTORE_REST
|
||||
- cmpl $(IA32_NR_syscalls-1),%eax
|
||||
+ cmpq $(IA32_NR_syscalls-1),%rax
|
||||
ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
|
||||
jmp ia32_do_call
|
||||
END(ia32_syscall)
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-190
@@ -1,190 +0,0 @@
|
||||
From c41d68a513c71e35a14f66d71782d27a79a81ea6 Mon Sep 17 00:00:00 2001
|
||||
From: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Date: Tue, 7 Sep 2010 16:16:18 -0700
|
||||
Subject: [PATCH] compat: Make compat_alloc_user_space() incorporate the access_ok()
|
||||
|
||||
compat_alloc_user_space() expects the caller to independently call
|
||||
access_ok() to verify the returned area. A missing call could
|
||||
introduce problems on some architectures.
|
||||
|
||||
This patch incorporates the access_ok() check into
|
||||
compat_alloc_user_space() and also adds a sanity check on the length.
|
||||
The existing compat_alloc_user_space() implementations are renamed
|
||||
arch_compat_alloc_user_space() and are used as part of the
|
||||
implementation of the new global function.
|
||||
|
||||
This patch assumes NULL will cause __get_user()/__put_user() to either
|
||||
fail or access userspace on all architectures. This should be
|
||||
followed by checking the return value of compat_access_user_space()
|
||||
for NULL in the callers, at which time the access_ok() in the callers
|
||||
can also be removed.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
|
||||
Acked-by: David S. Miller <davem@davemloft.net>
|
||||
Acked-by: Ingo Molnar <mingo@elte.hu>
|
||||
Acked-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Acked-by: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Arnd Bergmann <arnd@arndb.de>
|
||||
Cc: Fenghua Yu <fenghua.yu@intel.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
|
||||
Cc: Helge Deller <deller@gmx.de>
|
||||
Cc: James Bottomley <jejb@parisc-linux.org>
|
||||
Cc: Kyle McMartin <kyle@mcmartin.ca>
|
||||
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
Cc: Paul Mackerras <paulus@samba.org>
|
||||
Cc: Ralf Baechle <ralf@linux-mips.org>
|
||||
Cc: <stable@kernel.org>
|
||||
---
|
||||
arch/ia64/include/asm/compat.h | 2 +-
|
||||
arch/mips/include/asm/compat.h | 2 +-
|
||||
arch/parisc/include/asm/compat.h | 2 +-
|
||||
arch/powerpc/include/asm/compat.h | 2 +-
|
||||
arch/s390/include/asm/compat.h | 2 +-
|
||||
arch/sparc/include/asm/compat.h | 2 +-
|
||||
arch/tile/include/asm/compat.h | 2 +-
|
||||
arch/x86/include/asm/compat.h | 2 +-
|
||||
include/linux/compat.h | 3 +++
|
||||
kernel/compat.c | 21 +++++++++++++++++++++
|
||||
10 files changed, 32 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/ia64/include/asm/compat.h b/arch/ia64/include/asm/compat.h
|
||||
index f90edc8..9301a28 100644
|
||||
--- a/arch/ia64/include/asm/compat.h
|
||||
+++ b/arch/ia64/include/asm/compat.h
|
||||
@@ -199,7 +199,7 @@ ptr_to_compat(void __user *uptr)
|
||||
}
|
||||
|
||||
static __inline__ void __user *
|
||||
-compat_alloc_user_space (long len)
|
||||
+arch_compat_alloc_user_space (long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
|
||||
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
|
||||
index 613f691..dbc5106 100644
|
||||
--- a/arch/mips/include/asm/compat.h
|
||||
+++ b/arch/mips/include/asm/compat.h
|
||||
@@ -145,7 +145,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
|
||||
index 02b77ba..efa0b60 100644
|
||||
--- a/arch/parisc/include/asm/compat.h
|
||||
+++ b/arch/parisc/include/asm/compat.h
|
||||
@@ -147,7 +147,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static __inline__ void __user *compat_alloc_user_space(long len)
|
||||
+static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
|
||||
index 396d21a..a11d4ea 100644
|
||||
--- a/arch/powerpc/include/asm/compat.h
|
||||
+++ b/arch/powerpc/include/asm/compat.h
|
||||
@@ -134,7 +134,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
|
||||
index 104f200..a875c2f 100644
|
||||
--- a/arch/s390/include/asm/compat.h
|
||||
+++ b/arch/s390/include/asm/compat.h
|
||||
@@ -181,7 +181,7 @@ static inline int is_compat_task(void)
|
||||
|
||||
#endif
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
|
||||
index 5016f76..6f57325 100644
|
||||
--- a/arch/sparc/include/asm/compat.h
|
||||
+++ b/arch/sparc/include/asm/compat.h
|
||||
@@ -167,7 +167,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
|
||||
index 306160e..1d9cd27 100644
|
||||
--- a/arch/x86/include/asm/compat.h
|
||||
+++ b/arch/x86/include/asm/compat.h
|
||||
@@ -205,7 +205,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
|
||||
return (u32)(unsigned long)uptr;
|
||||
}
|
||||
|
||||
-static inline void __user *compat_alloc_user_space(long len)
|
||||
+static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(current);
|
||||
return (void __user *)regs->sp - len;
|
||||
diff --git a/include/linux/compat.h b/include/linux/compat.h
|
||||
index 9ddc878..5778b55 100644
|
||||
--- a/include/linux/compat.h
|
||||
+++ b/include/linux/compat.h
|
||||
@@ -360,5 +360,8 @@ extern ssize_t compat_rw_copy_check_uvector(int type,
|
||||
const struct compat_iovec __user *uvector, unsigned long nr_segs,
|
||||
unsigned long fast_segs, struct iovec *fast_pointer,
|
||||
struct iovec **ret_pointer);
|
||||
+
|
||||
+extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
+
|
||||
#endif /* CONFIG_COMPAT */
|
||||
#endif /* _LINUX_COMPAT_H */
|
||||
diff --git a/kernel/compat.c b/kernel/compat.c
|
||||
index e167efc..c9e2ec0 100644
|
||||
--- a/kernel/compat.c
|
||||
+++ b/kernel/compat.c
|
||||
@@ -1126,3 +1126,24 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Allocate user-space memory for the duration of a single system call,
|
||||
+ * in order to marshall parameters inside a compat thunk.
|
||||
+ */
|
||||
+void __user *compat_alloc_user_space(unsigned long len)
|
||||
+{
|
||||
+ void __user *ptr;
|
||||
+
|
||||
+ /* If len would occupy more than half of the entire compat space... */
|
||||
+ if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = arch_compat_alloc_user_space(len);
|
||||
+
|
||||
+ if (unlikely(!access_ok(VERIFY_WRITE, ptr, len)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ptr;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From eefdca043e8391dcd719711716492063030b55ac Mon Sep 17 00:00:00 2001
|
||||
From: Roland McGrath <roland@redhat.com>
|
||||
Date: Tue, 14 Sep 2010 12:22:58 -0700
|
||||
Subject: [PATCH] x86-64, compat: Retruncate rax after ia32 syscall entry tracing
|
||||
|
||||
In commit d4d6715, we reopened an old hole for a 64-bit ptracer touching a
|
||||
32-bit tracee in system call entry. A %rax value set via ptrace at the
|
||||
entry tracing stop gets used whole as a 32-bit syscall number, while we
|
||||
only check the low 32 bits for validity.
|
||||
|
||||
Fix it by truncating %rax back to 32 bits after syscall_trace_enter,
|
||||
in addition to testing the full 64 bits as has already been added.
|
||||
|
||||
Reported-by: Ben Hawkes <hawkes@sota.gen.nz>
|
||||
Signed-off-by: Roland McGrath <roland@redhat.com>
|
||||
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 8 +++++++-
|
||||
1 files changed, 7 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index 84e3a4e..518bb99 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -50,7 +50,12 @@
|
||||
/*
|
||||
* Reload arg registers from stack in case ptrace changed them.
|
||||
* We don't reload %eax because syscall_trace_enter() returned
|
||||
- * the value it wants us to use in the table lookup.
|
||||
+ * the %rax value we should see. Instead, we just truncate that
|
||||
+ * value to 32 bits again as we did on entry from user mode.
|
||||
+ * If it's a new value set by user_regset during entry tracing,
|
||||
+ * this matches the normal truncation of the user-mode value.
|
||||
+ * If it's -1 to make us punt the syscall, then (u32)-1 is still
|
||||
+ * an appropriately invalid value.
|
||||
*/
|
||||
.macro LOAD_ARGS32 offset, _r9=0
|
||||
.if \_r9
|
||||
@@ -60,6 +65,7 @@
|
||||
movl \offset+48(%rsp),%edx
|
||||
movl \offset+56(%rsp),%esi
|
||||
movl \offset+64(%rsp),%edi
|
||||
+ movl %eax,%eax /* zero extension */
|
||||
.endm
|
||||
|
||||
.macro CFI_STARTPROC32 simple
|
||||
--
|
||||
1.7.2.3
|
||||
|
||||
-775
@@ -1,775 +0,0 @@
|
||||
From 5d8081e87e00f23132f5d014ad83b105e62f598c Mon Sep 17 00:00:00 2001
|
||||
From: Mitch Harder <mitch.harder@sabayonlinux.org>
|
||||
Date: Sun, 21 Nov 2010 11:10:47 -0600
|
||||
Subject: [v4] sched: automated per session task groups
|
||||
|
||||
On Tue, 2010-11-16 at 18:28 +0100, Ingo Molnar wrote:
|
||||
|
||||
> Mike,
|
||||
>
|
||||
> Mind sending a new patch with a separate v2 announcement in a new thread, once you
|
||||
> have something i could apply to the scheduler tree (for a v2.6.38 merge)?
|
||||
|
||||
Changes since last:
|
||||
- switch to per session vs tty
|
||||
- make autogroups visible in /proc/sched_debug
|
||||
- make autogroups visible in /proc/<pid>/autogroup
|
||||
- add nice level bandwidth tweakability to /proc/<pid>/autogroup
|
||||
|
||||
Modulo "kill it" debate outcome...
|
||||
|
||||
A recurring complaint from CFS users is that parallel kbuild has a negative
|
||||
impact on desktop interactivity. This patch implements an idea from Linus,
|
||||
to automatically create task groups. This patch only per session autogroups,
|
||||
but leaves the way open for enhancement.
|
||||
|
||||
Implementation: each task's signal struct contains an inherited pointer to a
|
||||
refcounted autogroup struct containing a task group pointer, the default for
|
||||
all tasks pointing to the init_task_group. When a task calls setsid(), the
|
||||
process wide reference to the default group is dropped, a new task group is
|
||||
created, and the process is moved into the new task group. Children thereafter
|
||||
inherit this task group, and increase it's refcount. On exit, a reference to the
|
||||
current task group is dropped when the last reference to each signal struct is
|
||||
dropped. The task group is destroyed when the last signal struct referencing
|
||||
it is freed. At runqueue selection time, IFF a task has no cgroup assignment,
|
||||
it's current autogroup is used.
|
||||
|
||||
Autogroup bandwidth is controllable via setting it's nice level through the
|
||||
proc filesystem. cat /proc/<pid>/autogroup displays the task's group and
|
||||
the group's nice level. echo <nice level> > /proc/<pid>/autogroup sets the
|
||||
task group's shares to the weight of nice <level> task. Setting nice level
|
||||
is rate limited for !admin users due to the abuse risk of task group locking.
|
||||
|
||||
The feature is enabled from boot by default if CONFIG_SCHED_AUTOGROUP is
|
||||
selected, but can be disabled via the boot option noautogroup, and can be
|
||||
also be turned on/off on the fly via..
|
||||
echo [01] > /proc/sys/kernel/sched_autogroup_enabled.
|
||||
..which will automatically move tasks to/from the root task group.
|
||||
|
||||
Signed-off-by: Mike Galbraith <efault@gmx.de>
|
||||
---
|
||||
Documentation/kernel-parameters.txt | 2 +
|
||||
fs/proc/base.c | 79 +++++++++++
|
||||
include/linux/sched.h | 23 ++++
|
||||
init/Kconfig | 12 ++
|
||||
kernel/fork.c | 5 +-
|
||||
kernel/sched.c | 13 ++-
|
||||
kernel/sched_autogroup.c | 243 +++++++++++++++++++++++++++++++++++
|
||||
kernel/sched_autogroup.h | 23 ++++
|
||||
kernel/sched_debug.c | 29 ++--
|
||||
kernel/sys.c | 4 +-
|
||||
kernel/sysctl.c | 11 ++
|
||||
11 files changed, 426 insertions(+), 18 deletions(-)
|
||||
create mode 100644 kernel/sched_autogroup.c
|
||||
create mode 100644 kernel/sched_autogroup.h
|
||||
|
||||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
|
||||
index 8dd7248..1e02f1f 100644
|
||||
--- a/Documentation/kernel-parameters.txt
|
||||
+++ b/Documentation/kernel-parameters.txt
|
||||
@@ -1608,10 +1608,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
noalign [KNL,ARM]
|
||||
|
||||
noapic [SMP,APIC] Tells the kernel to not make use of any
|
||||
IOAPICs that may be present in the system.
|
||||
|
||||
+ noautogroup Disable scheduler automatic task group creation.
|
||||
+
|
||||
nobats [PPC] Do not use BATs for mapping kernel lowmem
|
||||
on "Classic" PPC cores.
|
||||
|
||||
nocache [ARM]
|
||||
|
||||
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
||||
index 8e4adda..302d94f 100644
|
||||
--- a/fs/proc/base.c
|
||||
+++ b/fs/proc/base.c
|
||||
@@ -1357,10 +1357,86 @@ static const struct file_operations proc_pid_sched_operations = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+/*
|
||||
+ * Print out autogroup related information:
|
||||
+ */
|
||||
+static int sched_autogroup_show(struct seq_file *m, void *v)
|
||||
+{
|
||||
+ struct inode *inode = m->private;
|
||||
+ struct task_struct *p;
|
||||
+
|
||||
+ p = get_proc_task(inode);
|
||||
+ if (!p)
|
||||
+ return -ESRCH;
|
||||
+ proc_sched_autogroup_show_task(p, m);
|
||||
+
|
||||
+ put_task_struct(p);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static ssize_t
|
||||
+sched_autogroup_write(struct file *file, const char __user *buf,
|
||||
+ size_t count, loff_t *offset)
|
||||
+{
|
||||
+ struct inode *inode = file->f_path.dentry->d_inode;
|
||||
+ struct task_struct *p;
|
||||
+ char buffer[PROC_NUMBUF];
|
||||
+ long nice;
|
||||
+ int err;
|
||||
+
|
||||
+ memset(buffer, 0, sizeof(buffer));
|
||||
+ if (count > sizeof(buffer) - 1)
|
||||
+ count = sizeof(buffer) - 1;
|
||||
+ if (copy_from_user(buffer, buf, count))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ err = strict_strtol(strstrip(buffer), 0, &nice);
|
||||
+ if (err)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ p = get_proc_task(inode);
|
||||
+ if (!p)
|
||||
+ return -ESRCH;
|
||||
+
|
||||
+ err = nice;
|
||||
+ err = proc_sched_autogroup_set_nice(p, &err);
|
||||
+ if (err)
|
||||
+ count = err;
|
||||
+
|
||||
+ put_task_struct(p);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static int sched_autogroup_open(struct inode *inode, struct file *filp)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = single_open(filp, sched_autogroup_show, NULL);
|
||||
+ if (!ret) {
|
||||
+ struct seq_file *m = filp->private_data;
|
||||
+
|
||||
+ m->private = inode;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct file_operations proc_pid_sched_autogroup_operations = {
|
||||
+ .open = sched_autogroup_open,
|
||||
+ .read = seq_read,
|
||||
+ .write = sched_autogroup_write,
|
||||
+ .llseek = seq_lseek,
|
||||
+ .release = single_release,
|
||||
+};
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
+
|
||||
static ssize_t comm_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *offset)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct task_struct *p;
|
||||
@@ -2677,10 +2753,13 @@ static const struct pid_entry tgid_base_stuff[] = {
|
||||
ONE("personality", S_IRUSR, proc_pid_personality),
|
||||
INF("limits", S_IRUGO, proc_pid_limits),
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
|
||||
#endif
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
|
||||
+#endif
|
||||
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
|
||||
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
|
||||
INF("syscall", S_IRUSR, proc_pid_syscall),
|
||||
#endif
|
||||
INF("cmdline", S_IRUGO, proc_pid_cmdline),
|
||||
diff --git a/include/linux/sched.h b/include/linux/sched.h
|
||||
index 1e2a6db..2c94373 100644
|
||||
--- a/include/linux/sched.h
|
||||
+++ b/include/linux/sched.h
|
||||
@@ -504,10 +504,12 @@ struct thread_group_cputimer {
|
||||
struct task_cputime cputime;
|
||||
int running;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
+struct autogroup;
|
||||
+
|
||||
/*
|
||||
* NOTE! "signal_struct" does not have it's own
|
||||
* locking, because a shared signal_struct always
|
||||
* implies a shared sighand_struct, so locking
|
||||
* sighand_struct is always a proper superset of
|
||||
@@ -571,10 +573,13 @@ struct signal_struct {
|
||||
/* boolean value for session group leader */
|
||||
int leader;
|
||||
|
||||
struct tty_struct *tty; /* NULL if no tty */
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ struct autogroup *autogroup;
|
||||
+#endif
|
||||
/*
|
||||
* Cumulative resource counters for dead threads in the group,
|
||||
* and for reaped dead child processes forked by this group.
|
||||
* Live threads maintain their own counters and add to these
|
||||
* in __exit_signal, except for the group leader.
|
||||
@@ -1898,10 +1903,28 @@ int sched_rt_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos);
|
||||
|
||||
extern unsigned int sysctl_sched_compat_yield;
|
||||
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+extern unsigned int sysctl_sched_autogroup_enabled;
|
||||
+
|
||||
+extern void sched_autogroup_create_attach(struct task_struct *p);
|
||||
+extern void sched_autogroup_detach(struct task_struct *p);
|
||||
+extern void sched_autogroup_fork(struct signal_struct *sig);
|
||||
+extern void sched_autogroup_exit(struct signal_struct *sig);
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+extern void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m);
|
||||
+extern int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice);
|
||||
+#endif
|
||||
+#else
|
||||
+static inline void sched_autogroup_create_attach(struct task_struct *p) { }
|
||||
+static inline void sched_autogroup_detach(struct task_struct *p) { }
|
||||
+static inline void sched_autogroup_fork(struct signal_struct *sig) { }
|
||||
+static inline void sched_autogroup_exit(struct signal_struct *sig) { }
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_RT_MUTEXES
|
||||
extern int rt_mutex_getprio(struct task_struct *p);
|
||||
extern void rt_mutex_setprio(struct task_struct *p, int prio);
|
||||
extern void rt_mutex_adjust_pi(struct task_struct *p);
|
||||
#else
|
||||
diff --git a/init/Kconfig b/init/Kconfig
|
||||
index 2de5b1c..666fc7e 100644
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -650,10 +650,22 @@ config DEBUG_BLK_CGROUP
|
||||
Enable some debugging help. Currently it exports additional stat
|
||||
files in a cgroup which can be useful for debugging.
|
||||
|
||||
endif # CGROUPS
|
||||
|
||||
+config SCHED_AUTOGROUP
|
||||
+ bool "Automatic process group scheduling"
|
||||
+ select CGROUPS
|
||||
+ select CGROUP_SCHED
|
||||
+ select FAIR_GROUP_SCHED
|
||||
+ help
|
||||
+ This option optimizes the scheduler for common desktop workloads by
|
||||
+ automatically creating and populating task groups. This separation
|
||||
+ of workloads isolates aggressive CPU burners (like build jobs) from
|
||||
+ desktop applications. Task group autogeneration is currently based
|
||||
+ upon task session.
|
||||
+
|
||||
config MM_OWNER
|
||||
bool
|
||||
|
||||
config SYSFS_DEPRECATED
|
||||
bool
|
||||
diff --git a/kernel/fork.c b/kernel/fork.c
|
||||
index c445f8c..61f2802 100644
|
||||
--- a/kernel/fork.c
|
||||
+++ b/kernel/fork.c
|
||||
@@ -171,12 +171,14 @@ static inline void free_signal_struct(struct signal_struct *sig)
|
||||
kmem_cache_free(signal_cachep, sig);
|
||||
}
|
||||
|
||||
static inline void put_signal_struct(struct signal_struct *sig)
|
||||
{
|
||||
- if (atomic_dec_and_test(&sig->sigcnt))
|
||||
+ if (atomic_dec_and_test(&sig->sigcnt)) {
|
||||
+ sched_autogroup_exit(sig);
|
||||
free_signal_struct(sig);
|
||||
+ }
|
||||
}
|
||||
|
||||
void __put_task_struct(struct task_struct *tsk)
|
||||
{
|
||||
WARN_ON(!tsk->exit_state);
|
||||
@@ -898,10 +900,11 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
|
||||
task_unlock(current->group_leader);
|
||||
|
||||
posix_cpu_timers_init_group(sig);
|
||||
|
||||
tty_audit_fork(sig);
|
||||
+ sched_autogroup_fork(sig);
|
||||
|
||||
sig->oom_adj = current->signal->oom_adj;
|
||||
sig->oom_score_adj = current->signal->oom_score_adj;
|
||||
|
||||
return 0;
|
||||
diff --git a/kernel/sched.c b/kernel/sched.c
|
||||
index dc85ceb..795e0ec 100644
|
||||
--- a/kernel/sched.c
|
||||
+++ b/kernel/sched.c
|
||||
@@ -76,10 +76,11 @@
|
||||
#include <asm/tlb.h>
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
#include "sched_cpupri.h"
|
||||
#include "workqueue_sched.h"
|
||||
+#include "sched_autogroup.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/sched.h>
|
||||
|
||||
/*
|
||||
@@ -266,10 +267,14 @@ struct task_group {
|
||||
struct list_head list;
|
||||
|
||||
struct task_group *parent;
|
||||
struct list_head siblings;
|
||||
struct list_head children;
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ struct autogroup *autogroup;
|
||||
+#endif
|
||||
};
|
||||
|
||||
#define root_task_group init_task_group
|
||||
|
||||
/* task_group_lock serializes add/remove of task groups and also changes to
|
||||
@@ -610,15 +615,18 @@ static inline int cpu_of(struct rq *rq)
|
||||
* holds that lock for each task it moves into the cgroup. Therefore
|
||||
* by holding that lock, we pin the task to the current cgroup.
|
||||
*/
|
||||
static inline struct task_group *task_group(struct task_struct *p)
|
||||
{
|
||||
+ struct task_group *tg;
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
|
||||
lockdep_is_held(&task_rq(p)->lock));
|
||||
- return container_of(css, struct task_group, css);
|
||||
+ tg = container_of(css, struct task_group, css);
|
||||
+
|
||||
+ return autogroup_task_group(p, tg);
|
||||
}
|
||||
|
||||
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
|
||||
static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
|
||||
{
|
||||
@@ -1918,10 +1926,11 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
|
||||
}
|
||||
|
||||
#include "sched_idletask.c"
|
||||
#include "sched_fair.c"
|
||||
#include "sched_rt.c"
|
||||
+#include "sched_autogroup.c"
|
||||
#ifdef CONFIG_SCHED_DEBUG
|
||||
# include "sched_debug.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -7747,11 +7756,11 @@ void __init sched_init(void)
|
||||
#endif /* CONFIG_RT_GROUP_SCHED */
|
||||
|
||||
#ifdef CONFIG_CGROUP_SCHED
|
||||
list_add(&init_task_group.list, &task_groups);
|
||||
INIT_LIST_HEAD(&init_task_group.children);
|
||||
-
|
||||
+ autogroup_init(&init_task);
|
||||
#endif /* CONFIG_CGROUP_SCHED */
|
||||
|
||||
#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
|
||||
update_shares_data = __alloc_percpu(nr_cpu_ids * sizeof(unsigned long),
|
||||
__alignof__(unsigned long));
|
||||
diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c
|
||||
new file mode 100644
|
||||
index 0000000..2266b02
|
||||
--- /dev/null
|
||||
+++ b/kernel/sched_autogroup.c
|
||||
@@ -0,0 +1,243 @@
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+
|
||||
+#include <linux/proc_fs.h>
|
||||
+#include <linux/seq_file.h>
|
||||
+#include <linux/kallsyms.h>
|
||||
+#include <linux/utsname.h>
|
||||
+
|
||||
+unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
|
||||
+
|
||||
+struct autogroup {
|
||||
+ struct task_group *tg;
|
||||
+ struct kref kref;
|
||||
+ struct rw_semaphore lock;
|
||||
+ unsigned long id;
|
||||
+ int nice;
|
||||
+};
|
||||
+
|
||||
+static struct autogroup autogroup_default;
|
||||
+static atomic_t autogroup_seq_nr;
|
||||
+
|
||||
+static void autogroup_init(struct task_struct *init_task)
|
||||
+{
|
||||
+ autogroup_default.tg = &init_task_group;
|
||||
+ init_task_group.autogroup = &autogroup_default;
|
||||
+ kref_init(&autogroup_default.kref);
|
||||
+ init_rwsem(&autogroup_default.lock);
|
||||
+ init_task->signal->autogroup = &autogroup_default;
|
||||
+}
|
||||
+
|
||||
+static inline void autogroup_destroy(struct kref *kref)
|
||||
+{
|
||||
+ struct autogroup *ag = container_of(kref, struct autogroup, kref);
|
||||
+ struct task_group *tg = ag->tg;
|
||||
+
|
||||
+ kfree(ag);
|
||||
+ sched_destroy_group(tg);
|
||||
+}
|
||||
+
|
||||
+static inline void autogroup_kref_put(struct autogroup *ag)
|
||||
+{
|
||||
+ kref_put(&ag->kref, autogroup_destroy);
|
||||
+}
|
||||
+
|
||||
+static inline struct autogroup *autogroup_kref_get(struct autogroup *ag)
|
||||
+{
|
||||
+ kref_get(&ag->kref);
|
||||
+ return ag;
|
||||
+}
|
||||
+
|
||||
+static inline struct autogroup *autogroup_create(void)
|
||||
+{
|
||||
+ struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL);
|
||||
+
|
||||
+ if (!ag)
|
||||
+ goto out_fail;
|
||||
+
|
||||
+ ag->tg = sched_create_group(&init_task_group);
|
||||
+
|
||||
+ if (IS_ERR(ag->tg))
|
||||
+ goto out_fail;
|
||||
+
|
||||
+ ag->tg->autogroup = ag;
|
||||
+ kref_init(&ag->kref);
|
||||
+ init_rwsem(&ag->lock);
|
||||
+ ag->id = atomic_inc_return(&autogroup_seq_nr);
|
||||
+
|
||||
+ return ag;
|
||||
+
|
||||
+out_fail:
|
||||
+ if (ag) {
|
||||
+ kfree(ag);
|
||||
+ WARN_ON(1);
|
||||
+ } else
|
||||
+ WARN_ON(1);
|
||||
+
|
||||
+ return autogroup_kref_get(&autogroup_default);
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+task_wants_autogroup(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ if (tg != &root_task_group)
|
||||
+ return false;
|
||||
+
|
||||
+ if (p->sched_class != &fair_sched_class)
|
||||
+ return false;
|
||||
+
|
||||
+ /*
|
||||
+ * We can only assume the task group can't go away on us if
|
||||
+ * autogroup_move_group() can see us on ->thread_group list.
|
||||
+ */
|
||||
+ if (p->flags & PF_EXITING)
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
|
||||
+
|
||||
+ if (enabled && task_wants_autogroup(p, tg))
|
||||
+ return p->signal->autogroup->tg;
|
||||
+
|
||||
+ return tg;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+autogroup_move_group(struct task_struct *p, struct autogroup *ag)
|
||||
+{
|
||||
+ struct autogroup *prev;
|
||||
+ struct task_struct *t;
|
||||
+
|
||||
+ spin_lock(&p->sighand->siglock);
|
||||
+
|
||||
+ prev = p->signal->autogroup;
|
||||
+ if (prev == ag) {
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ p->signal->autogroup = autogroup_kref_get(ag);
|
||||
+ t = p;
|
||||
+
|
||||
+ do {
|
||||
+ sched_move_task(p);
|
||||
+ } while_each_thread(p, t);
|
||||
+
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+
|
||||
+ autogroup_kref_put(prev);
|
||||
+}
|
||||
+
|
||||
+/* Allocates GFP_KERNEL, cannot be called under any spinlock */
|
||||
+void sched_autogroup_create_attach(struct task_struct *p)
|
||||
+{
|
||||
+ struct autogroup *ag = autogroup_create();
|
||||
+
|
||||
+ autogroup_move_group(p, ag);
|
||||
+ /* drop extra refrence added by autogroup_create() */
|
||||
+ autogroup_kref_put(ag);
|
||||
+}
|
||||
+EXPORT_SYMBOL(sched_autogroup_create_attach);
|
||||
+
|
||||
+/* Cannot be called under siglock. Currently has no users */
|
||||
+void sched_autogroup_detach(struct task_struct *p)
|
||||
+{
|
||||
+ autogroup_move_group(p, &autogroup_default);
|
||||
+}
|
||||
+EXPORT_SYMBOL(sched_autogroup_detach);
|
||||
+
|
||||
+void sched_autogroup_fork(struct signal_struct *sig)
|
||||
+{
|
||||
+ struct sighand_struct *sighand = current->sighand;
|
||||
+
|
||||
+ spin_lock(&sighand->siglock);
|
||||
+ sig->autogroup = autogroup_kref_get(current->signal->autogroup);
|
||||
+ spin_unlock(&sighand->siglock);
|
||||
+}
|
||||
+
|
||||
+void sched_autogroup_exit(struct signal_struct *sig)
|
||||
+{
|
||||
+ autogroup_kref_put(sig->autogroup);
|
||||
+}
|
||||
+
|
||||
+static int __init setup_autogroup(char *str)
|
||||
+{
|
||||
+ sysctl_sched_autogroup_enabled = 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+__setup("noautogroup", setup_autogroup);
|
||||
+
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+
|
||||
+static inline struct autogroup *autogroup_get(struct task_struct *p)
|
||||
+{
|
||||
+ struct autogroup *ag;
|
||||
+
|
||||
+ /* task may be moved after we unlock.. tough */
|
||||
+ spin_lock(&p->sighand->siglock);
|
||||
+ ag = autogroup_kref_get(p->signal->autogroup);
|
||||
+ spin_unlock(&p->sighand->siglock);
|
||||
+
|
||||
+ return ag;
|
||||
+}
|
||||
+
|
||||
+int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice)
|
||||
+{
|
||||
+ static unsigned long next = INITIAL_JIFFIES;
|
||||
+ struct autogroup *ag;
|
||||
+ int err;
|
||||
+
|
||||
+ if (*nice < -20 || *nice > 19)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ err = security_task_setnice(current, *nice);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (*nice < 0 && !can_nice(current, *nice))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ /* this is a heavy operation taking global locks.. */
|
||||
+ if (!capable(CAP_SYS_ADMIN) && time_before(jiffies, next))
|
||||
+ return -EAGAIN;
|
||||
+
|
||||
+ next = HZ / 10 + jiffies;;
|
||||
+ ag = autogroup_get(p);
|
||||
+
|
||||
+ down_write(&ag->lock);
|
||||
+ err = sched_group_set_shares(ag->tg, prio_to_weight[*nice + 20]);
|
||||
+ if (!err)
|
||||
+ ag->nice = *nice;
|
||||
+ up_write(&ag->lock);
|
||||
+
|
||||
+ autogroup_kref_put(ag);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
|
||||
+{
|
||||
+ struct autogroup *ag = autogroup_get(p);
|
||||
+
|
||||
+ down_read(&ag->lock);
|
||||
+ seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice);
|
||||
+ up_read(&ag->lock);
|
||||
+
|
||||
+ autogroup_kref_put(ag);
|
||||
+}
|
||||
+#endif /* CONFIG_PROC_FS */
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_DEBUG
|
||||
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ return snprintf(buf, buflen, "%s-%ld", "/autogroup", tg->autogroup->id);
|
||||
+}
|
||||
+#endif /* CONFIG_SCHED_DEBUG */
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
|
||||
new file mode 100644
|
||||
index 0000000..40deaef
|
||||
--- /dev/null
|
||||
+++ b/kernel/sched_autogroup.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg);
|
||||
+
|
||||
+#else /* !CONFIG_SCHED_AUTOGROUP */
|
||||
+
|
||||
+static inline void autogroup_init(struct task_struct *init_task) { }
|
||||
+
|
||||
+static inline struct task_group *
|
||||
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
|
||||
+{
|
||||
+ return tg;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_SCHED_DEBUG
|
||||
+static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif /* CONFIG_SCHED_AUTOGROUP */
|
||||
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
|
||||
index 2e1b0d1..94bcabe 100644
|
||||
--- a/kernel/sched_debug.c
|
||||
+++ b/kernel/sched_debug.c
|
||||
@@ -85,10 +85,24 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu,
|
||||
#undef PN
|
||||
#undef P
|
||||
}
|
||||
#endif
|
||||
|
||||
+#if defined(CONFIG_CGROUP_SCHED) && \
|
||||
+ (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED))
|
||||
+static void task_group_path(struct task_group *tg, char *buf, int buflen)
|
||||
+{
|
||||
+ /* may be NULL if the underlying cgroup isn't fully-created yet */
|
||||
+ if (!tg->css.cgroup) {
|
||||
+ if (!autogroup_path(tg, buf, buflen))
|
||||
+ buf[0] = '\0';
|
||||
+ return;
|
||||
+ }
|
||||
+ cgroup_path(tg->css.cgroup, buf, buflen);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void
|
||||
print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
|
||||
{
|
||||
if (rq->curr == p)
|
||||
SEQ_printf(m, "R");
|
||||
@@ -113,11 +127,11 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
|
||||
#ifdef CONFIG_CGROUP_SCHED
|
||||
{
|
||||
char path[64];
|
||||
|
||||
rcu_read_lock();
|
||||
- cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
|
||||
+ task_group_path(task_group(p), path, sizeof(path));
|
||||
rcu_read_unlock();
|
||||
SEQ_printf(m, " %s", path);
|
||||
}
|
||||
#endif
|
||||
SEQ_printf(m, "\n");
|
||||
@@ -145,23 +159,10 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu)
|
||||
} while_each_thread(g, p);
|
||||
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
}
|
||||
|
||||
-#if defined(CONFIG_CGROUP_SCHED) && \
|
||||
- (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED))
|
||||
-static void task_group_path(struct task_group *tg, char *buf, int buflen)
|
||||
-{
|
||||
- /* may be NULL if the underlying cgroup isn't fully-created yet */
|
||||
- if (!tg->css.cgroup) {
|
||||
- buf[0] = '\0';
|
||||
- return;
|
||||
- }
|
||||
- cgroup_path(tg->css.cgroup, buf, buflen);
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
|
||||
{
|
||||
s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1,
|
||||
spread, rq0_min_vruntime, spread0;
|
||||
struct rq *rq = cpu_rq(cpu);
|
||||
diff --git a/kernel/sys.c b/kernel/sys.c
|
||||
index 7f5a0cd..2745dcd 100644
|
||||
--- a/kernel/sys.c
|
||||
+++ b/kernel/sys.c
|
||||
@@ -1078,12 +1078,14 @@ SYSCALL_DEFINE0(setsid)
|
||||
proc_clear_tty(group_leader);
|
||||
|
||||
err = session;
|
||||
out:
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
- if (err > 0)
|
||||
+ if (err > 0) {
|
||||
proc_sid_connector(group_leader);
|
||||
+ sched_autogroup_create_attach(group_leader);
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
DECLARE_RWSEM(uts_sem);
|
||||
|
||||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
||||
index 3a45c22..165eb9b 100644
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -382,10 +382,21 @@ static struct ctl_table kern_table[] = {
|
||||
.data = &sysctl_sched_compat_yield,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
},
|
||||
+#ifdef CONFIG_SCHED_AUTOGROUP
|
||||
+ {
|
||||
+ .procname = "sched_autogroup_enabled",
|
||||
+ .data = &sysctl_sched_autogroup_enabled,
|
||||
+ .maxlen = sizeof(unsigned int),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_dointvec,
|
||||
+ .extra1 = &zero,
|
||||
+ .extra2 = &one,
|
||||
+ },
|
||||
+#endif
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
{
|
||||
.procname = "prove_locking",
|
||||
.data = &prove_locking,
|
||||
.maxlen = sizeof(int),
|
||||
--
|
||||
1.7.2.2
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,21 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="3"
|
||||
K_KERNEL_PATCH_VER=""
|
||||
K_SABKERNEL_NAME="sabayon"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
K_KERNEL_PATCH_HOTFIXES="${FILESDIR}/hotfixes/2.6.36/v4-sched-automated-per-session-task-groups.patch"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-sabayon-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-sabayon-${PVR} )"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="6"
|
||||
K_KERNEL_PATCH_VER="3"
|
||||
K_SABKERNEL_NAME="sabayon"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-sabayon-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-sabayon-${PVR} )"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="1"
|
||||
K_KERNEL_PATCH_VER="6"
|
||||
K_SABKERNEL_NAME="sabayon"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-sabayon-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-sabayon-${PVR} )"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_NAME="sabayon"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Standard kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-sabayon-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-sabayon-${PVR} )"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="12"
|
||||
K_KERNEL_PATCH_VER="10"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
K_SABKERNEL_LONGTERM="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="10"
|
||||
K_KERNEL_PATCH_VER="14"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
K_SABKERNEL_LONGTERM="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="4"
|
||||
K_KERNEL_PATCH_VER="4"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="7"
|
||||
K_KERNEL_PATCH_VER="6"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_WANT_GENPATCHES=""
|
||||
K_GENPATCHES_VER=""
|
||||
K_SABPATCHES_VER="1"
|
||||
K_KERNEL_PATCH_VER="8"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_SABKERNEL_URI_CONFIG="yes"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,15 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,15 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
@@ -1,15 +0,0 @@
|
||||
# Copyright 2004-2010 Sabayon Linux
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
K_SABKERNEL_SELF_TARBALL_NAME="sabayon"
|
||||
K_SABKERNEL_NAME="server"
|
||||
K_ONLY_SOURCES="1"
|
||||
inherit sabayon-kernel
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
DESCRIPTION="Official Sabayon Linux Server kernel sources"
|
||||
RESTRICT="mirror"
|
||||
IUSE="sources_standalone"
|
||||
|
||||
DEPEND="${DEPEND}
|
||||
sources_standalone? ( !=sys-kernel/linux-server-${PVR} )
|
||||
!sources_standalone? ( =sys-kernel/linux-server-${PVR} )"
|
||||
Reference in New Issue
Block a user