1 /* Signal support for 32-bit kernel builds
2 *
3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
5 *
6 * Code was mostly borrowed from kernel/signal.c.
7 * See kernel/signal.c for additional Copyrights.
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 #include <linux/compat.h>
26 #include <linux/module.h>
27 #include <linux/unistd.h>
28 #include <linux/init.h>
29 #include <linux/sched.h>
30 #include <linux/syscalls.h>
31 #include <linux/types.h>
32 #include <linux/errno.h>
33
34 #include <asm/uaccess.h>
35
36 #include "signal32.h"
37 #include "sys32.h"
38
39 #define DEBUG_COMPAT_SIG 0
40 #define DEBUG_COMPAT_SIG_LEVEL 2
41
42 #if DEBUG_COMPAT_SIG
43 #define DBG(LEVEL, ...) \
44 ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
45 ? printk(__VA_ARGS__) : (void) 0)
46 #else
47 #define DBG(LEVEL, ...)
48 #endif
49
50 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
51
52 inline void
sigset_32to64(sigset_t * s64,compat_sigset_t * s32)53 sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
54 {
55 s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
56 }
57
58 inline void
sigset_64to32(compat_sigset_t * s32,sigset_t * s64)59 sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
60 {
61 s32->sig[0] = s64->sig[0] & 0xffffffffUL;
62 s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
63 }
64
65 static int
put_sigset32(compat_sigset_t __user * up,sigset_t * set,size_t sz)66 put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
67 {
68 compat_sigset_t s;
69
70 if (sz != sizeof *set)
71 return -EINVAL;
72 sigset_64to32(&s, set);
73
74 return copy_to_user(up, &s, sizeof s);
75 }
76
77 static int
get_sigset32(compat_sigset_t __user * up,sigset_t * set,size_t sz)78 get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
79 {
80 compat_sigset_t s;
81 int r;
82
83 if (sz != sizeof *set)
84 return -EINVAL;
85
86 if ((r = copy_from_user(&s, up, sz)) == 0) {
87 sigset_32to64(set, &s);
88 }
89
90 return r;
91 }
92
sys32_rt_sigprocmask(int how,compat_sigset_t __user * set,compat_sigset_t __user * oset,unsigned int sigsetsize)93 int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
94 unsigned int sigsetsize)
95 {
96 sigset_t old_set, new_set;
97 int ret;
98
99 if (set && get_sigset32(set, &new_set, sigsetsize))
100 return -EFAULT;
101
102 KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
103 oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
104
105 if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
106 return -EFAULT;
107
108 return ret;
109 }
110
111
sys32_rt_sigpending(compat_sigset_t __user * uset,unsigned int sigsetsize)112 int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
113 {
114 int ret;
115 sigset_t set;
116
117 KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
118
119 if (!ret && put_sigset32(uset, &set, sigsetsize))
120 return -EFAULT;
121
122 return ret;
123 }
124
125 long
sys32_rt_sigaction(int sig,const struct sigaction32 __user * act,struct sigaction32 __user * oact,size_t sigsetsize)126 sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
127 size_t sigsetsize)
128 {
129 struct k_sigaction32 new_sa32, old_sa32;
130 struct k_sigaction new_sa, old_sa;
131 int ret = -EINVAL;
132
133 if (act) {
134 if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
135 return -EFAULT;
136 new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
137 new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
138 sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
139 }
140
141 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
142
143 if (!ret && oact) {
144 sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
145 old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
146 old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
147 if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
148 return -EFAULT;
149 }
150 return ret;
151 }
152
153 int
do_sigaltstack32(const compat_stack_t __user * uss32,compat_stack_t __user * uoss32,unsigned long sp)154 do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
155 {
156 compat_stack_t ss32, oss32;
157 stack_t ss, oss;
158 stack_t *ssp = NULL, *ossp = NULL;
159 int ret;
160
161 if (uss32) {
162 if (copy_from_user(&ss32, uss32, sizeof ss32))
163 return -EFAULT;
164
165 ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
166 ss.ss_flags = ss32.ss_flags;
167 ss.ss_size = ss32.ss_size;
168
169 ssp = &ss;
170 }
171
172 if (uoss32)
173 ossp = &oss;
174
175 KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
176
177 if (!ret && uoss32) {
178 oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
179 oss32.ss_flags = oss.ss_flags;
180 oss32.ss_size = oss.ss_size;
181 if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
182 return -EFAULT;
183 }
184
185 return ret;
186 }
187
188 long
restore_sigcontext32(struct compat_sigcontext __user * sc,struct compat_regfile __user * rf,struct pt_regs * regs)189 restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
190 struct pt_regs *regs)
191 {
192 long err = 0;
193 compat_uint_t compat_reg;
194 compat_uint_t compat_regt;
195 int regn;
196
197 /* When loading 32-bit values into 64-bit registers make
198 sure to clear the upper 32-bits */
199 DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
200 DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
201 DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
202 for(regn=0; regn < 32; regn++){
203 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
204 regs->gr[regn] = compat_reg;
205 /* Load upper half */
206 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
207 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
208 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
209 regn, regs->gr[regn], compat_regt, compat_reg);
210 }
211 DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
212 /* XXX: BE WARNED FR's are 64-BIT! */
213 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
214
215 /* Better safe than sorry, pass __get_user two things of
216 the same size and let gcc do the upward conversion to
217 64-bits */
218 err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
219 /* Load upper half */
220 err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
221 regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
222 DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
223 DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
224 &sc->sc_iaoq[0], compat_reg);
225
226 err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
227 /* Load upper half */
228 err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
229 regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
230 DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
231 DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
232 &sc->sc_iaoq[1],compat_reg);
233 DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
234 regs->iaoq[0],regs->iaoq[1]);
235
236 err |= __get_user(compat_reg, &sc->sc_iasq[0]);
237 /* Load the upper half for iasq */
238 err |= __get_user(compat_regt, &rf->rf_iasq[0]);
239 regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
240 DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
241
242 err |= __get_user(compat_reg, &sc->sc_iasq[1]);
243 /* Load the upper half for iasq */
244 err |= __get_user(compat_regt, &rf->rf_iasq[1]);
245 regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
246 DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
247 DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
248 regs->iasq[0],regs->iasq[1]);
249
250 err |= __get_user(compat_reg, &sc->sc_sar);
251 /* Load the upper half for sar */
252 err |= __get_user(compat_regt, &rf->rf_sar);
253 regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
254 DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
255 DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
256 DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
257
258 return err;
259 }
260
261 /*
262 * Set up the sigcontext structure for this process.
263 * This is not an easy task if the kernel is 64-bit, it will require
264 * that we examine the process personality to determine if we need to
265 * truncate for a 32-bit userspace.
266 */
267 long
setup_sigcontext32(struct compat_sigcontext __user * sc,struct compat_regfile __user * rf,struct pt_regs * regs,int in_syscall)268 setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
269 struct pt_regs *regs, int in_syscall)
270 {
271 compat_int_t flags = 0;
272 long err = 0;
273 compat_uint_t compat_reg;
274 compat_uint_t compat_regb;
275 int regn;
276
277 if (on_sig_stack((unsigned long) sc))
278 flags |= PARISC_SC_FLAG_ONSTACK;
279
280 if (in_syscall) {
281
282 DBG(1,"setup_sigcontext32: in_syscall\n");
283
284 flags |= PARISC_SC_FLAG_IN_SYSCALL;
285 /* Truncate gr31 */
286 compat_reg = (compat_uint_t)(regs->gr[31]);
287 /* regs->iaoq is undefined in the syscall return path */
288 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
289 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
290 &sc->sc_iaoq[0], compat_reg);
291
292 /* Store upper half */
293 compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
294 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
295 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
296
297
298 compat_reg = (compat_uint_t)(regs->gr[31]+4);
299 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
300 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
301 &sc->sc_iaoq[1], compat_reg);
302 /* Store upper half */
303 compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
304 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
305 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
306
307 /* Truncate sr3 */
308 compat_reg = (compat_uint_t)(regs->sr[3]);
309 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
310 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
311
312 /* Store upper half */
313 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
314 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
315 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
316
317 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
318 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
319 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
320 regs->gr[31], regs->gr[31]+4);
321
322 } else {
323
324 compat_reg = (compat_uint_t)(regs->iaoq[0]);
325 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
326 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
327 &sc->sc_iaoq[0], compat_reg);
328 /* Store upper half */
329 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
330 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
331 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
332
333 compat_reg = (compat_uint_t)(regs->iaoq[1]);
334 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
335 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
336 &sc->sc_iaoq[1], compat_reg);
337 /* Store upper half */
338 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
339 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
340 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
341
342
343 compat_reg = (compat_uint_t)(regs->iasq[0]);
344 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
345 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
346 &sc->sc_iasq[0], compat_reg);
347 /* Store upper half */
348 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
349 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
350 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
351
352
353 compat_reg = (compat_uint_t)(regs->iasq[1]);
354 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
355 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
356 &sc->sc_iasq[1], compat_reg);
357 /* Store upper half */
358 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
359 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
360 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
361
362 /* Print out the IAOQ for debugging */
363 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
364 regs->iaoq[0], regs->iaoq[1]);
365 }
366
367 err |= __put_user(flags, &sc->sc_flags);
368
369 DBG(1,"setup_sigcontext32: Truncating general registers.\n");
370
371 for(regn=0; regn < 32; regn++){
372 /* Truncate a general register */
373 compat_reg = (compat_uint_t)(regs->gr[regn]);
374 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
375 /* Store upper half */
376 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
377 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
378
379 /* DEBUG: Write out the "upper / lower" register data */
380 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
381 compat_regb, compat_reg);
382 }
383
384 /* Copy the floating point registers (same size)
385 XXX: BE WARNED FR's are 64-BIT! */
386 DBG(1,"setup_sigcontext32: Copying from regs to sc, "
387 "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
388 sizeof(regs->fr), sizeof(sc->sc_fr));
389 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
390
391 compat_reg = (compat_uint_t)(regs->sar);
392 err |= __put_user(compat_reg, &sc->sc_sar);
393 DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
394 /* Store upper half */
395 compat_reg = (compat_uint_t)(regs->sar >> 32);
396 err |= __put_user(compat_reg, &rf->rf_sar);
397 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
398 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
399
400 return err;
401 }
402
403 int
copy_siginfo_from_user32(siginfo_t * to,compat_siginfo_t __user * from)404 copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
405 {
406 compat_uptr_t addr;
407 int err;
408
409 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
410 return -EFAULT;
411
412 err = __get_user(to->si_signo, &from->si_signo);
413 err |= __get_user(to->si_errno, &from->si_errno);
414 err |= __get_user(to->si_code, &from->si_code);
415
416 if (to->si_code < 0)
417 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
418 else {
419 switch (to->si_code >> 16) {
420 case __SI_CHLD >> 16:
421 err |= __get_user(to->si_utime, &from->si_utime);
422 err |= __get_user(to->si_stime, &from->si_stime);
423 err |= __get_user(to->si_status, &from->si_status);
424 default:
425 err |= __get_user(to->si_pid, &from->si_pid);
426 err |= __get_user(to->si_uid, &from->si_uid);
427 break;
428 case __SI_FAULT >> 16:
429 err |= __get_user(addr, &from->si_addr);
430 to->si_addr = compat_ptr(addr);
431 break;
432 case __SI_POLL >> 16:
433 err |= __get_user(to->si_band, &from->si_band);
434 err |= __get_user(to->si_fd, &from->si_fd);
435 break;
436 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
437 case __SI_MESGQ >> 16:
438 err |= __get_user(to->si_pid, &from->si_pid);
439 err |= __get_user(to->si_uid, &from->si_uid);
440 err |= __get_user(to->si_int, &from->si_int);
441 break;
442 }
443 }
444 return err;
445 }
446
447 int
copy_siginfo_to_user32(compat_siginfo_t __user * to,siginfo_t * from)448 copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
449 {
450 compat_uptr_t addr;
451 compat_int_t val;
452 int err;
453
454 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
455 return -EFAULT;
456
457 /* If you change siginfo_t structure, please be sure
458 this code is fixed accordingly.
459 It should never copy any pad contained in the structure
460 to avoid security leaks, but must copy the generic
461 3 ints plus the relevant union member.
462 This routine must convert siginfo from 64bit to 32bit as well
463 at the same time. */
464 err = __put_user(from->si_signo, &to->si_signo);
465 err |= __put_user(from->si_errno, &to->si_errno);
466 err |= __put_user((short)from->si_code, &to->si_code);
467 if (from->si_code < 0)
468 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
469 else {
470 switch (from->si_code >> 16) {
471 case __SI_CHLD >> 16:
472 err |= __put_user(from->si_utime, &to->si_utime);
473 err |= __put_user(from->si_stime, &to->si_stime);
474 err |= __put_user(from->si_status, &to->si_status);
475 default:
476 err |= __put_user(from->si_pid, &to->si_pid);
477 err |= __put_user(from->si_uid, &to->si_uid);
478 break;
479 case __SI_FAULT >> 16:
480 addr = ptr_to_compat(from->si_addr);
481 err |= __put_user(addr, &to->si_addr);
482 break;
483 case __SI_POLL >> 16:
484 err |= __put_user(from->si_band, &to->si_band);
485 err |= __put_user(from->si_fd, &to->si_fd);
486 break;
487 case __SI_TIMER >> 16:
488 err |= __put_user(from->si_tid, &to->si_tid);
489 err |= __put_user(from->si_overrun, &to->si_overrun);
490 val = (compat_int_t)from->si_int;
491 err |= __put_user(val, &to->si_int);
492 break;
493 case __SI_RT >> 16: /* Not generated by the kernel as of now. */
494 case __SI_MESGQ >> 16:
495 err |= __put_user(from->si_uid, &to->si_uid);
496 err |= __put_user(from->si_pid, &to->si_pid);
497 val = (compat_int_t)from->si_int;
498 err |= __put_user(val, &to->si_int);
499 break;
500 }
501 }
502 return err;
503 }
504
compat_sys_rt_sigqueueinfo(int pid,int sig,struct compat_siginfo __user * uinfo)505 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
506 struct compat_siginfo __user *uinfo)
507 {
508 siginfo_t info;
509
510 if (copy_siginfo_from_user32(&info, uinfo))
511 return -EFAULT;
512
513 /* Not even root can pretend to send signals from the kernel.
514 Nor can they impersonate a kill(), which adds source info. */
515 if (info.si_code >= 0)
516 return -EPERM;
517 info.si_signo = sig;
518
519 /* POSIX.1b doesn't mention process groups. */
520 return kill_proc_info(sig, &info, pid);
521 }
522
523