diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/calls.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 60 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.h | 14 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 129 | ||||
-rw-r--r-- | arch/arm/kernel/sys_oabi-compat.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/unwind.c | 4 |
6 files changed, 17 insertions, 197 deletions
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 9314a2d681f..37ae301cc47 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -91,7 +91,7 @@ | |||
91 | CALL(sys_settimeofday) | 91 | CALL(sys_settimeofday) |
92 | /* 80 */ CALL(sys_getgroups16) | 92 | /* 80 */ CALL(sys_getgroups16) |
93 | CALL(sys_setgroups16) | 93 | CALL(sys_setgroups16) |
94 | CALL(OBSOLETE(old_select)) /* used by libc4 */ | 94 | CALL(OBSOLETE(sys_old_select)) /* used by libc4 */ |
95 | CALL(sys_symlink) | 95 | CALL(sys_symlink) |
96 | CALL(sys_ni_syscall) /* was sys_lstat */ | 96 | CALL(sys_ni_syscall) /* was sys_lstat */ |
97 | /* 85 */ CALL(sys_readlink) | 97 | /* 85 */ CALL(sys_readlink) |
@@ -99,7 +99,7 @@ | |||
99 | CALL(sys_swapon) | 99 | CALL(sys_swapon) |
100 | CALL(sys_reboot) | 100 | CALL(sys_reboot) |
101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ | 101 | CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ |
102 | /* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */ | 102 | /* 90 */ CALL(OBSOLETE(sys_old_mmap)) /* used by libc4 */ |
103 | CALL(sys_munmap) | 103 | CALL(sys_munmap) |
104 | CALL(sys_truncate) | 104 | CALL(sys_truncate) |
105 | CALL(sys_ftruncate) | 105 | CALL(sys_ftruncate) |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 08f899fb76a..3f562a7c0a9 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -452,12 +452,23 @@ void ptrace_cancel_bpt(struct task_struct *child) | |||
452 | clear_breakpoint(child, &child->thread.debug.bp[i]); | 452 | clear_breakpoint(child, &child->thread.debug.bp[i]); |
453 | } | 453 | } |
454 | 454 | ||
455 | void user_disable_single_step(struct task_struct *task) | ||
456 | { | ||
457 | task->ptrace &= ~PT_SINGLESTEP; | ||
458 | ptrace_cancel_bpt(task); | ||
459 | } | ||
460 | |||
461 | void user_enable_single_step(struct task_struct *task) | ||
462 | { | ||
463 | task->ptrace |= PT_SINGLESTEP; | ||
464 | } | ||
465 | |||
455 | /* | 466 | /* |
456 | * Called by kernel/ptrace.c when detaching.. | 467 | * Called by kernel/ptrace.c when detaching.. |
457 | */ | 468 | */ |
458 | void ptrace_disable(struct task_struct *child) | 469 | void ptrace_disable(struct task_struct *child) |
459 | { | 470 | { |
460 | single_step_disable(child); | 471 | user_disable_single_step(child); |
461 | } | 472 | } |
462 | 473 | ||
463 | /* | 474 | /* |
@@ -753,53 +764,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
753 | ret = ptrace_write_user(child, addr, data); | 764 | ret = ptrace_write_user(child, addr, data); |
754 | break; | 765 | break; |
755 | 766 | ||
756 | /* | ||
757 | * continue/restart and stop at next (return from) syscall | ||
758 | */ | ||
759 | case PTRACE_SYSCALL: | ||
760 | case PTRACE_CONT: | ||
761 | ret = -EIO; | ||
762 | if (!valid_signal(data)) | ||
763 | break; | ||
764 | if (request == PTRACE_SYSCALL) | ||
765 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
766 | else | ||
767 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
768 | child->exit_code = data; | ||
769 | single_step_disable(child); | ||
770 | wake_up_process(child); | ||
771 | ret = 0; | ||
772 | break; | ||
773 | |||
774 | /* | ||
775 | * make the child exit. Best I can do is send it a sigkill. | ||
776 | * perhaps it should be put in the status that it wants to | ||
777 | * exit. | ||
778 | */ | ||
779 | case PTRACE_KILL: | ||
780 | single_step_disable(child); | ||
781 | if (child->exit_state != EXIT_ZOMBIE) { | ||
782 | child->exit_code = SIGKILL; | ||
783 | wake_up_process(child); | ||
784 | } | ||
785 | ret = 0; | ||
786 | break; | ||
787 | |||
788 | /* | ||
789 | * execute single instruction. | ||
790 | */ | ||
791 | case PTRACE_SINGLESTEP: | ||
792 | ret = -EIO; | ||
793 | if (!valid_signal(data)) | ||
794 | break; | ||
795 | single_step_enable(child); | ||
796 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
797 | child->exit_code = data; | ||
798 | /* give it a chance to run. */ | ||
799 | wake_up_process(child); | ||
800 | ret = 0; | ||
801 | break; | ||
802 | |||
803 | case PTRACE_GETREGS: | 767 | case PTRACE_GETREGS: |
804 | ret = ptrace_getregs(child, (void __user *)data); | 768 | ret = ptrace_getregs(child, (void __user *)data); |
805 | break; | 769 | break; |
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h index def3b6184a7..3926605b82e 100644 --- a/arch/arm/kernel/ptrace.h +++ b/arch/arm/kernel/ptrace.h | |||
@@ -14,20 +14,6 @@ extern void ptrace_set_bpt(struct task_struct *); | |||
14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); | 14 | extern void ptrace_break(struct task_struct *, struct pt_regs *); |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * make sure single-step breakpoint is gone. | ||
18 | */ | ||
19 | static inline void single_step_disable(struct task_struct *task) | ||
20 | { | ||
21 | task->ptrace &= ~PT_SINGLESTEP; | ||
22 | ptrace_cancel_bpt(task); | ||
23 | } | ||
24 | |||
25 | static inline void single_step_enable(struct task_struct *task) | ||
26 | { | ||
27 | task->ptrace |= PT_SINGLESTEP; | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Send SIGTRAP if we're single-stepping | 17 | * Send SIGTRAP if we're single-stepping |
32 | */ | 18 | */ |
33 | static inline void single_step_trap(struct task_struct *task) | 19 | static inline void single_step_trap(struct task_struct *task) |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ae4027bd01b..4350f75e578 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -28,135 +28,6 @@ | |||
28 | #include <linux/ipc.h> | 28 | #include <linux/ipc.h> |
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | 30 | ||
31 | struct mmap_arg_struct { | ||
32 | unsigned long addr; | ||
33 | unsigned long len; | ||
34 | unsigned long prot; | ||
35 | unsigned long flags; | ||
36 | unsigned long fd; | ||
37 | unsigned long offset; | ||
38 | }; | ||
39 | |||
40 | asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) | ||
41 | { | ||
42 | int error = -EFAULT; | ||
43 | struct mmap_arg_struct a; | ||
44 | |||
45 | if (copy_from_user(&a, arg, sizeof(a))) | ||
46 | goto out; | ||
47 | |||
48 | error = -EINVAL; | ||
49 | if (a.offset & ~PAGE_MASK) | ||
50 | goto out; | ||
51 | |||
52 | error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); | ||
53 | out: | ||
54 | return error; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Perform the select(nd, in, out, ex, tv) and mmap() system | ||
59 | * calls. | ||
60 | */ | ||
61 | |||
62 | struct sel_arg_struct { | ||
63 | unsigned long n; | ||
64 | fd_set __user *inp, *outp, *exp; | ||
65 | struct timeval __user *tvp; | ||
66 | }; | ||
67 | |||
68 | asmlinkage int old_select(struct sel_arg_struct __user *arg) | ||
69 | { | ||
70 | struct sel_arg_struct a; | ||
71 | |||
72 | if (copy_from_user(&a, arg, sizeof(a))) | ||
73 | return -EFAULT; | ||
74 | /* sys_select() does the appropriate kernel locking */ | ||
75 | return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); | ||
76 | } | ||
77 | |||
78 | #if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT) | ||
79 | /* | ||
80 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
81 | * | ||
82 | * This is really horribly ugly. | ||
83 | */ | ||
84 | asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
85 | void __user *ptr, long fifth) | ||
86 | { | ||
87 | int version, ret; | ||
88 | |||
89 | version = call >> 16; /* hack for backward compatibility */ | ||
90 | call &= 0xffff; | ||
91 | |||
92 | switch (call) { | ||
93 | case SEMOP: | ||
94 | return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
95 | case SEMTIMEDOP: | ||
96 | return sys_semtimedop(first, (struct sembuf __user *)ptr, second, | ||
97 | (const struct timespec __user *)fifth); | ||
98 | |||
99 | case SEMGET: | ||
100 | return sys_semget (first, second, third); | ||
101 | case SEMCTL: { | ||
102 | union semun fourth; | ||
103 | if (!ptr) | ||
104 | return -EINVAL; | ||
105 | if (get_user(fourth.__pad, (void __user * __user *) ptr)) | ||
106 | return -EFAULT; | ||
107 | return sys_semctl (first, second, third, fourth); | ||
108 | } | ||
109 | |||
110 | case MSGSND: | ||
111 | return sys_msgsnd(first, (struct msgbuf __user *) ptr, | ||
112 | second, third); | ||
113 | case MSGRCV: | ||
114 | switch (version) { | ||
115 | case 0: { | ||
116 | struct ipc_kludge tmp; | ||
117 | if (!ptr) | ||
118 | return -EINVAL; | ||
119 | if (copy_from_user(&tmp,(struct ipc_kludge __user *)ptr, | ||
120 | sizeof (tmp))) | ||
121 | return -EFAULT; | ||
122 | return sys_msgrcv (first, tmp.msgp, second, | ||
123 | tmp.msgtyp, third); | ||
124 | } | ||
125 | default: | ||
126 | return sys_msgrcv (first, | ||
127 | (struct msgbuf __user *) ptr, | ||
128 | second, fifth, third); | ||
129 | } | ||
130 | case MSGGET: | ||
131 | return sys_msgget ((key_t) first, second); | ||
132 | case MSGCTL: | ||
133 | return sys_msgctl(first, second, (struct msqid_ds __user *)ptr); | ||
134 | |||
135 | case SHMAT: | ||
136 | switch (version) { | ||
137 | default: { | ||
138 | ulong raddr; | ||
139 | ret = do_shmat(first, (char __user *)ptr, second, &raddr); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | return put_user(raddr, (ulong __user *)third); | ||
143 | } | ||
144 | case 1: /* Of course, we don't support iBCS2! */ | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | case SHMDT: | ||
148 | return sys_shmdt ((char __user *)ptr); | ||
149 | case SHMGET: | ||
150 | return sys_shmget (first, second, third); | ||
151 | case SHMCTL: | ||
152 | return sys_shmctl (first, second, | ||
153 | (struct shmid_ds __user *) ptr); | ||
154 | default: | ||
155 | return -ENOSYS; | ||
156 | } | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | /* Fork a new task - this creates a new program thread. | 31 | /* Fork a new task - this creates a new program thread. |
161 | * This is called indirectly via a small wrapper | 32 | * This is called indirectly via a small wrapper |
162 | */ | 33 | */ |
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index d59a0cd537f..33ff678e32f 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -346,9 +346,6 @@ asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, | |||
346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); | 346 | return sys_oabi_semtimedop(semid, tsops, nsops, NULL); |
347 | } | 347 | } |
348 | 348 | ||
349 | extern asmlinkage int sys_ipc(uint call, int first, int second, int third, | ||
350 | void __user *ptr, long fifth); | ||
351 | |||
352 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, | 349 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, |
353 | void __user *ptr, long fifth) | 350 | void __user *ptr, long fifth) |
354 | { | 351 | { |
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 786ac2b6914..50292cd9c12 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c | |||
@@ -359,7 +359,9 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) | |||
359 | frame.fp = regs->ARM_fp; | 359 | frame.fp = regs->ARM_fp; |
360 | frame.sp = regs->ARM_sp; | 360 | frame.sp = regs->ARM_sp; |
361 | frame.lr = regs->ARM_lr; | 361 | frame.lr = regs->ARM_lr; |
362 | frame.pc = regs->ARM_pc; | 362 | /* PC might be corrupted, use LR in that case. */ |
363 | frame.pc = kernel_text_address(regs->ARM_pc) | ||
364 | ? regs->ARM_pc : regs->ARM_lr; | ||
363 | } else if (tsk == current) { | 365 | } else if (tsk == current) { |
364 | frame.fp = (unsigned long)__builtin_frame_address(0); | 366 | frame.fp = (unsigned long)__builtin_frame_address(0); |
365 | frame.sp = current_sp; | 367 | frame.sp = current_sp; |