Blame view

arch/x86/kernel/signal.c 20.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *  Copyright (C) 1991, 1992  Linus Torvalds
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
3
   *  Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
   *
   *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
   *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
7
   *  2000-2002   x86-64 support by Andi Kleen
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   */
5c9b3a0c7   Hiroshi Shimamoto   x86: signal: cosm...
9
10
11
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/smp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
  #include <linux/kernel.h>
  #include <linux/signal.h>
  #include <linux/errno.h>
  #include <linux/wait.h>
5c9b3a0c7   Hiroshi Shimamoto   x86: signal: cosm...
16
  #include <linux/ptrace.h>
36a033082   Roland McGrath   x86: tracehook_si...
17
  #include <linux/tracehook.h>
5c9b3a0c7   Hiroshi Shimamoto   x86: signal: cosm...
18
19
20
21
  #include <linux/unistd.h>
  #include <linux/stddef.h>
  #include <linux/personality.h>
  #include <linux/uaccess.h>
7c68af6e3   Avi Kivity   core, x86: Add us...
22
  #include <linux/user-return-notifier.h>
7e907f489   Ingo Molnar   x86: clean up arc...
23

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <asm/processor.h>
  #include <asm/ucontext.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <asm/i387.h>
6c3652efc   Roland McGrath   x86 vDSO: i386 vd...
27
  #include <asm/vdso.h>
4efc0670b   Andi Kleen   x86, mce: use 64b...
28
  #include <asm/mce.h>
5c9b3a0c7   Hiroshi Shimamoto   x86: signal: cosm...
29
30
31
32
  
  #ifdef CONFIG_X86_64
  #include <asm/proto.h>
  #include <asm/ia32_unistd.h>
5c9b3a0c7   Hiroshi Shimamoto   x86: signal: cosm...
33
  #endif /* CONFIG_X86_64 */
bb57925f5   Hiroshi Shimamoto   x86_32: signal: u...
34
  #include <asm/syscall.h>
bbc1f698a   Jaswinder Singh   x86: Introducing ...
35
  #include <asm/syscalls.h>
7e907f489   Ingo Molnar   x86: clean up arc...
36

41af86fad   Hiroshi Shimamoto   x86: signal: move...
37
  #include <asm/sigframe.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
1a1768039   Harvey Harrison   x86: Use FIX_EFLA...
40
41
42
43
44
45
46
47
48
49
  #define __FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \
  			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
  			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
  			 X86_EFLAGS_CF)
  
  #ifdef CONFIG_X86_32
  # define FIX_EFLAGS	(__FIX_EFLAGS | X86_EFLAGS_RF)
  #else
  # define FIX_EFLAGS	__FIX_EFLAGS
  #endif
d9a89a26e   Tejun Heo   x86: add %gs acce...
50
51
52
  #define COPY(x)			do {			\
  	get_user_ex(regs->x, &sc->x);			\
  } while (0)
2601657d2   Hiroshi Shimamoto   x86: signal: move...
53

d9a89a26e   Tejun Heo   x86: add %gs acce...
54
55
56
57
58
  #define GET_SEG(seg)		({			\
  	unsigned short tmp;				\
  	get_user_ex(tmp, &sc->seg);			\
  	tmp;						\
  })
2601657d2   Hiroshi Shimamoto   x86: signal: move...
59

d9a89a26e   Tejun Heo   x86: add %gs acce...
60
61
62
  #define COPY_SEG(seg)		do {			\
  	regs->seg = GET_SEG(seg);			\
  } while (0)
2601657d2   Hiroshi Shimamoto   x86: signal: move...
63

d9a89a26e   Tejun Heo   x86: add %gs acce...
64
65
66
  #define COPY_SEG_CPL3(seg)	do {			\
  	regs->seg = GET_SEG(seg) | 3;			\
  } while (0)
