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