diff options
| -rw-r--r-- | arch/x86/kernel/signal_32.c | 38 | ||||
| -rw-r--r-- | arch/x86/kernel/signal_64.c | 18 |
2 files changed, 32 insertions, 24 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index 4337cd510f0a..545448b7aeba 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
| @@ -113,6 +113,27 @@ asmlinkage int sys_sigaltstack(unsigned long bx) | |||
| 113 | return do_sigaltstack(uss, uoss, regs->sp); | 113 | return do_sigaltstack(uss, uoss, regs->sp); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | #define COPY(x) { \ | ||
| 117 | err |= __get_user(regs->x, &sc->x); \ | ||
| 118 | } | ||
| 119 | |||
| 120 | #define COPY_SEG(seg) { \ | ||
| 121 | unsigned short tmp; \ | ||
| 122 | err |= __get_user(tmp, &sc->seg); \ | ||
| 123 | regs->seg = tmp; \ | ||
| 124 | } | ||
| 125 | |||
| 126 | #define COPY_SEG_STRICT(seg) { \ | ||
| 127 | unsigned short tmp; \ | ||
| 128 | err |= __get_user(tmp, &sc->seg); \ | ||
| 129 | regs->seg = tmp | 3; \ | ||
| 130 | } | ||
| 131 | |||
| 132 | #define GET_SEG(seg) { \ | ||
| 133 | unsigned short tmp; \ | ||
| 134 | err |= __get_user(tmp, &sc->seg); \ | ||
| 135 | loadsegment(seg, tmp); \ | ||
| 136 | } | ||
| 116 | 137 | ||
| 117 | /* | 138 | /* |
| 118 | * Do a signal return; undo the signal stack. | 139 | * Do a signal return; undo the signal stack. |
| @@ -126,23 +147,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 126 | /* Always make any pending restarted system calls return -EINTR */ | 147 | /* Always make any pending restarted system calls return -EINTR */ |
| 127 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 148 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 128 | 149 | ||
| 129 | #define COPY(x) err |= __get_user(regs->x, &sc->x) | ||
| 130 | |||
| 131 | #define COPY_SEG(seg) \ | ||
| 132 | { unsigned short tmp; \ | ||
| 133 | err |= __get_user(tmp, &sc->seg); \ | ||
| 134 | regs->seg = tmp; } | ||
| 135 | |||
| 136 | #define COPY_SEG_STRICT(seg) \ | ||
| 137 | { unsigned short tmp; \ | ||
| 138 | err |= __get_user(tmp, &sc->seg); \ | ||
| 139 | regs->seg = tmp|3; } | ||
| 140 | |||
| 141 | #define GET_SEG(seg) \ | ||
| 142 | { unsigned short tmp; \ | ||
| 143 | err |= __get_user(tmp, &sc->seg); \ | ||
| 144 | loadsegment(seg, tmp); } | ||
| 145 | |||
| 146 | GET_SEG(gs); | 150 | GET_SEG(gs); |
| 147 | COPY_SEG(fs); | 151 | COPY_SEG(fs); |
| 148 | COPY_SEG(es); | 152 | COPY_SEG(es); |
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 53f86d95985b..feff4a91d095 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
| @@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
| 52 | return do_sigaltstack(uss, uoss, regs->sp); | 52 | return do_sigaltstack(uss, uoss, regs->sp); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | #define COPY(x) { \ | ||
| 56 | err |= __get_user(regs->x, &sc->x); \ | ||
| 57 | } | ||
| 58 | |||
| 59 | #define COPY_SEG_STRICT(seg) { \ | ||
| 60 | unsigned short tmp; \ | ||
| 61 | err |= __get_user(tmp, &sc->seg); \ | ||
| 62 | regs->seg = tmp | 3; \ | ||
| 63 | } | ||
| 64 | |||
| 55 | /* | 65 | /* |
| 56 | * Do a signal return; undo the signal stack. | 66 | * Do a signal return; undo the signal stack. |
| 57 | */ | 67 | */ |
| @@ -64,8 +74,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 64 | /* Always make any pending restarted system calls return -EINTR */ | 74 | /* Always make any pending restarted system calls return -EINTR */ |
| 65 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 75 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
| 66 | 76 | ||
| 67 | #define COPY(x) (err |= __get_user(regs->x, &sc->x)) | ||
| 68 | |||
| 69 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); | 77 | COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); |
| 70 | COPY(dx); COPY(cx); COPY(ip); | 78 | COPY(dx); COPY(cx); COPY(ip); |
| 71 | COPY(r8); | 79 | COPY(r8); |
| @@ -80,11 +88,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, | |||
| 80 | /* Kernel saves and restores only the CS segment register on signals, | 88 | /* Kernel saves and restores only the CS segment register on signals, |
| 81 | * which is the bare minimum needed to allow mixed 32/64-bit code. | 89 | * which is the bare minimum needed to allow mixed 32/64-bit code. |
| 82 | * App's signal handler can save/restore other segments if needed. */ | 90 | * App's signal handler can save/restore other segments if needed. */ |
| 83 | { | 91 | COPY_SEG_STRICT(cs); |
| 84 | unsigned cs; | ||
| 85 | err |= __get_user(cs, &sc->cs); | ||
| 86 | regs->cs = cs | 3; /* Force into user mode */ | ||
| 87 | } | ||
| 88 | 92 | ||
| 89 | { | 93 | { |
| 90 | unsigned int tmpflags; | 94 | unsigned int tmpflags; |