2601657d2   Hiroshi Shimamoto   x86: signal: move...
67
68
69
70
71
72
73
74
75
76
77
  
  static int
  restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
  		   unsigned long *pax)
  {
  	void __user *buf;
  	unsigned int tmpflags;
  	unsigned int err = 0;
  
  	/* Always make any pending restarted system calls return -EINTR */
  	current_thread_info()->restart_block.fn = do_no_restart_syscall;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
78
  	get_user_try {
2601657d2   Hiroshi Shimamoto   x86: signal: move...
79
  #ifdef CONFIG_X86_32
d9a89a26e   Tejun Heo   x86: add %gs acce...
80
  		set_user_gs(regs, GET_SEG(gs));
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
81
82
83
  		COPY_SEG(fs);
  		COPY_SEG(es);
  		COPY_SEG(ds);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
84
  #endif /* CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
85
86
  		COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
  		COPY(dx); COPY(cx); COPY(ip);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
87
88
  
  #ifdef CONFIG_X86_64
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
89
90
91
92
93
94
95
96
  		COPY(r8);
  		COPY(r9);
  		COPY(r10);
  		COPY(r11);
  		COPY(r12);
  		COPY(r13);
  		COPY(r14);
  		COPY(r15);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
97
98
99
  #endif /* CONFIG_X86_64 */
  
  #ifdef CONFIG_X86_32
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
100
101
  		COPY_SEG_CPL3(cs);
  		COPY_SEG_CPL3(ss);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
102
  #else /* !CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
103
104
105
106
  		/* Kernel saves and restores only the CS segment register on signals,
  		 * which is the bare minimum needed to allow mixed 32/64-bit code.
  		 * App's signal handler can save/restore other segments if needed. */
  		COPY_SEG_CPL3(cs);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
107
  #endif /* CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
108
109
110
111
112
113
  		get_user_ex(tmpflags, &sc->flags);
  		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
  		regs->orig_ax = -1;		/* disable syscall checks */
  
  		get_user_ex(buf, &sc->fpstate);
  		err |= restore_i387_xstate(buf);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
114

98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
115
116
  		get_user_ex(*pax, &sc->ax);
  	} get_user_catch(err);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
117

2601657d2   Hiroshi Shimamoto   x86: signal: move...
118
119
120
121
122
123
124
125
  	return err;
  }
  
  static int
  setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
  		 struct pt_regs *regs, unsigned long mask)
  {
  	int err = 0;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
126
  	put_user_try {
2601657d2   Hiroshi Shimamoto   x86: signal: move...
127

98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
128
  #ifdef CONFIG_X86_32
d9a89a26e   Tejun Heo   x86: add %gs acce...
129
  		put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs);
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
130
131
132
  		put_user_ex(regs->fs, (unsigned int __user *)&sc->fs);
  		put_user_ex(regs->es, (unsigned int __user *)&sc->es);
  		put_user_ex(regs->ds, (unsigned int __user *)&sc->ds);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
133
  #endif /* CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
134
135
136
137
138
139
140
141
  		put_user_ex(regs->di, &sc->di);
  		put_user_ex(regs->si, &sc->si);
  		put_user_ex(regs->bp, &sc->bp);
  		put_user_ex(regs->sp, &sc->sp);
  		put_user_ex(regs->bx, &sc->bx);
  		put_user_ex(regs->dx, &sc->dx);
  		put_user_ex(regs->cx, &sc->cx);
  		put_user_ex(regs->ax, &sc->ax);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
142
  #ifdef CONFIG_X86_64
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
143
144
145
146
147
148
149
150
  		put_user_ex(regs->r8, &sc->r8);
  		put_user_ex(regs->r9, &sc->r9);
  		put_user_ex(regs->r10, &sc->r10);
  		put_user_ex(regs->r11, &sc->r11);
  		put_user_ex(regs->r12, &sc->r12);
  		put_user_ex(regs->r13, &sc->r13);
  		put_user_ex(regs->r14, &sc->r14);
  		put_user_ex(regs->r15, &sc->r15);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
151
  #endif /* CONFIG_X86_64 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
152
153
154
  		put_user_ex(current->thread.trap_no, &sc->trapno);
  		put_user_ex(current->thread.error_code, &sc->err);
  		put_user_ex(regs->ip, &sc->ip);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
155
  #ifdef CONFIG_X86_32
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
156
157
158
159
  		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
  		put_user_ex(regs->flags, &sc->flags);
  		put_user_ex(regs->sp, &sc->sp_at_signal);
  		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
160
  #else /* !CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
161
162
163
164
  		put_user_ex(regs->flags, &sc->flags);
  		put_user_ex(regs->cs, &sc->cs);
  		put_user_ex(0, &sc->gs);
  		put_user_ex(0, &sc->fs);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
165
  #endif /* CONFIG_X86_32 */
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
166
  		put_user_ex(fpstate, &sc->fpstate);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
167

98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
168
169
170
171
  		/* non-iBCS2 extensions.. */
  		put_user_ex(mask, &sc->oldmask);
  		put_user_ex(current->thread.cr2, &sc->cr2);
  	} put_user_catch(err);
2601657d2   Hiroshi Shimamoto   x86: signal: move...
172
173
174
  
  	return err;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  /*
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
176
   * Set up a signal frame.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
  
  /*
   * Determine which stack to use..
   */
1fae0279c   Hiroshi Shimamoto   x86: signal: intr...
182
183
184
185
186
187
188
189
190
191
192
193
194
  static unsigned long align_sigframe(unsigned long sp)
  {
  #ifdef CONFIG_X86_32
  	/*
  	 * Align the stack pointer according to the i386 ABI,
  	 * i.e. so that on function entry ((sp + 4) & 15) == 0.
  	 */
  	sp = ((sp + 4) & -16ul) - 4;
  #else /* !CONFIG_X86_32 */
  	sp = round_down(sp, 16) - 8;
  #endif
  	return sp;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  static inline void __user *
3c1c7f101   Suresh Siddha   x86, xsave: dynam...
196
  get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
144b0712d   Hiroshi Shimamoto   x86: signal: add ...
197
  	     void __user **fpstate)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  	/* Default to using normal stack */
