xref: /freebsd/sys/i386/linux/linux_machdep.c (revision a220d00e74dd245b4fca59c5eca0c53963686325)
1 /*-
2  * Copyright (c) 2000 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/lock.h>
34 #include <sys/mman.h>
35 #include <sys/mutex.h>
36 #include <sys/proc.h>
37 #include <sys/resource.h>
38 #include <sys/resourcevar.h>
39 #include <sys/sysproto.h>
40 #include <sys/unistd.h>
41 
42 #include <machine/frame.h>
43 #include <machine/psl.h>
44 #include <machine/segments.h>
45 #include <machine/sysarch.h>
46 
47 #include <vm/vm.h>
48 #include <vm/pmap.h>
49 #include <vm/vm_map.h>
50 
51 #include <i386/linux/linux.h>
52 #include <i386/linux/linux_proto.h>
53 #include <compat/linux/linux_ipc.h>
54 #include <compat/linux/linux_signal.h>
55 #include <compat/linux/linux_util.h>
56 
57 struct l_descriptor {
58 	l_uint		entry_number;
59 	l_ulong		base_addr;
60 	l_uint		limit;
61 	l_uint		seg_32bit:1;
62 	l_uint		contents:2;
63 	l_uint		read_exec_only:1;
64 	l_uint		limit_in_pages:1;
65 	l_uint		seg_not_present:1;
66 	l_uint		useable:1;
67 };
68 
69 struct l_old_select_argv {
70 	l_int		nfds;
71 	l_fd_set	*readfds;
72 	l_fd_set	*writefds;
73 	l_fd_set	*exceptfds;
74 	struct l_timeval	*timeout;
75 };
76 
77 int
78 linux_to_bsd_sigaltstack(int lsa)
79 {
80 	int bsa = 0;
81 
82 	if (lsa & LINUX_SS_DISABLE)
83 		bsa |= SS_DISABLE;
84 	if (lsa & LINUX_SS_ONSTACK)
85 		bsa |= SS_ONSTACK;
86 	return (bsa);
87 }
88 
89 int
90 bsd_to_linux_sigaltstack(int bsa)
91 {
92 	int lsa = 0;
93 
94 	if (bsa & SS_DISABLE)
95 		lsa |= LINUX_SS_DISABLE;
96 	if (bsa & SS_ONSTACK)
97 		lsa |= LINUX_SS_ONSTACK;
98 	return (lsa);
99 }
100 
101 int
102 linux_execve(struct thread *td, struct linux_execve_args *args)
103 {
104 	struct execve_args bsd;
105 	caddr_t sg;
106 
107 	sg = stackgap_init();
108 	CHECKALTEXIST(td, &sg, args->path);
109 
110 #ifdef DEBUG
111 	if (ldebug(execve))
112 		printf(ARGS(execve, "%s"), args->path);
113 #endif
114 
115 	bsd.fname = args->path;
116 	bsd.argv = args->argp;
117 	bsd.envv = args->envp;
118 	return (execve(td, &bsd));
119 }
120 
121 struct l_ipc_kludge {
122 	struct l_msgbuf *msgp;
123 	l_long msgtyp;
124 };
125 
126 int
127 linux_ipc(struct thread *td, struct linux_ipc_args *args)
128 {
129 
130 	switch (args->what & 0xFFFF) {
131 	case LINUX_SEMOP: {
132 		struct linux_semop_args a;
133 
134 		a.semid = args->arg1;
135 		a.tsops = args->ptr;
136 		a.nsops = args->arg2;
137 		return (linux_semop(td, &a));
138 	}
139 	case LINUX_SEMGET: {
140 		struct linux_semget_args a;
141 
142 		a.key = args->arg1;
143 		a.nsems = args->arg2;
144 		a.semflg = args->arg3;
145 		return (linux_semget(td, &a));
146 	}
147 	case LINUX_SEMCTL: {
148 		struct linux_semctl_args a;
149 		int error;
150 
151 		a.semid = args->arg1;
152 		a.semnum = args->arg2;
153 		a.cmd = args->arg3;
154 		error = copyin((caddr_t)args->ptr, &a.arg, sizeof(a.arg));
155 		if (error)
156 			return (error);
157 		return (linux_semctl(td, &a));
158 	}
159 	case LINUX_MSGSND: {
160 		struct linux_msgsnd_args a;
161 
162 		a.msqid = args->arg1;
163 		a.msgp = args->ptr;
164 		a.msgsz = args->arg2;
165 		a.msgflg = args->arg3;
166 		return (linux_msgsnd(td, &a));
167 	}
168 	case LINUX_MSGRCV: {
169 		struct linux_msgrcv_args a;
170 
171 		a.msqid = args->arg1;
172 		a.msgsz = args->arg2;
173 		a.msgflg = args->arg3;
174 		if ((args->what >> 16) == 0) {
175 			struct l_ipc_kludge tmp;
176 			int error;
177 
178 			if (args->ptr == NULL)
179 				return (EINVAL);
180 			error = copyin((caddr_t)args->ptr, &tmp, sizeof(tmp));
181 			if (error)
182 				return (error);
183 			a.msgp = tmp.msgp;
184 			a.msgtyp = tmp.msgtyp;
185 		} else {
186 			a.msgp = args->ptr;
187 			a.msgtyp = args->arg5;
188 		}
189 		return (linux_msgrcv(td, &a));
190 	}
191 	case LINUX_MSGGET: {
192 		struct linux_msgget_args a;
193 
194 		a.key = args->arg1;
195 		a.msgflg = args->arg2;
196 		return (linux_msgget(td, &a));
197 	}
198 	case LINUX_MSGCTL: {
199 		struct linux_msgctl_args a;
200 
201 		a.msqid = args->arg1;
202 		a.cmd = args->arg2;
203 		a.buf = args->ptr;
204 		return (linux_msgctl(td, &a));
205 	}
206 	case LINUX_SHMAT: {
207 		struct linux_shmat_args a;
208 
209 		a.shmid = args->arg1;
210 		a.shmaddr = args->ptr;
211 		a.shmflg = args->arg2;
212 		a.raddr = (l_ulong *)args->arg3;
213 		return (linux_shmat(td, &a));
214 	}
215 	case LINUX_SHMDT: {
216 		struct linux_shmdt_args a;
217 
218 		a.shmaddr = args->ptr;
219 		return (linux_shmdt(td, &a));
220 	}
221 	case LINUX_SHMGET: {
222 		struct linux_shmget_args a;
223 
224 		a.key = args->arg1;
225 		a.size = args->arg2;
226 		a.shmflg = args->arg3;
227 		return (linux_shmget(td, &a));
228 	}
229 	case LINUX_SHMCTL: {
230 		struct linux_shmctl_args a;
231 
232 		a.shmid = args->arg1;
233 		a.cmd = args->arg2;
234 		a.buf = args->ptr;
235 		return (linux_shmctl(td, &a));
236 	}
237 	default:
238 		break;
239 	}
240 
241 	return (EINVAL);
242 }
243 
244 int
245 linux_old_select(struct thread *td, struct linux_old_select_args *args)
246 {
247 	struct l_old_select_argv linux_args;
248 	struct linux_select_args newsel;
249 	int error;
250 
251 #ifdef DEBUG
252 	if (ldebug(old_select))
253 		printf(ARGS(old_select, "%x"), args->ptr);
254 #endif
255 
256 	error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
257 	if (error)
258 		return (error);
259 
260 	newsel.nfds = linux_args.nfds;
261 	newsel.readfds = linux_args.readfds;
262 	newsel.writefds = linux_args.writefds;
263 	newsel.exceptfds = linux_args.exceptfds;
264 	newsel.timeout = linux_args.timeout;
265 	return (linux_select(td, &newsel));
266 }
267 
268 int
269 linux_fork(struct thread *td, struct linux_fork_args *args)
270 {
271 	int error;
272 
273 #ifdef DEBUG
274 	if (ldebug(fork))
275 		printf(ARGS(fork, ""));
276 #endif
277 
278 	if ((error = fork(td, (struct fork_args *)args)) != 0)
279 		return (error);
280 
281 	if (td->td_retval[1] == 1)
282 		td->td_retval[0] = 0;
283 	return (0);
284 }
285 
286 int
287 linux_vfork(struct thread *td, struct linux_vfork_args *args)
288 {
289 	int error;
290 
291 #ifdef DEBUG
292 	if (ldebug(vfork))
293 		printf(ARGS(vfork, ""));
294 #endif
295 
296 	if ((error = vfork(td, (struct vfork_args *)args)) != 0)
297 		return (error);
298 	/* Are we the child? */
299 	if (td->td_retval[1] == 1)
300 		td->td_retval[0] = 0;
301 	return (0);
302 }
303 
304 #define CLONE_VM	0x100
305 #define CLONE_FS	0x200
306 #define CLONE_FILES	0x400
307 #define CLONE_SIGHAND	0x800
308 #define CLONE_PID	0x1000
309 
310 int
311 linux_clone(struct thread *td, struct linux_clone_args *args)
312 {
313 	int error, ff = RFPROC | RFSTOPPED;
314 	struct proc *p2;
315 	int exit_signal;
316 
317 #ifdef DEBUG
318 	if (ldebug(clone)) {
319 		printf(ARGS(clone, "flags %x, stack %x"),
320 		    (unsigned int)args->flags, (unsigned int)args->stack);
321 		if (args->flags & CLONE_PID)
322 			printf(LMSG("CLONE_PID not yet supported"));
323 	}
324 #endif
325 
326 	if (!args->stack)
327 		return (EINVAL);
328 
329 	exit_signal = args->flags & 0x000000ff;
330 	if (exit_signal >= LINUX_NSIG)
331 		return (EINVAL);
332 
333 	if (exit_signal <= LINUX_SIGTBLSZ)
334 		exit_signal = linux_to_bsd_signal[_SIG_IDX(exit_signal)];
335 
336 	if (args->flags & CLONE_VM)
337 		ff |= RFMEM;
338 	if (args->flags & CLONE_SIGHAND)
339 		ff |= RFSIGSHARE;
340 	if (!(args->flags & CLONE_FILES))
341 		ff |= RFFDG;
342 
343 	mtx_lock(&Giant);
344 	error = fork1(td, ff, &p2);
345 	if (error == 0) {
346 		td->td_retval[0] = p2->p_pid;
347 		td->td_retval[1] = 0;
348 
349 		PROC_LOCK(p2);
350 		p2->p_sigparent = exit_signal;
351 		p2->p_thread.td_frame->tf_esp = (unsigned int)args->stack;
352 
353 #ifdef DEBUG
354 		if (ldebug(clone))
355 			printf(LMSG("clone: successful rfork to %ld"),
356 			    (long)p2->p_pid);
357 #endif
358 
359 		/*
360 		 * Make this runnable after we are finished with it.
361 		 */
362 		mtx_lock_spin(&sched_lock);
363 		p2->p_stat = SRUN;
364 		setrunqueue(&p2->p_thread);
365 		mtx_unlock_spin(&sched_lock);
366 		PROC_UNLOCK(p2);
367 	}
368 	mtx_unlock(&Giant);
369 
370 	return (error);
371 }
372 
373 /* XXX move */
374 struct l_mmap_argv {
375 	l_caddr_t	addr;
376 	l_int		len;
377 	l_int		prot;
378 	l_int		flags;
379 	l_int		fd;
380 	l_int		pos;
381 };
382 
383 #define STACK_SIZE  (2 * 1024 * 1024)
384 #define GUARD_SIZE  (4 * PAGE_SIZE)
385 
386 int
387 linux_mmap(struct thread *td, struct linux_mmap_args *args)
388 {
389 	struct proc *p = td->td_proc;
390 	struct mmap_args /* {
391 		caddr_t addr;
392 		size_t len;
393 		int prot;
394 		int flags;
395 		int fd;
396 		long pad;
397 		off_t pos;
398 	} */ bsd_args;
399 	int error;
400 	struct l_mmap_argv linux_args;
401 
402 	error = copyin((caddr_t)args->ptr, &linux_args, sizeof(linux_args));
403 	if (error)
404 		return (error);
405 
406 #ifdef DEBUG
407 	if (ldebug(mmap))
408 		printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
409 		    (void *)linux_args.addr, linux_args.len, linux_args.prot,
410 		    linux_args.flags, linux_args.fd, linux_args.pos);
411 #endif
412 
413 	bsd_args.flags = 0;
414 	if (linux_args.flags & LINUX_MAP_SHARED)
415 		bsd_args.flags |= MAP_SHARED;
416 	if (linux_args.flags & LINUX_MAP_PRIVATE)
417 		bsd_args.flags |= MAP_PRIVATE;
418 	if (linux_args.flags & LINUX_MAP_FIXED)
419 		bsd_args.flags |= MAP_FIXED;
420 	if (linux_args.flags & LINUX_MAP_ANON)
421 		bsd_args.flags |= MAP_ANON;
422 	else
423 		bsd_args.flags |= MAP_NOSYNC;
424 	if (linux_args.flags & LINUX_MAP_GROWSDOWN) {
425 		bsd_args.flags |= MAP_STACK;
426 
427 		/* The linux MAP_GROWSDOWN option does not limit auto
428 		 * growth of the region.  Linux mmap with this option
429 		 * takes as addr the inital BOS, and as len, the initial
430 		 * region size.  It can then grow down from addr without
431 		 * limit.  However, linux threads has an implicit internal
432 		 * limit to stack size of STACK_SIZE.  Its just not
433 		 * enforced explicitly in linux.  But, here we impose
434 		 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
435 		 * region, since we can do this with our mmap.
436 		 *
437 		 * Our mmap with MAP_STACK takes addr as the maximum
438 		 * downsize limit on BOS, and as len the max size of
439 		 * the region.  It them maps the top SGROWSIZ bytes,
440 		 * and autgrows the region down, up to the limit
441 		 * in addr.
442 		 *
443 		 * If we don't use the MAP_STACK option, the effect
444 		 * of this code is to allocate a stack region of a
445 		 * fixed size of (STACK_SIZE - GUARD_SIZE).
446 		 */
447 
448 		/* This gives us TOS */
449 		bsd_args.addr = linux_args.addr + linux_args.len;
450 
451 		if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
452 			/* Some linux apps will attempt to mmap
453 			 * thread stacks near the top of their
454 			 * address space.  If their TOS is greater
455 			 * than vm_maxsaddr, vm_map_growstack()
456 			 * will confuse the thread stack with the
457 			 * process stack and deliver a SEGV if they
458 			 * attempt to grow the thread stack past their
459 			 * current stacksize rlimit.  To avoid this,
460 			 * adjust vm_maxsaddr upwards to reflect
461 			 * the current stacksize rlimit rather
462 			 * than the maximum possible stacksize.
463 			 * It would be better to adjust the
464 			 * mmap'ed region, but some apps do not check
465 			 * mmap's return value.
466 			 */
467 			mtx_assert(&Giant, MA_OWNED);
468 			p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
469 			    p->p_rlimit[RLIMIT_STACK].rlim_cur;
470 		}
471 
472 		/* This gives us our maximum stack size */
473 		if (linux_args.len > STACK_SIZE - GUARD_SIZE)
474 			bsd_args.len = linux_args.len;
475 		else
476 			bsd_args.len  = STACK_SIZE - GUARD_SIZE;
477 
478 		/* This gives us a new BOS.  If we're using VM_STACK, then
479 		 * mmap will just map the top SGROWSIZ bytes, and let
480 		 * the stack grow down to the limit at BOS.  If we're
481 		 * not using VM_STACK we map the full stack, since we
482 		 * don't have a way to autogrow it.
483 		 */
484 		bsd_args.addr -= bsd_args.len;
485 	} else {
486 		bsd_args.addr = linux_args.addr;
487 		bsd_args.len  = linux_args.len;
488 	}
489 
490 	bsd_args.prot = linux_args.prot | PROT_READ;	/* always required */
491 	if (linux_args.flags & LINUX_MAP_ANON)
492 		bsd_args.fd = -1;
493 	else
494 		bsd_args.fd = linux_args.fd;
495 	bsd_args.pos = linux_args.pos;
496 	bsd_args.pad = 0;
497 
498 #ifdef DEBUG
499 	if (ldebug(mmap))
500 		printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n",
501 		    (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
502 		    bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
503 #endif
504 
505 	return (mmap(td, &bsd_args));
506 }
507 
508 int
509 linux_pipe(struct thread *td, struct linux_pipe_args *args)
510 {
511 	int error;
512 	int reg_edx;
513 
514 #ifdef DEBUG
515 	if (ldebug(pipe))
516 		printf(ARGS(pipe, "*"));
517 #endif
518 
519 	reg_edx = td->td_retval[1];
520 	error = pipe(td, 0);
521 	if (error) {
522 		td->td_retval[1] = reg_edx;
523 		return (error);
524 	}
525 
526 	error = copyout(td->td_retval, args->pipefds, 2*sizeof(int));
527 	if (error) {
528 		td->td_retval[1] = reg_edx;
529 		return (error);
530 	}
531 
532 	td->td_retval[1] = reg_edx;
533 	td->td_retval[0] = 0;
534 	return (0);
535 }
536 
537 int
538 linux_ioperm(struct thread *td, struct linux_ioperm_args *args)
539 {
540 	struct sysarch_args sa;
541 	struct i386_ioperm_args *iia;
542 	caddr_t sg;
543 
544 	sg = stackgap_init();
545 	iia = stackgap_alloc(&sg, sizeof(struct i386_ioperm_args));
546 	iia->start = args->start;
547 	iia->length = args->length;
548 	iia->enable = args->enable;
549 	sa.op = I386_SET_IOPERM;
550 	sa.parms = (char *)iia;
551 	return (sysarch(td, &sa));
552 }
553 
554 int
555 linux_iopl(struct thread *td, struct linux_iopl_args *args)
556 {
557 	int error;
558 
559 	if (args->level < 0 || args->level > 3)
560 		return (EINVAL);
561 	if ((error = suser_td(td)) != 0)
562 		return (error);
563 	if ((error = securelevel_gt(td->td_proc->p_ucred, 0)) != 0)
564 		return (error);
565 	td->td_frame->tf_eflags = (td->td_frame->tf_eflags & ~PSL_IOPL) |
566 	    (args->level * (PSL_IOPL / 3));
567 	return (0);
568 }
569 
570 int
571 linux_modify_ldt(td, uap)
572 	struct thread *td;
573 	struct linux_modify_ldt_args *uap;
574 {
575 	int error;
576 	caddr_t sg;
577 	struct sysarch_args args;
578 	struct i386_ldt_args *ldt;
579 	struct l_descriptor ld;
580 	union descriptor *desc;
581 
582 	sg = stackgap_init();
583 
584 	if (uap->ptr == NULL)
585 		return (EINVAL);
586 
587 	switch (uap->func) {
588 	case 0x00: /* read_ldt */
589 		ldt = stackgap_alloc(&sg, sizeof(*ldt));
590 		ldt->start = 0;
591 		ldt->descs = uap->ptr;
592 		ldt->num = uap->bytecount / sizeof(union descriptor);
593 		args.op = I386_GET_LDT;
594 		args.parms = (char*)ldt;
595 		error = sysarch(td, &args);
596 		td->td_retval[0] *= sizeof(union descriptor);
597 		break;
598 	case 0x01: /* write_ldt */
599 	case 0x11: /* write_ldt */
600 		if (uap->bytecount != sizeof(ld))
601 			return (EINVAL);
602 
603 		error = copyin(uap->ptr, &ld, sizeof(ld));
604 		if (error)
605 			return (error);
606 
607 		ldt = stackgap_alloc(&sg, sizeof(*ldt));
608 		desc = stackgap_alloc(&sg, sizeof(*desc));
609 		ldt->start = ld.entry_number;
610 		ldt->descs = desc;
611 		ldt->num = 1;
612 		desc->sd.sd_lolimit = (ld.limit & 0x0000ffff);
613 		desc->sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16;
614 		desc->sd.sd_lobase = (ld.base_addr & 0x00ffffff);
615 		desc->sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24;
616 		desc->sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) |
617 			(ld.contents << 2);
618 		desc->sd.sd_dpl = 3;
619 		desc->sd.sd_p = (ld.seg_not_present ^ 1);
620 		desc->sd.sd_xx = 0;
621 		desc->sd.sd_def32 = ld.seg_32bit;
622 		desc->sd.sd_gran = ld.limit_in_pages;
623 		args.op = I386_SET_LDT;
624 		args.parms = (char*)ldt;
625 		error = sysarch(td, &args);
626 		break;
627 	default:
628 		error = EINVAL;
629 		break;
630 	}
631 
632 	if (error == EOPNOTSUPP) {
633 		printf("linux: modify_ldt needs kernel option USER_LDT\n");
634 		error = ENOSYS;
635 	}
636 
637 	return (error);
638 }
639 
640 int
641 linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
642 {
643 	l_osigaction_t osa;
644 	l_sigaction_t act, oact;
645 	int error;
646 
647 #ifdef DEBUG
648 	if (ldebug(sigaction))
649 		printf(ARGS(sigaction, "%d, %p, %p"),
650 		    args->sig, (void *)args->nsa, (void *)args->osa);
651 #endif
652 
653 	if (args->nsa != NULL) {
654 		error = copyin((caddr_t)args->nsa, &osa,
655 		    sizeof(l_osigaction_t));
656 		if (error)
657 			return (error);
658 		act.lsa_handler = osa.lsa_handler;
659 		act.lsa_flags = osa.lsa_flags;
660 		act.lsa_restorer = osa.lsa_restorer;
661 		LINUX_SIGEMPTYSET(act.lsa_mask);
662 		act.lsa_mask.__bits[0] = osa.lsa_mask;
663 	}
664 
665 	error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL,
666 	    args->osa ? &oact : NULL);
667 
668 	if (args->osa != NULL && !error) {
669 		osa.lsa_handler = oact.lsa_handler;
670 		osa.lsa_flags = oact.lsa_flags;
671 		osa.lsa_restorer = oact.lsa_restorer;
672 		osa.lsa_mask = oact.lsa_mask.__bits[0];
673 		error = copyout(&osa, (caddr_t)args->osa,
674 		    sizeof(l_osigaction_t));
675 	}
676 
677 	return (error);
678 }
679 
680 /*
681  * Linux has two extra args, restart and oldmask.  We dont use these,
682  * but it seems that "restart" is actually a context pointer that
683  * enables the signal to happen with a different register set.
684  */
685 int
686 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args)
687 {
688 	struct sigsuspend_args bsd;
689 	sigset_t *sigmask;
690 	l_sigset_t mask;
691 	caddr_t sg = stackgap_init();
692 
693 #ifdef DEBUG
694 	if (ldebug(sigsuspend))
695 		printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
696 #endif
697 
698 	sigmask = stackgap_alloc(&sg, sizeof(sigset_t));
699 	LINUX_SIGEMPTYSET(mask);
700 	mask.__bits[0] = args->mask;
701 	linux_to_bsd_sigset(&mask, sigmask);
702 	bsd.sigmask = sigmask;
703 	return (sigsuspend(td, &bsd));
704 }
705 
706 int
707 linux_rt_sigsuspend(td, uap)
708 	struct thread *td;
709 	struct linux_rt_sigsuspend_args *uap;
710 {
711 	l_sigset_t lmask;
712 	sigset_t *bmask;
713 	struct sigsuspend_args bsd;
714 	caddr_t sg = stackgap_init();
715 	int error;
716 
717 #ifdef DEBUG
718 	if (ldebug(rt_sigsuspend))
719 		printf(ARGS(rt_sigsuspend, "%p, %d"),
720 		    (void *)uap->newset, uap->sigsetsize);
721 #endif
722 
723 	if (uap->sigsetsize != sizeof(l_sigset_t))
724 		return (EINVAL);
725 
726 	error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
727 	if (error)
728 		return (error);
729 
730 	bmask = stackgap_alloc(&sg, sizeof(sigset_t));
731 	linux_to_bsd_sigset(&lmask, bmask);
732 	bsd.sigmask = bmask;
733 	return (sigsuspend(td, &bsd));
734 }
735 
736 int
737 linux_pause(struct thread *td, struct linux_pause_args *args)
738 {
739 	struct proc *p = td->td_proc;
740 	struct sigsuspend_args bsd;
741 	sigset_t *sigmask;
742 	caddr_t sg = stackgap_init();
743 
744 #ifdef DEBUG
745 	if (ldebug(pause))
746 		printf(ARGS(pause, ""));
747 #endif
748 
749 	sigmask = stackgap_alloc(&sg, sizeof(sigset_t));
750 	PROC_LOCK(p);
751 	*sigmask = p->p_sigmask;
752 	PROC_UNLOCK(p);
753 	bsd.sigmask = sigmask;
754 	return (sigsuspend(td, &bsd));
755 }
756 
757 int
758 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
759 {
760 	struct sigaltstack_args bsd;
761 	stack_t *ss, *oss;
762 	l_stack_t lss;
763 	int error;
764 	caddr_t sg = stackgap_init();
765 
766 #ifdef DEBUG
767 	if (ldebug(sigaltstack))
768 		printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
769 #endif
770 
771 	if (uap->uss == NULL) {
772 		ss = NULL;
773 	} else {
774 		error = copyin(uap->uss, &lss, sizeof(l_stack_t));
775 		if (error)
776 			return (error);
777 
778 		ss = stackgap_alloc(&sg, sizeof(stack_t));
779 		ss->ss_sp = lss.ss_sp;
780 		ss->ss_size = lss.ss_size;
781 		ss->ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
782 	}
783 	oss = (uap->uoss != NULL)
784 	    ? stackgap_alloc(&sg, sizeof(stack_t))
785 	    : NULL;
786 
787 	bsd.ss = ss;
788 	bsd.oss = oss;
789 	error = sigaltstack(td, &bsd);
790 
791 	if (!error && oss != NULL) {
792 		lss.ss_sp = oss->ss_sp;
793 		lss.ss_size = oss->ss_size;
794 		lss.ss_flags = bsd_to_linux_sigaltstack(oss->ss_flags);
795 		error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
796 	}
797 
798 	return (error);
799 }
800