xref: /linux/arch/alpha/kernel/signal.c (revision 71ca97da9d027009d318d319cbacf54a72f666c1)
1 /*
2  *  linux/arch/alpha/kernel/signal.c
3  *
4  *  Copyright (C) 1995  Linus Torvalds
5  *
6  *  1997-11-02  Modified for POSIX.1b signals by Richard Henderson
7  */
8 
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/signal.h>
12 #include <linux/errno.h>
13 #include <linux/wait.h>
14 #include <linux/ptrace.h>
15 #include <linux/unistd.h>
16 #include <linux/mm.h>
17 #include <linux/smp.h>
18 #include <linux/stddef.h>
19 #include <linux/tty.h>
20 #include <linux/binfmts.h>
21 #include <linux/bitops.h>
22 #include <linux/syscalls.h>
23 #include <linux/tracehook.h>
24 
25 #include <asm/uaccess.h>
26 #include <asm/sigcontext.h>
27 #include <asm/ucontext.h>
28 
29 #include "proto.h"
30 
31 
32 #define DEBUG_SIG 0
33 
34 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35 
36 asmlinkage void ret_from_sys_call(void);
37 
38 /*
39  * The OSF/1 sigprocmask calling sequence is different from the
40  * C sigprocmask() sequence..
41  */
42 SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
43 {
44 	sigset_t oldmask;
45 	sigset_t mask;
46 	unsigned long res;
47 
48 	siginitset(&mask, newmask & _BLOCKABLE);
49 	res = sigprocmask(how, &mask, &oldmask);
50 	if (!res) {
51 		force_successful_syscall_return();
52 		res = oldmask.sig[0];
53 	}
54 	return res;
55 }
56 
57 SYSCALL_DEFINE3(osf_sigaction, int, sig,
58 		const struct osf_sigaction __user *, act,
59 		struct osf_sigaction __user *, oact)
60 {
61 	struct k_sigaction new_ka, old_ka;
62 	int ret;
63 
64 	if (act) {
65 		old_sigset_t mask;
66 		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
67 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
68 		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
69 		    __get_user(mask, &act->sa_mask))
70 			return -EFAULT;
71 		siginitset(&new_ka.sa.sa_mask, mask);
72 		new_ka.ka_restorer = NULL;
73 	}
74 
75 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
76 
77 	if (!ret && oact) {
78 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
79 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
80 		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
81 		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
82 			return -EFAULT;
83 	}
84 
85 	return ret;
86 }
87 
88 SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
89 		struct sigaction __user *, oact,
90 		size_t, sigsetsize, void __user *, restorer)
91 {
92 	struct k_sigaction new_ka, old_ka;
93 	int ret;
94 
95 	/* XXX: Don't preclude handling different sized sigset_t's.  */
96 	if (sigsetsize != sizeof(sigset_t))
97 		return -EINVAL;
98 
99 	if (act) {
100 		new_ka.ka_restorer = restorer;
101 		if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
102 			return -EFAULT;
103 	}
104 
105 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
106 
107 	if (!ret && oact) {
108 		if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
109 			return -EFAULT;
110 	}
111 
112 	return ret;
113 }
114 
115 /*
116  * Atomically swap in the new signal mask, and wait for a signal.
117  */
118 SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
119 {
120 	sigset_t blocked;
121 	siginitset(&blocked, mask);
122 	return sigsuspend(&blocked);
123 }
124 
125 asmlinkage int
126 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
127 {
128 	return do_sigaltstack(uss, uoss, rdusp());
129 }
130 
131 /*
132  * Do a signal return; undo the signal stack.
133  */
134 
135 #if _NSIG_WORDS > 1
136 # error "Non SA_SIGINFO frame needs rearranging"
137 #endif
138 
139 struct sigframe
140 {
141 	struct sigcontext sc;
142 	unsigned int retcode[3];
143 };
144 
145 struct rt_sigframe
146 {
147 	struct siginfo info;
148 	struct ucontext uc;
149 	unsigned int retcode[3];
150 };
151 
152 /* If this changes, userland unwinders that Know Things about our signal
153    frame will break.  Do not undertake lightly.  It also implies an ABI
154    change wrt the size of siginfo_t, which may cause some pain.  */
155 extern char compile_time_assert
156         [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
157 
158 #define INSN_MOV_R30_R16	0x47fe0410
159 #define INSN_LDI_R0		0x201f0000
160 #define INSN_CALLSYS		0x00000083
161 
162 static long
163 restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
164 		   struct switch_stack *sw)
165 {
166 	unsigned long usp;
167 	long i, err = __get_user(regs->pc, &sc->sc_pc);
168 
169 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
170 
171 	sw->r26 = (unsigned long) ret_from_sys_call;
172 
173 	err |= __get_user(regs->r0, sc->sc_regs+0);
174 	err |= __get_user(regs->r1, sc->sc_regs+1);
175 	err |= __get_user(regs->r2, sc->sc_regs+2);
176 	err |= __get_user(regs->r3, sc->sc_regs+3);
177 	err |= __get_user(regs->r4, sc->sc_regs+4);
178 	err |= __get_user(regs->r5, sc->sc_regs+5);
179 	err |= __get_user(regs->r6, sc->sc_regs+6);
180 	err |= __get_user(regs->r7, sc->sc_regs+7);
181 	err |= __get_user(regs->r8, sc->sc_regs+8);
182 	err |= __get_user(sw->r9, sc->sc_regs+9);
183 	err |= __get_user(sw->r10, sc->sc_regs+10);
184 	err |= __get_user(sw->r11, sc->sc_regs+11);
185 	err |= __get_user(sw->r12, sc->sc_regs+12);
186 	err |= __get_user(sw->r13, sc->sc_regs+13);
187 	err |= __get_user(sw->r14, sc->sc_regs+14);
188 	err |= __get_user(sw->r15, sc->sc_regs+15);
189 	err |= __get_user(regs->r16, sc->sc_regs+16);
190 	err |= __get_user(regs->r17, sc->sc_regs+17);
191 	err |= __get_user(regs->r18, sc->sc_regs+18);
192 	err |= __get_user(regs->r19, sc->sc_regs+19);
193 	err |= __get_user(regs->r20, sc->sc_regs+20);
194 	err |= __get_user(regs->r21, sc->sc_regs+21);
195 	err |= __get_user(regs->r22, sc->sc_regs+22);
196 	err |= __get_user(regs->r23, sc->sc_regs+23);
197 	err |= __get_user(regs->r24, sc->sc_regs+24);
198 	err |= __get_user(regs->r25, sc->sc_regs+25);
199 	err |= __get_user(regs->r26, sc->sc_regs+26);
200 	err |= __get_user(regs->r27, sc->sc_regs+27);
201 	err |= __get_user(regs->r28, sc->sc_regs+28);
202 	err |= __get_user(regs->gp, sc->sc_regs+29);
203 	err |= __get_user(usp, sc->sc_regs+30);
204 	wrusp(usp);
205 
206 	for (i = 0; i < 31; i++)
207 		err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
208 	err |= __get_user(sw->fp[31], &sc->sc_fpcr);
209 
210 	return err;
211 }
212 
213 /* Note that this syscall is also used by setcontext(3) to install
214    a given sigcontext.  This because it's impossible to set *all*
215    registers and transfer control from userland.  */
216 
217 asmlinkage void
218 do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
219 	     struct switch_stack *sw)
220 {
221 	sigset_t set;
222 
223 	/* Verify that it's a good sigcontext before using it */
224 	if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
225 		goto give_sigsegv;
226 	if (__get_user(set.sig[0], &sc->sc_mask))
227 		goto give_sigsegv;
228 
229 	sigdelsetmask(&set, ~_BLOCKABLE);
230 	set_current_blocked(&set);
231 
232 	if (restore_sigcontext(sc, regs, sw))
233 		goto give_sigsegv;
234 
235 	/* Send SIGTRAP if we're single-stepping: */
236 	if (ptrace_cancel_bpt (current)) {
237 		siginfo_t info;
238 
239 		info.si_signo = SIGTRAP;
240 		info.si_errno = 0;
241 		info.si_code = TRAP_BRKPT;
242 		info.si_addr = (void __user *) regs->pc;
243 		info.si_trapno = 0;
244 		send_sig_info(SIGTRAP, &info, current);
245 	}
246 	return;
247 
248 give_sigsegv:
249 	force_sig(SIGSEGV, current);
250 }
251 
252 asmlinkage void
253 do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
254 		struct switch_stack *sw)
255 {
256 	sigset_t set;
257 
258 	/* Verify that it's a good ucontext_t before using it */
259 	if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
260 		goto give_sigsegv;
261 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
262 		goto give_sigsegv;
263 
264 	sigdelsetmask(&set, ~_BLOCKABLE);
265 	set_current_blocked(&set);
266 
267 	if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
268 		goto give_sigsegv;
269 
270 	/* Send SIGTRAP if we're single-stepping: */
271 	if (ptrace_cancel_bpt (current)) {
272 		siginfo_t info;
273 
274 		info.si_signo = SIGTRAP;
275 		info.si_errno = 0;
276 		info.si_code = TRAP_BRKPT;
277 		info.si_addr = (void __user *) regs->pc;
278 		info.si_trapno = 0;
279 		send_sig_info(SIGTRAP, &info, current);
280 	}
281 	return;
282 
283 give_sigsegv:
284 	force_sig(SIGSEGV, current);
285 }
286 
287 
288 /*
289  * Set up a signal frame.
290  */
291 
292 static inline void __user *
293 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
294 {
295 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
296 		sp = current->sas_ss_sp + current->sas_ss_size;
297 
298 	return (void __user *)((sp - frame_size) & -32ul);
299 }
300 
301 static long
302 setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
303 		 struct switch_stack *sw, unsigned long mask, unsigned long sp)
304 {
305 	long i, err = 0;
306 
307 	err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
308 	err |= __put_user(mask, &sc->sc_mask);
309 	err |= __put_user(regs->pc, &sc->sc_pc);
310 	err |= __put_user(8, &sc->sc_ps);
311 
312 	err |= __put_user(regs->r0 , sc->sc_regs+0);
313 	err |= __put_user(regs->r1 , sc->sc_regs+1);
314 	err |= __put_user(regs->r2 , sc->sc_regs+2);
315 	err |= __put_user(regs->r3 , sc->sc_regs+3);
316 	err |= __put_user(regs->r4 , sc->sc_regs+4);
317 	err |= __put_user(regs->r5 , sc->sc_regs+5);
318 	err |= __put_user(regs->r6 , sc->sc_regs+6);
319 	err |= __put_user(regs->r7 , sc->sc_regs+7);
320 	err |= __put_user(regs->r8 , sc->sc_regs+8);
321 	err |= __put_user(sw->r9   , sc->sc_regs+9);
322 	err |= __put_user(sw->r10  , sc->sc_regs+10);
323 	err |= __put_user(sw->r11  , sc->sc_regs+11);
324 	err |= __put_user(sw->r12  , sc->sc_regs+12);
325 	err |= __put_user(sw->r13  , sc->sc_regs+13);
326 	err |= __put_user(sw->r14  , sc->sc_regs+14);
327 	err |= __put_user(sw->r15  , sc->sc_regs+15);
328 	err |= __put_user(regs->r16, sc->sc_regs+16);
329 	err |= __put_user(regs->r17, sc->sc_regs+17);
330 	err |= __put_user(regs->r18, sc->sc_regs+18);
331 	err |= __put_user(regs->r19, sc->sc_regs+19);
332 	err |= __put_user(regs->r20, sc->sc_regs+20);
333 	err |= __put_user(regs->r21, sc->sc_regs+21);
334 	err |= __put_user(regs->r22, sc->sc_regs+22);
335 	err |= __put_user(regs->r23, sc->sc_regs+23);
336 	err |= __put_user(regs->r24, sc->sc_regs+24);
337 	err |= __put_user(regs->r25, sc->sc_regs+25);
338 	err |= __put_user(regs->r26, sc->sc_regs+26);
339 	err |= __put_user(regs->r27, sc->sc_regs+27);
340 	err |= __put_user(regs->r28, sc->sc_regs+28);
341 	err |= __put_user(regs->gp , sc->sc_regs+29);
342 	err |= __put_user(sp, sc->sc_regs+30);
343 	err |= __put_user(0, sc->sc_regs+31);
344 
345 	for (i = 0; i < 31; i++)
346 		err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
347 	err |= __put_user(0, sc->sc_fpregs+31);
348 	err |= __put_user(sw->fp[31], &sc->sc_fpcr);
349 
350 	err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
351 	err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
352 	err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
353 
354 	return err;
355 }
356 
357 static int
358 setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
359 	    struct pt_regs *regs, struct switch_stack * sw)
360 {
361 	unsigned long oldsp, r26, err = 0;
362 	struct sigframe __user *frame;
363 
364 	oldsp = rdusp();
365 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
366 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
367 		return -EFAULT;
368 
369 	err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
370 	if (err)
371 		return -EFAULT;
372 
373 	/* Set up to return from userspace.  If provided, use a stub
374 	   already in userspace.  */
375 	if (ka->ka_restorer) {
376 		r26 = (unsigned long) ka->ka_restorer;
377 	} else {
378 		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
379 		err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
380 		err |= __put_user(INSN_CALLSYS, frame->retcode+2);
381 		imb();
382 		r26 = (unsigned long) frame->retcode;
383 	}
384 
385 	/* Check that everything was written properly.  */
386 	if (err)
387 		return err;
388 
389 	/* "Return" to the handler */
390 	regs->r26 = r26;
391 	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
392 	regs->r16 = sig;			/* a0: signal number */
393 	regs->r17 = 0;				/* a1: exception code */
394 	regs->r18 = (unsigned long) &frame->sc;	/* a2: sigcontext pointer */
395 	wrusp((unsigned long) frame);
396 
397 #if DEBUG_SIG
398 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
399 		current->comm, current->pid, frame, regs->pc, regs->r26);
400 #endif
401 	return 0;
402 }
403 
404 static int
405 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
406 	       sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
407 {
408 	unsigned long oldsp, r26, err = 0;
409 	struct rt_sigframe __user *frame;
410 
411 	oldsp = rdusp();
412 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
413 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
414 		return -EFAULT;
415 
416 	err |= copy_siginfo_to_user(&frame->info, info);
417 
418 	/* Create the ucontext.  */
419 	err |= __put_user(0, &frame->uc.uc_flags);
420 	err |= __put_user(0, &frame->uc.uc_link);
421 	err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
422 	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
423 	err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
424 	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
425 	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
426 				set->sig[0], oldsp);
427 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
428 	if (err)
429 		return -EFAULT;
430 
431 	/* Set up to return from userspace.  If provided, use a stub
432 	   already in userspace.  */
433 	if (ka->ka_restorer) {
434 		r26 = (unsigned long) ka->ka_restorer;
435 	} else {
436 		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
437 		err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
438 				  frame->retcode+1);
439 		err |= __put_user(INSN_CALLSYS, frame->retcode+2);
440 		imb();
441 		r26 = (unsigned long) frame->retcode;
442 	}
443 
444 	if (err)
445 		return -EFAULT;
446 
447 	/* "Return" to the handler */
448 	regs->r26 = r26;
449 	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
450 	regs->r16 = sig;			  /* a0: signal number */
451 	regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
452 	regs->r18 = (unsigned long) &frame->uc;	  /* a2: ucontext pointer */
453 	wrusp((unsigned long) frame);
454 
455 #if DEBUG_SIG
456 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
457 		current->comm, current->pid, frame, regs->pc, regs->r26);
458 #endif
459 
460 	return 0;
461 }
462 
463 
464 /*
465  * OK, we're invoking a handler.
466  */
467 static inline void
468 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
469 	      struct pt_regs * regs, struct switch_stack *sw)
470 {
471 	sigset_t *oldset = &current->blocked;
472 	int ret;
473 
474 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
475 		oldset = &current->saved_sigmask;
476 
477 	if (ka->sa.sa_flags & SA_SIGINFO)
478 		ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
479 	else
480 		ret = setup_frame(sig, ka, oldset, regs, sw);
481 
482 	if (ret) {
483 		force_sigsegv(sig, current);
484 		return;
485 	}
486 	block_sigmask(ka, sig);
487 	/* A signal was successfully delivered, and the
488 	   saved sigmask was stored on the signal frame,
489 	   and will be restored by sigreturn.  So we can
490 	   simply clear the restore sigmask flag.  */
491 	clear_thread_flag(TIF_RESTORE_SIGMASK);
492 }
493 
494 static inline void
495 syscall_restart(unsigned long r0, unsigned long r19,
496 		struct pt_regs *regs, struct k_sigaction *ka)
497 {
498 	switch (regs->r0) {
499 	case ERESTARTSYS:
500 		if (!(ka->sa.sa_flags & SA_RESTART)) {
501 		case ERESTARTNOHAND:
502 			regs->r0 = EINTR;
503 			break;
504 		}
505 		/* fallthrough */
506 	case ERESTARTNOINTR:
507 		regs->r0 = r0;	/* reset v0 and a3 and replay syscall */
508 		regs->r19 = r19;
509 		regs->pc -= 4;
510 		break;
511 	case ERESTART_RESTARTBLOCK:
512 		regs->r0 = EINTR;
513 		break;
514 	}
515 }
516 
517 
518 /*
519  * Note that 'init' is a special process: it doesn't get signals it doesn't
520  * want to handle. Thus you cannot kill init even with a SIGKILL even by
521  * mistake.
522  *
523  * Note that we go through the signals twice: once to check the signals that
524  * the kernel can handle, and then we build all the user-level signal handling
525  * stack-frames in one go after that.
526  *
527  * "r0" and "r19" are the registers we need to restore for system call
528  * restart. "r0" is also used as an indicator whether we can restart at
529  * all (if we get here from anything but a syscall return, it will be 0)
530  */
531 static void
532 do_signal(struct pt_regs * regs, struct switch_stack * sw,
533 	  unsigned long r0, unsigned long r19)
534 {
535 	siginfo_t info;
536 	int signr;
537 	unsigned long single_stepping = ptrace_cancel_bpt(current);
538 	struct k_sigaction ka;
539 
540 	/* This lets the debugger run, ... */
541 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
542 
543 	/* ... so re-check the single stepping. */
544 	single_stepping |= ptrace_cancel_bpt(current);
545 
546 	if (signr > 0) {
547 		/* Whee!  Actually deliver the signal.  */
548 		if (r0)
549 			syscall_restart(r0, r19, regs, &ka);
550 		handle_signal(signr, &ka, &info, regs, sw);
551 		if (single_stepping)
552 			ptrace_set_bpt(current); /* re-set bpt */
553 		return;
554 	}
555 
556 	if (r0) {
557 	  	switch (regs->r0) {
558 		case ERESTARTNOHAND:
559 		case ERESTARTSYS:
560 		case ERESTARTNOINTR:
561 			/* Reset v0 and a3 and replay syscall.  */
562 			regs->r0 = r0;
563 			regs->r19 = r19;
564 			regs->pc -= 4;
565 			break;
566 		case ERESTART_RESTARTBLOCK:
567 			/* Force v0 to the restart syscall and reply.  */
568 			regs->r0 = __NR_restart_syscall;
569 			regs->pc -= 4;
570 			break;
571 		}
572 	}
573 
574 	/* If there's no signal to deliver, we just restore the saved mask.  */
575 	if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
576 		set_current_blocked(&current->saved_sigmask);
577 
578 	if (single_stepping)
579 		ptrace_set_bpt(current);	/* re-set breakpoint */
580 }
581 
582 void
583 do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
584 		 unsigned long thread_info_flags,
585 		 unsigned long r0, unsigned long r19)
586 {
587 	if (thread_info_flags & _TIF_SIGPENDING)
588 		do_signal(regs, sw, r0, r19);
589 
590 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
591 		clear_thread_flag(TIF_NOTIFY_RESUME);
592 		tracehook_notify_resume(regs);
593 		if (current->replacement_session_keyring)
594 			key_replace_session_keyring();
595 	}
596 }
597