75779f052   Hiroshi Shimamoto   x86: signal: unif...
200
  	unsigned long sp = regs->sp;
14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
201
  	int onsigstack = on_sig_stack(sp);
75779f052   Hiroshi Shimamoto   x86: signal: unif...
202
203
204
205
206
  
  #ifdef CONFIG_X86_64
  	/* redzone */
  	sp -= 128;
  #endif /* CONFIG_X86_64 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207

14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
208
209
210
  	if (!onsigstack) {
  		/* This is the X/Open sanctioned signal stack switching.  */
  		if (ka->sa.sa_flags & SA_ONSTACK) {
0f8f30892   Hiroshi Shimamoto   x86: signal: chec...
211
  			if (current->sas_ss_size)
14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
212
213
  				sp = current->sas_ss_sp + current->sas_ss_size;
  		} else {
75779f052   Hiroshi Shimamoto   x86: signal: unif...
214
  #ifdef CONFIG_X86_32
14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
215
216
217
218
219
  			/* This is the legacy signal stack switching. */
  			if ((regs->ss & 0xffff) != __USER_DS &&
  				!(ka->sa.sa_flags & SA_RESTORER) &&
  					ka->sa.sa_restorer)
  				sp = (unsigned long) ka->sa.sa_restorer;
75779f052   Hiroshi Shimamoto   x86: signal: unif...
220
  #endif /* CONFIG_X86_32 */
14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
221
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	}
3c1c7f101   Suresh Siddha   x86, xsave: dynam...
223
  	if (used_math()) {
75779f052   Hiroshi Shimamoto   x86: signal: unif...
224
  		sp -= sig_xstate_size;
250517021   Hiroshi Shimamoto   x86, signals: fix...
225
226
227
228
  #ifdef CONFIG_X86_64
  		sp = round_down(sp, 64);
  #endif /* CONFIG_X86_64 */
  		*fpstate = (void __user *)sp;
3c1c7f101   Suresh Siddha   x86, xsave: dynam...
229
  	}
14fc9fbc7   Hiroshi Shimamoto   x86: signal: chec...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  	sp = align_sigframe(sp - frame_size);
  
  	/*
  	 * If we are on the alternate signal stack and would overflow it, don't.
  	 * Return an always-bogus address instead so we will die with SIGSEGV.
  	 */
  	if (onsigstack && !likely(on_sig_stack(sp)))
  		return (void __user *)-1L;
  
  	/* save i387 state */
  	if (used_math() && save_i387_xstate(*fpstate) < 0)
  		return (void __user *)-1L;
  
  	return (void __user *)sp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  }
75779f052   Hiroshi Shimamoto   x86: signal: unif...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  #ifdef CONFIG_X86_32
  static const struct {
  	u16 poplmovl;
  	u32 val;
  	u16 int80;
  } __attribute__((packed)) retcode = {
  	0xb858,		/* popl %eax; movl $..., %eax */
  	__NR_sigreturn,
  	0x80cd,		/* int $0x80 */
  };
  
  static const struct {
  	u8  movl;
  	u32 val;
  	u16 int80;
  	u8  pad;
  } __attribute__((packed)) rt_retcode = {
  	0xb8,		/* movl $..., %eax */
  	__NR_rt_sigreturn,
  	0x80cd,		/* int $0x80 */
  	0
  };
7e907f489   Ingo Molnar   x86: clean up arc...
267
  static int
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
268
269
  __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
  	      struct pt_regs *regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  	struct sigframe __user *frame;
7e907f489   Ingo Molnar   x86: clean up arc...
272
  	void __user *restorer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  	int err = 0;
ab5137015   Suresh Siddha   x86, xsave: reorg...
274
  	void __user *fpstate = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

3c1c7f101   Suresh Siddha   x86, xsave: dynam...
276
  	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
  
  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
279
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280

2ba48e16e   Hiroshi Shimamoto   x86: signal: remo...
281
  	if (__put_user(sig, &frame->sig))
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
282
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

2ba48e16e   Hiroshi Shimamoto   x86: signal: remo...
284
  	if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
285
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
  
  	if (_NSIG_WORDS > 1) {
2ba48e16e   Hiroshi Shimamoto   x86: signal: remo...
288
289
  		if (__copy_to_user(&frame->extramask, &set->sig[1],
  				   sizeof(frame->extramask)))
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
290
  			return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
  	}
1a3e4ca41   Roland McGrath   x86 vDSO: don't u...
292
  	if (current->mm->context.vdso)
6c3652efc   Roland McGrath   x86 vDSO: i386 vd...
293
  		restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
9fbbd4dd1   Andi Kleen   [PATCH] x86: Don'...
294
  	else
ade1af771   Jan Engelhardt   x86: remove unned...
295
  		restorer = &frame->retcode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
  	if (ka->sa.sa_flags & SA_RESTORER)
  		restorer = ka->sa.sa_restorer;
  
  	/* Set up to return from userspace.  */
  	err |= __put_user(restorer, &frame->pretcode);
