diff options
Diffstat (limited to 'arch/x86/ia32/ia32_signal.c')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 8dd0903da08b..588a7aa937e1 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -188,6 +188,14 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
188 | /* | 188 | /* |
189 | * Do a signal return; undo the signal stack. | 189 | * Do a signal return; undo the signal stack. |
190 | */ | 190 | */ |
191 | #define loadsegment_gs(v) load_gs_index(v) | ||
192 | #define loadsegment_fs(v) loadsegment(fs, v) | ||
193 | #define loadsegment_ds(v) loadsegment(ds, v) | ||
194 | #define loadsegment_es(v) loadsegment(es, v) | ||
195 | |||
196 | #define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; }) | ||
197 | #define set_user_seg(seg, v) loadsegment_##seg(v) | ||
198 | |||
191 | #define COPY(x) { \ | 199 | #define COPY(x) { \ |
192 | get_user_ex(regs->x, &sc->x); \ | 200 | get_user_ex(regs->x, &sc->x); \ |
193 | } | 201 | } |
@@ -203,19 +211,18 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | |||
203 | } while (0) | 211 | } while (0) |
204 | 212 | ||
205 | #define RELOAD_SEG(seg) { \ | 213 | #define RELOAD_SEG(seg) { \ |
206 | unsigned int cur, pre; \ | 214 | unsigned int pre = GET_SEG(seg); \ |
207 | get_user_ex(pre, &sc->seg); \ | 215 | unsigned int cur = get_user_seg(seg); \ |
208 | savesegment(seg, cur); \ | ||
209 | pre |= 3; \ | 216 | pre |= 3; \ |
210 | if (pre != cur) \ | 217 | if (pre != cur) \ |
211 | loadsegment(seg, pre); \ | 218 | set_user_seg(seg, pre); \ |
212 | } | 219 | } |
213 | 220 | ||
214 | static int ia32_restore_sigcontext(struct pt_regs *regs, | 221 | static int ia32_restore_sigcontext(struct pt_regs *regs, |
215 | struct sigcontext_ia32 __user *sc, | 222 | struct sigcontext_ia32 __user *sc, |
216 | unsigned int *pax) | 223 | unsigned int *pax) |
217 | { | 224 | { |
218 | unsigned int tmpflags, gs, oldgs, err = 0; | 225 | unsigned int tmpflags, err = 0; |
219 | void __user *buf; | 226 | void __user *buf; |
220 | u32 tmp; | 227 | u32 tmp; |
221 | 228 | ||
@@ -229,12 +236,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, | |||
229 | * the handler, but does not clobber them at least in the | 236 | * the handler, but does not clobber them at least in the |
230 | * normal case. | 237 | * normal case. |
231 | */ | 238 | */ |
232 | get_user_ex(gs, &sc->gs); | 239 | RELOAD_SEG(gs); |
233 | gs |= 3; | ||
234 | savesegment(gs, oldgs); | ||
235 | if (gs != oldgs) | ||
236 | load_gs_index(gs); | ||
237 | |||
238 | RELOAD_SEG(fs); | 240 | RELOAD_SEG(fs); |
239 | RELOAD_SEG(ds); | 241 | RELOAD_SEG(ds); |
240 | RELOAD_SEG(es); | 242 | RELOAD_SEG(es); |
@@ -333,17 +335,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, | |||
333 | void __user *fpstate, | 335 | void __user *fpstate, |
334 | struct pt_regs *regs, unsigned int mask) | 336 | struct pt_regs *regs, unsigned int mask) |
335 | { | 337 | { |
336 | int tmp, err = 0; | 338 | int err = 0; |
337 | 339 | ||
338 | put_user_try { | 340 | put_user_try { |
339 | savesegment(gs, tmp); | 341 | put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs); |
340 | put_user_ex(tmp, (unsigned int __user *)&sc->gs); | 342 | put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs); |
341 | savesegment(fs, tmp); | 343 | put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds); |
342 | put_user_ex(tmp, (unsigned int __user *)&sc->fs); | 344 | put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es); |
343 | savesegment(ds, tmp); | ||
344 | put_user_ex(tmp, (unsigned int __user *)&sc->ds); | ||
345 | savesegment(es, tmp); | ||
346 | put_user_ex(tmp, (unsigned int __user *)&sc->es); | ||
347 | 345 | ||
348 | put_user_ex(regs->di, &sc->di); | 346 | put_user_ex(regs->di, &sc->di); |
349 | put_user_ex(regs->si, &sc->si); | 347 | put_user_ex(regs->si, &sc->si); |