diff options
| -rw-r--r-- | arch/x86/include/asm/syscalls.h | 32 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 69 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 49 | ||||
| -rw-r--r-- | arch/x86/kernel/ioport.c | 28 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 70 | ||||
| -rw-r--r-- | arch/x86/kernel/process_32.c | 73 | ||||
| -rw-r--r-- | arch/x86/kernel/process_64.c | 35 | ||||
| -rw-r--r-- | arch/x86/kernel/signal.c | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/vm86_32.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/x8664_ksyms_64.c | 2 |
10 files changed, 148 insertions, 233 deletions
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 372b76edd63f..b0ce78061708 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
| @@ -18,16 +18,24 @@ | |||
| 18 | /* Common in X86_32 and X86_64 */ | 18 | /* Common in X86_32 and X86_64 */ |
| 19 | /* kernel/ioport.c */ | 19 | /* kernel/ioport.c */ |
| 20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); | 20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); |
| 21 | long sys_iopl(unsigned int, struct pt_regs *); | ||
| 21 | 22 | ||
| 22 | /* kernel/process.c */ | 23 | /* kernel/process.c */ |
| 23 | int sys_fork(struct pt_regs *); | 24 | int sys_fork(struct pt_regs *); |
| 24 | int sys_vfork(struct pt_regs *); | 25 | int sys_vfork(struct pt_regs *); |
| 26 | long sys_execve(char __user *, char __user * __user *, | ||
| 27 | char __user * __user *, struct pt_regs *); | ||
| 28 | long sys_clone(unsigned long, unsigned long, void __user *, | ||
| 29 | void __user *, struct pt_regs *); | ||
| 25 | 30 | ||
| 26 | /* kernel/ldt.c */ | 31 | /* kernel/ldt.c */ |
| 27 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); | 32 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); |
| 28 | 33 | ||
| 29 | /* kernel/signal.c */ | 34 | /* kernel/signal.c */ |
| 30 | long sys_rt_sigreturn(struct pt_regs *); | 35 | long sys_rt_sigreturn(struct pt_regs *); |
| 36 | long sys_sigaltstack(const stack_t __user *, stack_t __user *, | ||
| 37 | struct pt_regs *); | ||
| 38 | |||
| 31 | 39 | ||
| 32 | /* kernel/tls.c */ | 40 | /* kernel/tls.c */ |
| 33 | asmlinkage int sys_set_thread_area(struct user_desc __user *); | 41 | asmlinkage int sys_set_thread_area(struct user_desc __user *); |
| @@ -35,18 +43,11 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *); | |||
| 35 | 43 | ||
| 36 | /* X86_32 only */ | 44 | /* X86_32 only */ |
| 37 | #ifdef CONFIG_X86_32 | 45 | #ifdef CONFIG_X86_32 |
| 38 | /* kernel/ioport.c */ | ||
| 39 | long sys_iopl(struct pt_regs *); | ||
| 40 | |||
| 41 | /* kernel/process_32.c */ | ||
| 42 | int sys_clone(struct pt_regs *); | ||
| 43 | int sys_execve(struct pt_regs *); | ||
| 44 | 46 | ||
| 45 | /* kernel/signal.c */ | 47 | /* kernel/signal.c */ |
| 46 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); | 48 | asmlinkage int sys_sigsuspend(int, int, old_sigset_t); |
| 47 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, | 49 | asmlinkage int sys_sigaction(int, const struct old_sigaction __user *, |
| 48 | struct old_sigaction __user *); | 50 | struct old_sigaction __user *); |
| 49 | int sys_sigaltstack(struct pt_regs *); | ||
| 50 | unsigned long sys_sigreturn(struct pt_regs *); | 51 | unsigned long sys_sigreturn(struct pt_regs *); |
| 51 | 52 | ||
| 52 | /* kernel/sys_i386_32.c */ | 53 | /* kernel/sys_i386_32.c */ |
| @@ -64,28 +65,15 @@ asmlinkage int sys_uname(struct old_utsname __user *); | |||
| 64 | asmlinkage int sys_olduname(struct oldold_utsname __user *); | 65 | asmlinkage int sys_olduname(struct oldold_utsname __user *); |
| 65 | 66 | ||
| 66 | /* kernel/vm86_32.c */ | 67 | /* kernel/vm86_32.c */ |
| 67 | int sys_vm86old(struct pt_regs *); | 68 | int sys_vm86old(struct vm86_struct __user *, struct pt_regs *); |
| 68 | int sys_vm86(struct pt_regs *); | 69 | int sys_vm86(unsigned long, unsigned long, struct pt_regs *); |
| 69 | 70 | ||
| 70 | #else /* CONFIG_X86_32 */ | 71 | #else /* CONFIG_X86_32 */ |
| 71 | 72 | ||
| 72 | /* X86_64 only */ | 73 | /* X86_64 only */ |
| 73 | /* kernel/ioport.c */ | ||
| 74 | asmlinkage long sys_iopl(unsigned int, struct pt_regs *); | ||
| 75 | |||
| 76 | /* kernel/process_64.c */ | 74 | /* kernel/process_64.c */ |
| 77 | asmlinkage long sys_clone(unsigned long, unsigned long, | ||
| 78 | void __user *, void __user *, | ||
| 79 | struct pt_regs *); | ||
| 80 | asmlinkage long sys_execve(char __user *, char __user * __user *, | ||
| 81 | char __user * __user *, | ||
| 82 | struct pt_regs *); | ||
| 83 | long sys_arch_prctl(int, unsigned long); | 75 | long sys_arch_prctl(int, unsigned long); |
| 84 | 76 | ||
| 85 | /* kernel/signal.c */ | ||
| 86 | asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, | ||
| 87 | struct pt_regs *); | ||
| 88 | |||
| 89 | /* kernel/sys_x86_64.c */ | 77 | /* kernel/sys_x86_64.c */ |
| 90 | struct new_utsname; | 78 | struct new_utsname; |
| 91 | 79 | ||
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 50b9c220e121..44a8e0dc6737 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -725,22 +725,61 @@ END(syscall_badsys) | |||
| 725 | /* | 725 | /* |
| 726 | * System calls that need a pt_regs pointer. | 726 | * System calls that need a pt_regs pointer. |
| 727 | */ | 727 | */ |
| 728 | #define PTREGSCALL(name) \ | 728 | #define PTREGSCALL0(name) \ |
| 729 | ALIGN; \ | 729 | ALIGN; \ |
| 730 | ptregs_##name: \ | 730 | ptregs_##name: \ |
| 731 | leal 4(%esp),%eax; \ | 731 | leal 4(%esp),%eax; \ |
| 732 | jmp sys_##name; | 732 | jmp sys_##name; |
| 733 | 733 | ||
| 734 | PTREGSCALL(iopl) | 734 | #define PTREGSCALL1(name) \ |
| 735 | PTREGSCALL(fork) | 735 | ALIGN; \ |
| 736 | PTREGSCALL(clone) | 736 | ptregs_##name: \ |
| 737 | PTREGSCALL(vfork) | 737 | leal 4(%esp),%edx; \ |
| 738 | PTREGSCALL(execve) | 738 | movl (PT_EBX+4)(%esp),%eax; \ |
| 739 | PTREGSCALL(sigaltstack) | 739 | jmp sys_##name; |
| 740 | PTREGSCALL(sigreturn) | 740 | |
| 741 | PTREGSCALL(rt_sigreturn) | 741 | #define PTREGSCALL2(name) \ |
| 742 | PTREGSCALL(vm86) | 742 | ALIGN; \ |
| 743 | PTREGSCALL(vm86old) | 743 | ptregs_##name: \ |
| 744 | leal 4(%esp),%ecx; \ | ||
| 745 | movl (PT_ECX+4)(%esp),%edx; \ | ||
| 746 | movl (PT_EBX+4)(%esp),%eax; \ | ||
| 747 | jmp sys_##name; | ||
| 748 | |||
| 749 | #define PTREGSCALL3(name) \ | ||
| 750 | ALIGN; \ | ||
| 751 | ptregs_##name: \ | ||
| 752 | leal 4(%esp),%eax; \ | ||
| 753 | pushl %eax; \ | ||
| 754 | movl PT_EDX(%eax),%ecx; \ | ||
| 755 | movl PT_ECX(%eax),%edx; \ | ||
| 756 | movl PT_EBX(%eax),%eax; \ | ||
| 757 | call sys_##name; \ | ||
| 758 | addl $4,%esp; \ | ||
| 759 | ret | ||
| 760 | |||
| 761 | PTREGSCALL1(iopl) | ||
| 762 | PTREGSCALL0(fork) | ||
| 763 | PTREGSCALL0(vfork) | ||
| 764 | PTREGSCALL3(execve) | ||
| 765 | PTREGSCALL2(sigaltstack) | ||
| 766 | PTREGSCALL0(sigreturn) | ||
| 767 | PTREGSCALL0(rt_sigreturn) | ||
| 768 | PTREGSCALL2(vm86) | ||
| 769 | PTREGSCALL1(vm86old) | ||
| 770 | |||
| 771 | /* Clone is an oddball. The 4th arg is in %edi */ | ||
| 772 | ALIGN; | ||
| 773 | ptregs_clone: | ||
| 774 | leal 4(%esp),%eax | ||
| 775 | pushl %eax | ||
| 776 | pushl PT_EDI(%eax) | ||
| 777 | movl PT_EDX(%eax),%ecx | ||
| 778 | movl PT_ECX(%eax),%edx | ||
| 779 | movl PT_EBX(%eax),%eax | ||
| 780 | call sys_clone | ||
| 781 | addl $8,%esp | ||
| 782 | ret | ||
| 744 | 783 | ||
| 745 | .macro FIXUP_ESPFIX_STACK | 784 | .macro FIXUP_ESPFIX_STACK |
| 746 | /* | 785 | /* |
| @@ -1008,12 +1047,8 @@ END(spurious_interrupt_bug) | |||
| 1008 | ENTRY(kernel_thread_helper) | 1047 | ENTRY(kernel_thread_helper) |
| 1009 | pushl $0 # fake return address for unwinder | 1048 | pushl $0 # fake return address for unwinder |
| 1010 | CFI_STARTPROC | 1049 | CFI_STARTPROC |
| 1011 | movl %edx,%eax | 1050 | movl %edi,%eax |
| 1012 | push %edx | 1051 | call *%esi |
| 1013 | CFI_ADJUST_CFA_OFFSET 4 | ||
| 1014 | call *%ebx | ||
| 1015 | push %eax | ||
| 1016 | CFI_ADJUST_CFA_OFFSET 4 | ||
| 1017 | call do_exit | 1052 | call do_exit |
| 1018 | ud2 # padding for call trace | 1053 | ud2 # padding for call trace |
| 1019 | CFI_ENDPROC | 1054 | CFI_ENDPROC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 63bca794c8f9..73d9b2c0e217 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -1166,63 +1166,20 @@ bad_gs: | |||
| 1166 | jmp 2b | 1166 | jmp 2b |
| 1167 | .previous | 1167 | .previous |
| 1168 | 1168 | ||
| 1169 | /* | 1169 | ENTRY(kernel_thread_helper) |
| 1170 | * Create a kernel thread. | ||
| 1171 | * | ||
| 1172 | * C extern interface: | ||
| 1173 | * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 1174 | * | ||
| 1175 | * asm input arguments: | ||
| 1176 | * rdi: fn, rsi: arg, rdx: flags | ||
| 1177 | */ | ||
| 1178 | ENTRY(kernel_thread) | ||
| 1179 | CFI_STARTPROC | ||
| 1180 | FAKE_STACK_FRAME $child_rip | ||
| 1181 | SAVE_ALL | ||
| 1182 | |||
| 1183 | # rdi: flags, rsi: usp, rdx: will be &pt_regs | ||
| 1184 | movq %rdx,%rdi | ||
| 1185 | orq kernel_thread_flags(%rip),%rdi | ||
| 1186 | movq $-1, %rsi | ||
| 1187 | movq %rsp, %rdx | ||
| 1188 | |||
| 1189 | xorl %r8d,%r8d | ||
| 1190 | xorl %r9d,%r9d | ||
| 1191 | |||
| 1192 | # clone now | ||
| 1193 | call do_fork | ||
| 1194 | movq %rax,RAX(%rsp) | ||
| 1195 | xorl %edi,%edi | ||
| 1196 | |||
| 1197 | /* | ||
| 1198 | * It isn't worth to check for reschedule here, | ||
| 1199 | * so internally to the x86_64 port you can rely on kernel_thread() | ||
| 1200 | * not to reschedule the child before returning, this avoids the need | ||
| 1201 | * of hacks for example to fork off the per-CPU idle tasks. | ||
| 1202 | * [Hopefully no generic code relies on the reschedule -AK] | ||
| 1203 | */ | ||
| 1204 | RESTORE_ALL | ||
| 1205 | UNFAKE_STACK_FRAME | ||
| 1206 | ret | ||
| 1207 | CFI_ENDPROC | ||
| 1208 | END(kernel_thread) | ||
| 1209 | |||
| 1210 | ENTRY(child_rip) | ||
| 1211 | pushq $0 # fake return address | 1170 | pushq $0 # fake return address |
| 1212 | CFI_STARTPROC | 1171 | CFI_STARTPROC |
| 1213 | /* | 1172 | /* |
| 1214 | * Here we are in the child and the registers are set as they were | 1173 | * Here we are in the child and the registers are set as they were |
| 1215 | * at kernel_thread() invocation in the parent. | 1174 | * at kernel_thread() invocation in the parent. |
| 1216 | */ | 1175 | */ |
| 1217 | movq %rdi, %rax | 1176 | call *%rsi |
| 1218 | movq %rsi, %rdi | ||
| 1219 | call *%rax | ||
| 1220 | # exit | 1177 | # exit |
| 1221 | mov %eax, %edi | 1178 | mov %eax, %edi |
| 1222 | call do_exit | 1179 | call do_exit |
| 1223 | ud2 # padding for call trace | 1180 | ud2 # padding for call trace |
| 1224 | CFI_ENDPROC | 1181 | CFI_ENDPROC |
| 1225 | END(child_rip) | 1182 | END(kernel_thread_helper) |
| 1226 | 1183 | ||
| 1227 | /* | 1184 | /* |
| 1228 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. | 1185 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. |
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index 99c4d308f16b..8eec0ec59af2 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c | |||
| @@ -103,9 +103,10 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
| 103 | * on system-call entry - see also fork() and the signal handling | 103 | * on system-call entry - see also fork() and the signal handling |
| 104 | * code. | 104 | * code. |
| 105 | */ | 105 | */ |
| 106 | static int do_iopl(unsigned int level, struct pt_regs *regs) | 106 | long sys_iopl(unsigned int level, struct pt_regs *regs) |
| 107 | { | 107 | { |
| 108 | unsigned int old = (regs->flags >> 12) & 3; | 108 | unsigned int old = (regs->flags >> 12) & 3; |
| 109 | struct thread_struct *t = ¤t->thread; | ||
| 109 | 110 | ||
| 110 | if (level > 3) | 111 | if (level > 3) |
| 111 | return -EINVAL; | 112 | return -EINVAL; |
| @@ -115,29 +116,8 @@ static int do_iopl(unsigned int level, struct pt_regs *regs) | |||
| 115 | return -EPERM; | 116 | return -EPERM; |
| 116 | } | 117 | } |
| 117 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); | 118 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); |
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | #ifdef CONFIG_X86_32 | ||
| 123 | long sys_iopl(struct pt_regs *regs) | ||
| 124 | { | ||
| 125 | unsigned int level = regs->bx; | ||
| 126 | struct thread_struct *t = ¤t->thread; | ||
| 127 | int rc; | ||
| 128 | |||
| 129 | rc = do_iopl(level, regs); | ||
| 130 | if (rc < 0) | ||
| 131 | goto out; | ||
| 132 | |||
| 133 | t->iopl = level << 12; | 119 | t->iopl = level << 12; |
| 134 | set_iopl_mask(t->iopl); | 120 | set_iopl_mask(t->iopl); |
| 135 | out: | 121 | |
| 136 | return rc; | 122 | return 0; |
| 137 | } | ||
| 138 | #else | ||
| 139 | asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) | ||
| 140 | { | ||
| 141 | return do_iopl(level, regs); | ||
| 142 | } | 123 | } |
| 143 | #endif | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7a7bd4e3ec49..98c2cdeb599e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -255,6 +255,76 @@ int sys_vfork(struct pt_regs *regs) | |||
| 255 | NULL, NULL); | 255 | NULL, NULL); |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | long | ||
| 259 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
| 260 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
| 261 | { | ||
| 262 | if (!newsp) | ||
| 263 | newsp = regs->sp; | ||
| 264 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* | ||
| 268 | * This gets run with %si containing the | ||
| 269 | * function to call, and %di containing | ||
| 270 | * the "args". | ||
| 271 | */ | ||
| 272 | extern void kernel_thread_helper(void); | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Create a kernel thread | ||
| 276 | */ | ||
| 277 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 278 | { | ||
| 279 | struct pt_regs regs; | ||
| 280 | |||
| 281 | memset(®s, 0, sizeof(regs)); | ||
| 282 | |||
| 283 | regs.si = (unsigned long) fn; | ||
| 284 | regs.di = (unsigned long) arg; | ||
| 285 | |||
| 286 | #ifdef CONFIG_X86_32 | ||
| 287 | regs.ds = __USER_DS; | ||
| 288 | regs.es = __USER_DS; | ||
| 289 | regs.fs = __KERNEL_PERCPU; | ||
| 290 | regs.gs = __KERNEL_STACK_CANARY; | ||
| 291 | #endif | ||
| 292 | |||
| 293 | regs.orig_ax = -1; | ||
| 294 | regs.ip = (unsigned long) kernel_thread_helper; | ||
| 295 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
| 296 | regs.flags = X86_EFLAGS_IF | 0x2; | ||
| 297 | |||
| 298 | /* Ok, create the new process.. */ | ||
| 299 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
| 300 | } | ||
| 301 | EXPORT_SYMBOL(kernel_thread); | ||
| 302 | |||
| 303 | /* | ||
| 304 | * sys_execve() executes a new program. | ||
| 305 | */ | ||
| 306 | long sys_execve(char __user *name, char __user * __user *argv, | ||
| 307 | char __user * __user *envp, struct pt_regs *regs) | ||
| 308 | { | ||
| 309 | long error; | ||
| 310 | char *filename; | ||
| 311 | |||
| 312 | filename = getname(name); | ||
| 313 | error = PTR_ERR(filename); | ||
| 314 | if (IS_ERR(filename)) | ||
| 315 | return error; | ||
| 316 | error = do_execve(filename, argv, envp, regs); | ||
| 317 | |||
| 318 | #ifdef CONFIG_X86_32 | ||
| 319 | if (error == 0) { | ||
| 320 | /* Make sure we don't return using sysenter.. */ | ||
| 321 | set_thread_flag(TIF_IRET); | ||
| 322 | } | ||
| 323 | #endif | ||
| 324 | |||
| 325 | putname(filename); | ||
| 326 | return error; | ||
| 327 | } | ||
| 258 | 328 | ||
| 259 | /* | 329 | /* |
| 260 | * Idle related variables and functions | 330 | * Idle related variables and functions |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 120b88797a75..9c517b5858f0 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -180,39 +180,6 @@ void show_regs(struct pt_regs *regs) | |||
| 180 | show_trace(NULL, regs, ®s->sp, regs->bp); | 180 | show_trace(NULL, regs, ®s->sp, regs->bp); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /* | ||
| 184 | * This gets run with %bx containing the | ||
| 185 | * function to call, and %dx containing | ||
| 186 | * the "args". | ||
| 187 | */ | ||
| 188 | extern void kernel_thread_helper(void); | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Create a kernel thread | ||
| 192 | */ | ||
| 193 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 194 | { | ||
| 195 | struct pt_regs regs; | ||
| 196 | |||
| 197 | memset(®s, 0, sizeof(regs)); | ||
| 198 | |||
| 199 | regs.bx = (unsigned long) fn; | ||
| 200 | regs.dx = (unsigned long) arg; | ||
| 201 | |||
| 202 | regs.ds = __USER_DS; | ||
| 203 | regs.es = __USER_DS; | ||
| 204 | regs.fs = __KERNEL_PERCPU; | ||
| 205 | regs.gs = __KERNEL_STACK_CANARY; | ||
| 206 | regs.orig_ax = -1; | ||
| 207 | regs.ip = (unsigned long) kernel_thread_helper; | ||
| 208 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
| 209 | regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; | ||
| 210 | |||
| 211 | /* Ok, create the new process.. */ | ||
| 212 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
| 213 | } | ||
| 214 | EXPORT_SYMBOL(kernel_thread); | ||
| 215 | |||
| 216 | void release_thread(struct task_struct *dead_task) | 183 | void release_thread(struct task_struct *dead_task) |
| 217 | { | 184 | { |
| 218 | BUG_ON(dead_task->mm); | 185 | BUG_ON(dead_task->mm); |
| @@ -424,46 +391,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 424 | return prev_p; | 391 | return prev_p; |
| 425 | } | 392 | } |
| 426 | 393 | ||
| 427 | int sys_clone(struct pt_regs *regs) | ||
| 428 | { | ||
| 429 | unsigned long clone_flags; | ||
| 430 | unsigned long newsp; | ||
| 431 | int __user *parent_tidptr, *child_tidptr; | ||
| 432 | |||
| 433 | clone_flags = regs->bx; | ||
| 434 | newsp = regs->cx; | ||
| 435 | parent_tidptr = (int __user *)regs->dx; | ||
| 436 | child_tidptr = (int __user *)regs->di; | ||
| 437 | if (!newsp) | ||
| 438 | newsp = regs->sp; | ||
| 439 | return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); | ||
| 440 | } | ||
| 441 | |||
| 442 | /* | ||
| 443 | * sys_execve() executes a new program. | ||
| 444 | */ | ||
| 445 | int sys_execve(struct pt_regs *regs) | ||
| 446 | { | ||
| 447 | int error; | ||
| 448 | char *filename; | ||
| 449 | |||
| 450 | filename = getname((char __user *) regs->bx); | ||
| 451 | error = PTR_ERR(filename); | ||
| 452 | if (IS_ERR(filename)) | ||
| 453 | goto out; | ||
| 454 | error = do_execve(filename, | ||
| 455 | (char __user * __user *) regs->cx, | ||
| 456 | (char __user * __user *) regs->dx, | ||
| 457 | regs); | ||
| 458 | if (error == 0) { | ||
| 459 | /* Make sure we don't return using sysenter.. */ | ||
| 460 | set_thread_flag(TIF_IRET); | ||
| 461 | } | ||
| 462 | putname(filename); | ||
| 463 | out: | ||
| 464 | return error; | ||
| 465 | } | ||
| 466 | |||
| 467 | #define top_esp (THREAD_SIZE - sizeof(unsigned long)) | 394 | #define top_esp (THREAD_SIZE - sizeof(unsigned long)) |
| 468 | #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) | 395 | #define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) |
| 469 | 396 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e5ab0cd0ef36..52fbd0c60198 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -57,8 +57,6 @@ asmlinkage extern void ret_from_fork(void); | |||
| 57 | DEFINE_PER_CPU(unsigned long, old_rsp); | 57 | DEFINE_PER_CPU(unsigned long, old_rsp); |
| 58 | static DEFINE_PER_CPU(unsigned char, is_idle); | 58 | static DEFINE_PER_CPU(unsigned char, is_idle); |
| 59 | 59 | ||
| 60 | unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; | ||
| 61 | |||
| 62 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); | 60 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
| 63 | 61 | ||
| 64 | void idle_notifier_register(struct notifier_block *n) | 62 | void idle_notifier_register(struct notifier_block *n) |
| @@ -273,8 +271,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
| 273 | *childregs = *regs; | 271 | *childregs = *regs; |
| 274 | 272 | ||
| 275 | childregs->ax = 0; | 273 | childregs->ax = 0; |
| 276 | childregs->sp = sp; | 274 | if (user_mode(regs)) |
| 277 | if (sp == ~0UL) | 275 | childregs->sp = sp; |
| 276 | else | ||
| 278 | childregs->sp = (unsigned long)childregs; | 277 | childregs->sp = (unsigned long)childregs; |
| 279 | 278 | ||
| 280 | p->thread.sp = (unsigned long) childregs; | 279 | p->thread.sp = (unsigned long) childregs; |
| @@ -508,25 +507,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
| 508 | return prev_p; | 507 | return prev_p; |
| 509 | } | 508 | } |
| 510 | 509 | ||
| 511 | /* | ||
| 512 | * sys_execve() executes a new program. | ||
| 513 | */ | ||
| 514 | asmlinkage | ||
| 515 | long sys_execve(char __user *name, char __user * __user *argv, | ||
| 516 | char __user * __user *envp, struct pt_regs *regs) | ||
| 517 | { | ||
| 518 | long error; | ||
| 519 | char *filename; | ||
| 520 | |||
| 521 | filename = getname(name); | ||
| 522 | error = PTR_ERR(filename); | ||
| 523 | if (IS_ERR(filename)) | ||
| 524 | return error; | ||
| 525 | error = do_execve(filename, argv, envp, regs); | ||
| 526 | putname(filename); | ||
| 527 | return error; | ||
| 528 | } | ||
| 529 | |||
| 530 | void set_personality_64bit(void) | 510 | void set_personality_64bit(void) |
| 531 | { | 511 | { |
| 532 | /* inherit personality from parent */ | 512 | /* inherit personality from parent */ |
| @@ -541,15 +521,6 @@ void set_personality_64bit(void) | |||
| 541 | current->personality &= ~READ_IMPLIES_EXEC; | 521 | current->personality &= ~READ_IMPLIES_EXEC; |
| 542 | } | 522 | } |
| 543 | 523 | ||
| 544 | asmlinkage long | ||
| 545 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
| 546 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
| 547 | { | ||
| 548 | if (!newsp) | ||
| 549 | newsp = regs->sp; | ||
| 550 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
| 551 | } | ||
| 552 | |||
| 553 | unsigned long get_wchan(struct task_struct *p) | 524 | unsigned long get_wchan(struct task_struct *p) |
| 554 | { | 525 | { |
| 555 | unsigned long stack; | 526 | unsigned long stack; |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 74fe6d86dc5d..4fd173cd8e57 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
| @@ -545,22 +545,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
| 545 | } | 545 | } |
| 546 | #endif /* CONFIG_X86_32 */ | 546 | #endif /* CONFIG_X86_32 */ |
| 547 | 547 | ||
| 548 | #ifdef CONFIG_X86_32 | 548 | long |
| 549 | int sys_sigaltstack(struct pt_regs *regs) | ||
| 550 | { | ||
| 551 | const stack_t __user *uss = (const stack_t __user *)regs->bx; | ||
| 552 | stack_t __user *uoss = (stack_t __user *)regs->cx; | ||
| 553 | |||
| 554 | return do_sigaltstack(uss, uoss, regs->sp); | ||
| 555 | } | ||
| 556 | #else /* !CONFIG_X86_32 */ | ||
| 557 | asmlinkage long | ||
| 558 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 549 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
| 559 | struct pt_regs *regs) | 550 | struct pt_regs *regs) |
| 560 | { | 551 | { |
| 561 | return do_sigaltstack(uss, uoss, regs->sp); | 552 | return do_sigaltstack(uss, uoss, regs->sp); |
| 562 | } | 553 | } |
| 563 | #endif /* CONFIG_X86_32 */ | ||
| 564 | 554 | ||
| 565 | /* | 555 | /* |
| 566 | * Do a signal return; undo the signal stack. | 556 | * Do a signal return; undo the signal stack. |
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 9c4e62539058..5ffb5622f793 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
| @@ -197,9 +197,8 @@ out: | |||
| 197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); | 197 | static int do_vm86_irq_handling(int subfunction, int irqnumber); |
| 198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); | 198 | static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); |
| 199 | 199 | ||
| 200 | int sys_vm86old(struct pt_regs *regs) | 200 | int sys_vm86old(struct vm86_struct __user *v86, struct pt_regs *regs) |
| 201 | { | 201 | { |
| 202 | struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs->bx; | ||
| 203 | struct kernel_vm86_struct info; /* declare this _on top_, | 202 | struct kernel_vm86_struct info; /* declare this _on top_, |
| 204 | * this avoids wasting of stack space. | 203 | * this avoids wasting of stack space. |
| 205 | * This remains on the stack until we | 204 | * This remains on the stack until we |
| @@ -227,7 +226,7 @@ out: | |||
| 227 | } | 226 | } |
| 228 | 227 | ||
| 229 | 228 | ||
| 230 | int sys_vm86(struct pt_regs *regs) | 229 | int sys_vm86(unsigned long cmd, unsigned long arg, struct pt_regs *regs) |
| 231 | { | 230 | { |
| 232 | struct kernel_vm86_struct info; /* declare this _on top_, | 231 | struct kernel_vm86_struct info; /* declare this _on top_, |
| 233 | * this avoids wasting of stack space. | 232 | * this avoids wasting of stack space. |
| @@ -239,12 +238,12 @@ int sys_vm86(struct pt_regs *regs) | |||
| 239 | struct vm86plus_struct __user *v86; | 238 | struct vm86plus_struct __user *v86; |
| 240 | 239 | ||
| 241 | tsk = current; | 240 | tsk = current; |
| 242 | switch (regs->bx) { | 241 | switch (cmd) { |
| 243 | case VM86_REQUEST_IRQ: | 242 | case VM86_REQUEST_IRQ: |
| 244 | case VM86_FREE_IRQ: | 243 | case VM86_FREE_IRQ: |
| 245 | case VM86_GET_IRQ_BITS: | 244 | case VM86_GET_IRQ_BITS: |
| 246 | case VM86_GET_AND_RESET_IRQ: | 245 | case VM86_GET_AND_RESET_IRQ: |
| 247 | ret = do_vm86_irq_handling(regs->bx, (int)regs->cx); | 246 | ret = do_vm86_irq_handling(cmd, (int)arg); |
| 248 | goto out; | 247 | goto out; |
| 249 | case VM86_PLUS_INSTALL_CHECK: | 248 | case VM86_PLUS_INSTALL_CHECK: |
| 250 | /* | 249 | /* |
| @@ -261,7 +260,7 @@ int sys_vm86(struct pt_regs *regs) | |||
| 261 | ret = -EPERM; | 260 | ret = -EPERM; |
| 262 | if (tsk->thread.saved_sp0) | 261 | if (tsk->thread.saved_sp0) |
| 263 | goto out; | 262 | goto out; |
| 264 | v86 = (struct vm86plus_struct __user *)regs->cx; | 263 | v86 = (struct vm86plus_struct __user *)arg; |
| 265 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, | 264 | tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, |
| 266 | offsetof(struct kernel_vm86_struct, regs32) - | 265 | offsetof(struct kernel_vm86_struct, regs32) - |
| 267 | sizeof(info.regs)); | 266 | sizeof(info.regs)); |
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index a1029769b6f2..9fafaf83b3b8 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
| @@ -17,8 +17,6 @@ | |||
| 17 | EXPORT_SYMBOL(mcount); | 17 | EXPORT_SYMBOL(mcount); |
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | EXPORT_SYMBOL(kernel_thread); | ||
| 21 | |||
| 22 | EXPORT_SYMBOL(__get_user_1); | 20 | EXPORT_SYMBOL(__get_user_1); |
| 23 | EXPORT_SYMBOL(__get_user_2); | 21 | EXPORT_SYMBOL(__get_user_2); |
| 24 | EXPORT_SYMBOL(__get_user_4); | 22 | EXPORT_SYMBOL(__get_user_4); |