7e907f489   Ingo Molnar   x86: clean up arc...
301

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
  	/*
7e907f489   Ingo Molnar   x86: clean up arc...
303
  	 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
  	 *
  	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
  	 * reasons and because gdb uses it as a signature to notice
  	 * signal handler stack frames.
  	 */
4a6120485   Hiroshi Shimamoto   x86: signal_32: i...
309
  	err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  
  	if (err)
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
312
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  
  	/* Set up registers for signal handler */
7e907f489   Ingo Molnar   x86: clean up arc...
315
316
317
  	regs->sp = (unsigned long)frame;
  	regs->ip = (unsigned long)ka->sa.sa_handler;
  	regs->ax = (unsigned long)sig;
92bc20568   Harvey Harrison   x86: change most ...
318
319
  	regs->dx = 0;
  	regs->cx = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

65ea5b034   H. Peter Anvin   x86: rename the s...
321
322
323
324
  	regs->ds = __USER_DS;
  	regs->es = __USER_DS;
  	regs->ss = __USER_DS;
  	regs->cs = __USER_CS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325

283828f3c   David Howells   [PATCH] Handle TI...
326
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  }
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
328
329
  static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  			    sigset_t *set, struct pt_regs *regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  	struct rt_sigframe __user *frame;
7e907f489   Ingo Molnar   x86: clean up arc...
332
  	void __user *restorer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	int err = 0;
ab5137015   Suresh Siddha   x86, xsave: reorg...
334
  	void __user *fpstate = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335

3c1c7f101   Suresh Siddha   x86, xsave: dynam...
336
  	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
  
  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
339
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340

98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  	put_user_try {
  		put_user_ex(sig, &frame->sig);
  		put_user_ex(&frame->info, &frame->pinfo);
  		put_user_ex(&frame->uc, &frame->puc);
  		err |= copy_siginfo_to_user(&frame->info, info);
  
  		/* Create the ucontext.  */
  		if (cpu_has_xsave)
  			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
  		else
  			put_user_ex(0, &frame->uc.uc_flags);
  		put_user_ex(0, &frame->uc.uc_link);
  		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
  		put_user_ex(sas_ss_flags(regs->sp),
  			    &frame->uc.uc_stack.ss_flags);
  		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
  		err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
  					regs, set->sig[0]);
  		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  
  		/* Set up to return from userspace.  */
  		restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
  		if (ka->sa.sa_flags & SA_RESTORER)
  			restorer = ka->sa.sa_restorer;
  		put_user_ex(restorer, &frame->pretcode);
  
  		/*
  		 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
  		 *
  		 * WE DO NOT USE IT ANY MORE! It's only left here for historical
  		 * reasons and because gdb uses it as a signature to notice
  		 * signal handler stack frames.
  		 */
  		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
  	} put_user_catch(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  
  	if (err)
3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
378
  		return -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
  
  	/* Set up registers for signal handler */
7e907f489   Ingo Molnar   x86: clean up arc...
381
382
  	regs->sp = (unsigned long)frame;
  	regs->ip = (unsigned long)ka->sa.sa_handler;
13ad7725e   Hiroshi Shimamoto   x86_32: signal: m...
383
  	regs->ax = (unsigned long)sig;
7e907f489   Ingo Molnar   x86: clean up arc...
384
385
  	regs->dx = (unsigned long)&frame->info;
  	regs->cx = (unsigned long)&frame->uc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

65ea5b034   H. Peter Anvin   x86: rename the s...
387
388
389
390
  	regs->ds = __USER_DS;
  	regs->es = __USER_DS;
  	regs->ss = __USER_DS;
  	regs->cs = __USER_CS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391

283828f3c   David Howells   [PATCH] Handle TI...
392
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  }
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
394
  #else /* !CONFIG_X86_32 */
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
395
396
397
398
399
400
401
  static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  			    sigset_t *set, struct pt_regs *regs)
  {
  	struct rt_sigframe __user *frame;
  	void __user *fp = NULL;
  	int err = 0;
  	struct task_struct *me = current;
97286a2b6   Hiroshi Shimamoto   x86: signal: intr...
402
  	frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe), &fp);
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
403
404
405
406
407
408
409
410
  
  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
  		return -EFAULT;
  
  	if (ka->sa.sa_flags & SA_SIGINFO) {
  		if (copy_siginfo_to_user(&frame->info, info))
  			return -EFAULT;
  	}
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  	put_user_try {
  		/* Create the ucontext.  */
  		if (cpu_has_xsave)
  			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
  		else
  			put_user_ex(0, &frame->uc.uc_flags);
  		put_user_ex(0, &frame->uc.uc_link);
  		put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
  		put_user_ex(sas_ss_flags(regs->sp),
  			    &frame->uc.uc_stack.ss_flags);
  		put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
  		err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
  		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  
  		/* Set up to return from userspace.  If provided, use a stub
  		   already in userspace.  */
  		/* x86-64 should always use SA_RESTORER. */
  		if (ka->sa.sa_flags & SA_RESTORER) {
  			put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
  		} else {
  			/* could use a vstub here */
  			err |= -EFAULT;
  		}
  	} put_user_catch(err);
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  
  	if (err)
  		return -EFAULT;
  
  	/* Set up registers for signal handler */
  	regs->di = sig;
  	/* In case the signal handler was declared without prototypes */
  	regs->ax = 0;
  
  	/* This also works for non SA_SIGINFO handlers because they expect the
  	   next argument after the signal number on the stack. */
  	regs->si = (unsigned long)&frame->info;
  	regs->dx = (unsigned long)&frame->uc;
  	regs->ip = (unsigned long) ka->sa.sa_handler;
  
  	regs->sp = (unsigned long)frame;
  
  	/* Set up the CS register to run signal handlers in 64-bit mode,
  	   even if the handler happens to be interrupting 32-bit code. */
  	regs->cs = __USER_CS;
  
  	return 0;
  }
  #endif /* CONFIG_X86_32 */
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
459
  #ifdef CONFIG_X86_32
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
460
461
462
463
464
465
  /*
   * Atomically swap in the new signal mask, and wait for a signal.
   */
  asmlinkage int
  sys_sigsuspend(int history0, int history1, old_sigset_t mask)
  {
3982294b0   Oleg Nesterov   x86, signals: Con...
466
  	sigset_t blocked;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
467
  	current->saved_sigmask = current->blocked;
3982294b0   Oleg Nesterov   x86, signals: Con...
468
469
470
471
  
  	mask &= _BLOCKABLE;
  	siginitset(&blocked, mask);
  	set_current_blocked(&blocked);
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
472
473
474
  
  	current->state = TASK_INTERRUPTIBLE;
  	schedule();
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
475

3982294b0   Oleg Nesterov   x86, signals: Con...
476
  	set_restore_sigmask();
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
477
478
479
480
481
482
483
484
  	return -ERESTARTNOHAND;
  }
  
  asmlinkage int
  sys_sigaction(int sig, const struct old_sigaction __user *act,
  	      struct old_sigaction __user *oact)
  {
  	struct k_sigaction new_ka, old_ka;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
485
  	int ret = 0;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
486
487
488
  
  	if (act) {
  		old_sigset_t mask;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
489
  		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
490
  			return -EFAULT;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
491
492
493
494
495
496
497
498
499
  		get_user_try {
  			get_user_ex(new_ka.sa.sa_handler, &act->sa_handler);
  			get_user_ex(new_ka.sa.sa_flags, &act->sa_flags);
  			get_user_ex(mask, &act->sa_mask);
  			get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer);
  		} get_user_catch(ret);
  
  		if (ret)
  			return -EFAULT;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
500
501
502
503
504
505
  		siginitset(&new_ka.sa.sa_mask, mask);
  	}
  
  	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  
  	if (!ret && oact) {
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
506
  		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
507
  			return -EFAULT;
98e3d45ed   Hiroshi Shimamoto   x86: signal: use ...
508
509
510
511
512
513
514
515
516
  		put_user_try {
  			put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler);
  			put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags);
  			put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
  			put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer);
  		} put_user_catch(ret);
  
  		if (ret)
  			return -EFAULT;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
517
518
519
520
  	}
  
  	return ret;
  }
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
521
  #endif /* CONFIG_X86_32 */
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
522

052acad48   Brian Gerst   x86: Merge sys_si...
523
  long
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
524
525
526
527
528
  sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
  		struct pt_regs *regs)
  {
  	return do_sigaltstack(uss, uoss, regs->sp);
  }
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
529
530
531
532
  
  /*
   * Do a signal return; undo the signal stack.
   */
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
533
  #ifdef CONFIG_X86_32
b12bdaf11   Brian Gerst   x86: use regparm(...
534
  unsigned long sys_sigreturn(struct pt_regs *regs)
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
535
536
  {
  	struct sigframe __user *frame;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
537
538
  	unsigned long ax;
  	sigset_t set;
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
539
540
541
542
543
544
545
546
547
548
  	frame = (struct sigframe __user *)(regs->sp - 8);
  
  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
  		goto badframe;
  	if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
  		&& __copy_from_user(&set.sig[1], &frame->extramask,
  				    sizeof(frame->extramask))))
  		goto badframe;
  
  	sigdelsetmask(&set, ~_BLOCKABLE);
3982294b0   Oleg Nesterov   x86, signals: Con...
549
  	set_current_blocked(&set);
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
550
551
552
553
554
555
  
  	if (restore_sigcontext(regs, &frame->sc, &ax))
  		goto badframe;
  	return ax;
  
  badframe:
ae417bb48   Hiroshi Shimamoto   x86: signal: use ...
556
  	signal_fault(regs, frame, "sigreturn");
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
557
558
559
  
  	return 0;
  }
e5fa2d063   Hiroshi Shimamoto   x86: signal: unif...
560
  #endif /* CONFIG_X86_32 */
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
561

744525092   H. Peter Anvin   x86: merge sys_rt...
562
  long sys_rt_sigreturn(struct pt_regs *regs)
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
563
564
565
566
567
568
569
570
571
572
573
574
  {
  	struct rt_sigframe __user *frame;
  	unsigned long ax;
  	sigset_t set;
  
  	frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
  	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
  		goto badframe;
  	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  		goto badframe;
  
  	sigdelsetmask(&set, ~_BLOCKABLE);
e9bd3f0fa   Oleg Nesterov   x86: signal: sys_...
575
  	set_current_blocked(&set);
bfeb91a94   Hiroshi Shimamoto   x86: signal: cosm...
576
577
578
579
580
581
582
583
584
585
586
587
588
  
  	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
  		goto badframe;
  
  	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
  		goto badframe;
  
  	return ax;
  
  badframe:
  	signal_fault(regs, frame, "rt_sigreturn");
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  /*
7e907f489   Ingo Molnar   x86: clean up arc...
590
591
   * OK, we're invoking a handler:
   */
8d8c13bdb   Hiroshi Shimamoto   x86: signal_32.c:...
592
593
  static int signr_convert(int sig)
  {
96bf84b71   Hiroshi Shimamoto   x86: signal: cosm...
594
  #ifdef CONFIG_X86_32
8d8c13bdb   Hiroshi Shimamoto   x86: signal_32.c:...
595
596
597
598
  	struct thread_info *info = current_thread_info();
  
  	if (info->exec_domain && info->exec_domain->signal_invmap && sig < 32)
  		return info->exec_domain->signal_invmap[sig];
96bf84b71   Hiroshi Shimamoto   x86: signal: cosm...
599
  #endif /* CONFIG_X86_32 */
8d8c13bdb   Hiroshi Shimamoto   x86: signal_32.c:...
600
601
  	return sig;
  }
cabf50358   Hiroshi Shimamoto   x86: signal: cosm...
602
  #ifdef CONFIG_X86_32
455edbc42   Hiroshi Shimamoto   x86: signal: intr...
603
  #define is_ia32	1
4694d2391   Hiroshi Shimamoto   x86: signal_32.c:...
604
605
  #define ia32_setup_frame	__setup_frame
  #define ia32_setup_rt_frame	__setup_rt_frame
455edbc42   Hiroshi Shimamoto   x86: signal: intr...
606

cabf50358   Hiroshi Shimamoto   x86: signal: cosm...
607
608
609
610
611
612
613
  #else /* !CONFIG_X86_32 */
  
  #ifdef CONFIG_IA32_EMULATION
  #define is_ia32	test_thread_flag(TIF_IA32)
  #else /* !CONFIG_IA32_EMULATION */
  #define is_ia32	0
  #endif /* CONFIG_IA32_EMULATION */
f5223763a   Hiroshi Shimamoto   x86: signal: move...
614
615
616
617
  int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  		sigset_t *set, struct pt_regs *regs);
  int ia32_setup_frame(int sig, struct k_sigaction *ka,
  		sigset_t *set, struct pt_regs *regs);
cabf50358   Hiroshi Shimamoto   x86: signal: cosm...
618
  #endif /* CONFIG_X86_32 */
7c1def165   Roland McGrath   [PATCH] i386: nev...
619
  static int
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
620
  setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
9b4296207   Oleg Nesterov   x86, do_signal: S...
621
  		struct pt_regs *regs)
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
622
  {
8d8c13bdb   Hiroshi Shimamoto   x86: signal_32.c:...
623
  	int usig = signr_convert(sig);
9b4296207   Oleg Nesterov   x86, do_signal: S...
624
  	sigset_t *set = &current->blocked;
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
625
  	int ret;
9b4296207   Oleg Nesterov   x86, do_signal: S...
626
627
  	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
  		set = &current->saved_sigmask;
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
628
  	/* Set up the stack frame */
455edbc42   Hiroshi Shimamoto   x86: signal: intr...
629
630
  	if (is_ia32) {
  		if (ka->sa.sa_flags & SA_SIGINFO)
4694d2391   Hiroshi Shimamoto   x86: signal_32.c:...
631
  			ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
455edbc42   Hiroshi Shimamoto   x86: signal: intr...
632
  		else
4694d2391   Hiroshi Shimamoto   x86: signal_32.c:...
633
  			ret = ia32_setup_frame(usig, ka, set, regs);
455edbc42   Hiroshi Shimamoto   x86: signal: intr...
634
635
  	} else
  		ret = __setup_rt_frame(sig, ka, info, set, regs);
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
636

3d0aedd95   Hiroshi Shimamoto   x86: signal: put ...
637
638
639
640
  	if (ret) {
  		force_sigsegv(sig, current);
  		return -EFAULT;
  	}
9b4296207   Oleg Nesterov   x86, do_signal: S...
641
  	current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
1d13024e6   Hiroshi Shimamoto   x86: signal: spli...
642
643
644
645
  	return ret;
  }
  
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
9b4296207   Oleg Nesterov   x86, do_signal: S...
647
  		struct pt_regs *regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  {
7c1def165   Roland McGrath   [PATCH] i386: nev...
649
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  	/* Are we from a system call? */
bb57925f5   Hiroshi Shimamoto   x86_32: signal: u...
651
  	if (syscall_get_nr(current, regs) >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  		/* If so, check system call restarting.. */
bb57925f5   Hiroshi Shimamoto   x86_32: signal: u...
653
  		switch (syscall_get_error(current, regs)) {
ac66f3fd8   Harvey Harrison   x86: reduce trivi...
654
655
656
657
658
659
660
  		case -ERESTART_RESTARTBLOCK:
  		case -ERESTARTNOHAND:
  			regs->ax = -EINTR;
  			break;
  
  		case -ERESTARTSYS:
  			if (!(ka->sa.sa_flags & SA_RESTART)) {
65ea5b034   H. Peter Anvin   x86: rename the s...
661
  				regs->ax = -EINTR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  				break;
ac66f3fd8   Harvey Harrison   x86: reduce trivi...
663
664
665
666
667
668
  			}
  		/* fallthrough */
  		case -ERESTARTNOINTR:
  			regs->ax = regs->orig_ax;
  			regs->ip -= 2;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
  		}
  	}
  
  	/*
e1f287735   Roland McGrath   x86 single_step: ...
673
674
  	 * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF
  	 * flag so that register information in the sigcontext is correct.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  	 */
65ea5b034   H. Peter Anvin   x86: rename the s...
676
  	if (unlikely(regs->flags & X86_EFLAGS_TF) &&
e1f287735   Roland McGrath   x86 single_step: ...
677
  	    likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
65ea5b034   H. Peter Anvin   x86: rename the s...
678
  		regs->flags &= ~X86_EFLAGS_TF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

9b4296207   Oleg Nesterov   x86, do_signal: S...
680
  	ret = setup_rt_frame(sig, ka, info, regs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681

7e907f489   Ingo Molnar   x86: clean up arc...
682
683
  	if (ret)
  		return ret;
7c1def165   Roland McGrath   [PATCH] i386: nev...
684

8b9c5ff38   Roland McGrath   x86 signals: lift...
685
686
687
688
689
690
691
692
693
694
695
696
  	/*
  	 * Clear the direction flag as per the ABI for function entry.
  	 */
  	regs->flags &= ~X86_EFLAGS_DF;
  
  	/*
  	 * Clear TF when entering the signal handler, but
  	 * notify any tracer that was single-stepping it.
  	 * The tracer may want to single-step inside the
  	 * handler too.
  	 */
  	regs->flags &= ~X86_EFLAGS_TF;
8b9c5ff38   Roland McGrath   x86 signals: lift...
697

5e6292c0f   Matt Fleming   signal: add block...
698
  	block_sigmask(ka, sig);
7e907f489   Ingo Molnar   x86: clean up arc...
699

36a033082   Roland McGrath   x86: tracehook_si...
700
701
  	tracehook_signal_handler(sig, info, ka, regs,
  				 test_thread_flag(TIF_SINGLESTEP));
7e907f489   Ingo Molnar   x86: clean up arc...
702
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
  }
57917752f   Hiroshi Shimamoto   x86: signal: cosm...
704
  #ifdef CONFIG_X86_32
8fcd8e20f   Hiroshi Shimamoto   x86: signal: make...
705
  #define NR_restart_syscall	__NR_restart_syscall
57917752f   Hiroshi Shimamoto   x86: signal: cosm...
706
707
708
709
  #else /* !CONFIG_X86_32 */
  #define NR_restart_syscall	\
  	test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : __NR_restart_syscall
  #endif /* CONFIG_X86_32 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
714
  /*
   * Note that 'init' is a special process: it doesn't get signals it doesn't
   * want to handle. Thus you cannot kill init even with a SIGKILL even by
   * mistake.
   */
75604d7f7   Harvey Harrison   x86: remove all d...
715
  static void do_signal(struct pt_regs *regs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  {
ac66f3fd8   Harvey Harrison   x86: reduce trivi...
717
  	struct k_sigaction ka;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
719
  	siginfo_t info;
  	int signr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
  
  	/*
ac66f3fd8   Harvey Harrison   x86: reduce trivi...
722
723
724
725
726
  	 * We want the common case to go fast, which is why we may in certain
  	 * cases get here from kernel mode. Just return without doing anything
  	 * if so.
  	 * X86_32: vm86 regs switched out by assembly code before reaching
  	 * here, so testing against kernel CS suffices.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
  	 */
717b594a4   Vincent Hanquez   [PATCH] xen: x86:...
728
  	if (!user_mode(regs))
283828f3c   David Howells   [PATCH] Handle TI...
729
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
  	if (signr > 0) {
7e907f489   Ingo Molnar   x86: clean up arc...
733
  		/* Whee! Actually deliver the signal.  */
9b4296207   Oleg Nesterov   x86, do_signal: S...
734
  		handle_signal(signr, &info, &ka, regs);
283828f3c   David Howells   [PATCH] Handle TI...
735
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
  	/* Did we come from a system call? */
bb57925f5   Hiroshi Shimamoto   x86_32: signal: u...
738
  	if (syscall_get_nr(current, regs) >= 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  		/* Restart the system call - no handlers present */
bb57925f5   Hiroshi Shimamoto   x86_32: signal: u...
740
  		switch (syscall_get_error(current, regs)) {
283828f3c   David Howells   [PATCH] Handle TI...
741
742
743
  		case -ERESTARTNOHAND:
  		case -ERESTARTSYS:
  		case -ERESTARTNOINTR:
65ea5b034   H. Peter Anvin   x86: rename the s...
744
745
  			regs->ax = regs->orig_ax;
  			regs->ip -= 2;
283828f3c   David Howells   [PATCH] Handle TI...
746
747
748
  			break;
  
  		case -ERESTART_RESTARTBLOCK:
8fcd8e20f   Hiroshi Shimamoto   x86: signal: make...
749
  			regs->ax = NR_restart_syscall;
65ea5b034   H. Peter Anvin   x86: rename the s...
750
  			regs->ip -= 2;
283828f3c   David Howells   [PATCH] Handle TI...
751
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
  		}
  	}
283828f3c   David Howells   [PATCH] Handle TI...
754

ac66f3fd8   Harvey Harrison   x86: reduce trivi...
755
756
757
758
  	/*
  	 * If there's no signal to deliver, we just put the saved sigmask
  	 * back.
  	 */
5a8da0ea8   Roland McGrath   signals: x86 TS_R...
759
760
  	if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
  		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
9b4296207   Oleg Nesterov   x86, do_signal: S...
761
  		set_current_blocked(&current->saved_sigmask);
283828f3c   David Howells   [PATCH] Handle TI...
762
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
  }
  
  /*
   * notification of userspace execution resumption
283828f3c   David Howells   [PATCH] Handle TI...
767
   * - triggered by the TIF_WORK_MASK flags
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
   */
7e907f489   Ingo Molnar   x86: clean up arc...
769
770
  void
  do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  {
c1ebf8356   Andi Kleen   x86: mce: Rename ...
772
  #ifdef CONFIG_X86_MCE
ee847c54b   Hiroshi Shimamoto   x86: signal: cosm...
773
774
  	/* notify userspace of pending MCEs */
  	if (thread_info_flags & _TIF_MCE_NOTIFY)
9b1beaf2b   Andi Kleen   x86, mce: support...
775
  		mce_notify_process();
ee847c54b   Hiroshi Shimamoto   x86: signal: cosm...
776
  #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  	/* deal with pending signal delivery */
5a8da0ea8   Roland McGrath   signals: x86 TS_R...
778
  	if (thread_info_flags & _TIF_SIGPENDING)
283828f3c   David Howells   [PATCH] Handle TI...
779
  		do_signal(regs);
8f4d37ec0   Peter Zijlstra   sched: high-res p...
780

59e52130f   Roland McGrath   x86: tracehook: T...
781
782
783
  	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
  		clear_thread_flag(TIF_NOTIFY_RESUME);
  		tracehook_notify_resume(regs);
ee18d64c1   David Howells   KEYS: Add a keyct...
784
785
  		if (current->replacement_session_keyring)
  			key_replace_session_keyring();
59e52130f   Roland McGrath   x86: tracehook: T...
786
  	}
7c68af6e3   Avi Kivity   core, x86: Add us...
787
788
  	if (thread_info_flags & _TIF_USER_RETURN_NOTIFY)
  		fire_user_return_notifiers();
59e52130f   Roland McGrath   x86: tracehook: T...
789

ee847c54b   Hiroshi Shimamoto   x86: signal: cosm...
790
  #ifdef CONFIG_X86_32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  	clear_thread_flag(TIF_IRET);
ee847c54b   Hiroshi Shimamoto   x86: signal: cosm...
792
  #endif /* CONFIG_X86_32 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
  }
72fa50f4e   Hiroshi Shimamoto   x86_32: signal: i...
794
795
796
797
798
799
  
  void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
  {
  	struct task_struct *me = current;
  
  	if (show_unhandled_signals && printk_ratelimit()) {
ae417bb48   Hiroshi Shimamoto   x86: signal: use ...
800
  		printk("%s"
72fa50f4e   Hiroshi Shimamoto   x86_32: signal: i...
801
  		       "%s[%d] bad frame in %s frame:%p ip:%lx sp:%lx orax:%lx",
ae417bb48   Hiroshi Shimamoto   x86: signal: use ...
802
  		       task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
72fa50f4e   Hiroshi Shimamoto   x86_32: signal: i...
803
804
805
806
807
808
809
810
811
  		       me->comm, me->pid, where, frame,
  		       regs->ip, regs->sp, regs->orig_ax);
  		print_vma_addr(" in ", regs->ip);
  		printk(KERN_CONT "
  ");
  	}
  
  	force_sig(SIGSEGV, me);
  }