1 /*-
2 * Copyright (c) 2004 Tim J. Robbins
3 * Copyright (c) 2002 Doug Rabson
4 * Copyright (c) 2000 Marcel Moolenaar
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.51 2008/11/29 14:55:24 kib Exp $");
33
34 #include <sys/param.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 #include <sys/file.h>
38 #include <sys/fcntl.h>
39 #include <sys/clock.h>
40 #include <sys/imgact.h>
41 #include <sys/limits.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mman.h>
45 #include <sys/mutex.h>
46 #include <sys/priv.h>
47 #include <sys/proc.h>
48 #include <sys/resource.h>
49 #include <sys/resourcevar.h>
50 #include <sys/sched.h>
51 #include <sys/syscallsubr.h>
52 #include <sys/sysproto.h>
53 #include <sys/unistd.h>
54
55 #include <machine/frame.h>
56 #include <machine/pcb.h>
57 #include <machine/psl.h>
58 #include <machine/segments.h>
59 #include <machine/specialreg.h>
60
61 #include <vm/vm.h>
62 #include <vm/pmap.h>
63 #include <vm/vm_extern.h>
64 #include <vm/vm_kern.h>
65 #include <vm/vm_map.h>
66
67 #include <amd64/linux32/linux.h>
68 #include <amd64/linux32/linux32_proto.h>
69 #include <compat/linux/linux_ipc.h>
70 #include <compat/linux/linux_signal.h>
71 #include <compat/linux/linux_util.h>
72 #include <compat/linux/linux_emul.h>
73
74 struct l_old_select_argv {
75 l_int nfds;
76 l_uintptr_t readfds;
77 l_uintptr_t writefds;
78 l_uintptr_t exceptfds;
79 l_uintptr_t timeout;
80 } __packed;
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 /*
107 * Custom version of exec_copyin_args() so that we can translate
108 * the pointers.
109 */
110 static int
111 linux_exec_copyin_args(struct image_args *args, char *fname,
112 enum uio_seg segflg, char **argv, char **envv)
113 {
114 char *argp, *envp;
115 u_int32_t *p32, arg;
116 size_t length;
117 int error;
118
119 bzero(args, sizeof(*args));
120 if (argv == NULL)
121 return (EFAULT);
122
123 /*
124 * Allocate temporary demand zeroed space for argument and
125 * environment strings
126 */
127 args->buf = (char *)kmem_alloc_wait(exec_map,
128 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
129 if (args->buf == NULL)
130 return (ENOMEM);
131 args->begin_argv = args->buf;
132 args->endp = args->begin_argv;
133 args->stringspace = ARG_MAX;
134
135 args->fname = args->buf + ARG_MAX;
136
137 /*
138 * Copy the file name.
139 */
140 error = (segflg == UIO_SYSSPACE) ?
141 copystr(fname, args->fname, PATH_MAX, &length) :
142 copyinstr(fname, args->fname, PATH_MAX, &length);
143 if (error != 0)
144 goto err_exit;
145
146 /*
147 * extract arguments first
148 */
149 p32 = (u_int32_t *)argv;
150 for (;;) {
151 error = copyin(p32++, &arg, sizeof(arg));
152 if (error)
153 goto err_exit;
154 if (arg == 0)
155 break;
156 argp = PTRIN(arg);
157 error = copyinstr(argp, args->endp, args->stringspace, &length);
158 if (error) {
159 if (error == ENAMETOOLONG)
160 error = E2BIG;
161
162 goto err_exit;
163 }
164 args->stringspace -= length;
165 args->endp += length;
166 args->argc++;
167 }
168
169 args->begin_envv = args->endp;
170
171 /*
172 * extract environment strings
173 */
174 if (envv) {
175 p32 = (u_int32_t *)envv;
176 for (;;) {
177 error = copyin(p32++, &arg, sizeof(arg));
178 if (error)
179 goto err_exit;
180 if (arg == 0)
181 break;
182 envp = PTRIN(arg);
183 error = copyinstr(envp, args->endp, args->stringspace,
184 &length);
185 if (error) {
186 if (error == ENAMETOOLONG)
187 error = E2BIG;
188 goto err_exit;
189 }
190 args->stringspace -= length;
191 args->endp += length;
192 args->envc++;
193 }
194 }
195
196 return (0);
197
198 err_exit:
199 kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
200 PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
201 args->buf = NULL;
202 return (error);
203 }
204
205 int
206 linux_execve(struct thread *td, struct linux_execve_args *args)
207 {
208 struct image_args eargs;
209 char *path;
210 int error;
211
212 LCONVPATHEXIST(td, args->path, &path);
213
214 #ifdef DEBUG
215 if (ldebug(execve))
216 printf(ARGS(execve, "%s"), path);
217 #endif
218
219 error = linux_exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp,
220 args->envp);
221 free(path, M_TEMP);
222 if (error == 0)
223 error = kern_execve(td, &eargs, NULL);
224 if (error == 0)
225 /* Linux process can execute FreeBSD one, do not attempt
226 * to create emuldata for such process using
227 * linux_proc_init, this leads to a panic on KASSERT
228 * because such process has p->p_emuldata == NULL.
229 */
230 if (td->td_proc->p_sysent == &elf_linux_sysvec)
231 error = linux_proc_init(td, 0, 0);
232 return (error);
233 }
234
235 CTASSERT(sizeof(struct l_iovec32) == 8);
236
237 static int
238 linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop)
239 {
240 struct l_iovec32 iov32;
241 struct iovec *iov;
242 struct uio *uio;
243 uint32_t iovlen;
244 int error, i;
245
246 *uiop = NULL;
247 if (iovcnt > UIO_MAXIOV)
248 return (EINVAL);
249 iovlen = iovcnt * sizeof(struct iovec);
250 uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
251 iov = (struct iovec *)(uio + 1);
252 for (i = 0; i < iovcnt; i++) {
253 error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32));
254 if (error) {
255 free(uio, M_IOV);
256 return (error);
257 }
258 iov[i].iov_base = PTRIN(iov32.iov_base);
259 iov[i].iov_len = iov32.iov_len;
260 }
261 uio->uio_iov = iov;
262 uio->uio_iovcnt = iovcnt;
263 uio->uio_segflg = UIO_USERSPACE;
264 uio->uio_offset = -1;
265 uio->uio_resid = 0;
266 for (i = 0; i < iovcnt; i++) {
267 if (iov->iov_len > INT_MAX - uio->uio_resid) {
268 free(uio, M_IOV);
269 return (EINVAL);
270 }
271 uio->uio_resid += iov->iov_len;
272 iov++;
273 }
274 *uiop = uio;
275 return (0);
276 }
277
278 int
279 linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp,
280 int error)
281 {
282 struct l_iovec32 iov32;
283 struct iovec *iov;
284 uint32_t iovlen;
285 int i;
286
287 *iovp = NULL;
288 if (iovcnt > UIO_MAXIOV)
289 return (error);
290 iovlen = iovcnt * sizeof(struct iovec);
291 iov = malloc(iovlen, M_IOV, M_WAITOK);
292 for (i = 0; i < iovcnt; i++) {
293 error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32));
294 if (error) {
295 free(iov, M_IOV);
296 return (error);
297 }
298 iov[i].iov_base = PTRIN(iov32.iov_base);
299 iov[i].iov_len = iov32.iov_len;
300 }
301 *iovp = iov;
302 return(0);
303
304 }
305
306 int
307 linux_readv(struct thread *td, struct linux_readv_args *uap)
308 {
309 struct uio *auio;
310 int error;
311
312 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
313 if (error)
314 return (error);
315 error = kern_readv(td, uap->fd, auio);
316 free(auio, M_IOV);
317 return (error);
318 }
319
320 int
321 linux_writev(struct thread *td, struct linux_writev_args *uap)
322 {
323 struct uio *auio;
324 int error;
325
326 error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
327 if (error)
328 return (error);
329 error = kern_writev(td, uap->fd, auio);
330 free(auio, M_IOV);
331 return (error);
332 }
333
334 struct l_ipc_kludge {
335 l_uintptr_t msgp;
336 l_long msgtyp;
337 } __packed;
338
339 int
340 linux_ipc(struct thread *td, struct linux_ipc_args *args)
341 {
342
343 switch (args->what & 0xFFFF) {
344 case LINUX_SEMOP: {
345 struct linux_semop_args a;
346
347 a.semid = args->arg1;
348 a.tsops = args->ptr;
349 a.nsops = args->arg2;
350 return (linux_semop(td, &a));
351 }
352 case LINUX_SEMGET: {
353 struct linux_semget_args a;
354
355 a.key = args->arg1;
356 a.nsems = args->arg2;
357 a.semflg = args->arg3;
358 return (linux_semget(td, &a));
359 }
360 case LINUX_SEMCTL: {
361 struct linux_semctl_args a;
362 int error;
363
364 a.semid = args->arg1;
365 a.semnum = args->arg2;
366 a.cmd = args->arg3;
367 error = copyin(args->ptr, &a.arg, sizeof(a.arg));
368 if (error)
369 return (error);
370 return (linux_semctl(td, &a));
371 }
372 case LINUX_MSGSND: {
373 struct linux_msgsnd_args a;
374
375 a.msqid = args->arg1;
376 a.msgp = args->ptr;
377 a.msgsz = args->arg2;
378 a.msgflg = args->arg3;
379 return (linux_msgsnd(td, &a));
380 }
381 case LINUX_MSGRCV: {
382 struct linux_msgrcv_args a;
383
384 a.msqid = args->arg1;
385 a.msgsz = args->arg2;
386 a.msgflg = args->arg3;
387 if ((args->what >> 16) == 0) {
388 struct l_ipc_kludge tmp;
389 int error;
390
391 if (args->ptr == 0)
392 return (EINVAL);
393 error = copyin(args->ptr, &tmp, sizeof(tmp));
394 if (error)
395 return (error);
396 a.msgp = PTRIN(tmp.msgp);
397 a.msgtyp = tmp.msgtyp;
398 } else {
399 a.msgp = args->ptr;
400 a.msgtyp = args->arg5;
401 }
402 return (linux_msgrcv(td, &a));
403 }
404 case LINUX_MSGGET: {
405 struct linux_msgget_args a;
406
407 a.key = args->arg1;
408 a.msgflg = args->arg2;
409 return (linux_msgget(td, &a));
410 }
411 case LINUX_MSGCTL: {
412 struct linux_msgctl_args a;
413
414 a.msqid = args->arg1;
415 a.cmd = args->arg2;
416 a.buf = args->ptr;
417 return (linux_msgctl(td, &a));
418 }
419 case LINUX_SHMAT: {
420 struct linux_shmat_args a;
421
422 a.shmid = args->arg1;
423 a.shmaddr = args->ptr;
424 a.shmflg = args->arg2;
425 a.raddr = PTRIN((l_uint)args->arg3);
426 return (linux_shmat(td, &a));
427 }
428 case LINUX_SHMDT: {
429 struct linux_shmdt_args a;
430
431 a.shmaddr = args->ptr;
432 return (linux_shmdt(td, &a));
433 }
434 case LINUX_SHMGET: {
435 struct linux_shmget_args a;
436
437 a.key = args->arg1;
438 a.size = args->arg2;
439 a.shmflg = args->arg3;
440 return (linux_shmget(td, &a));
441 }
442 case LINUX_SHMCTL: {
443 struct linux_shmctl_args a;
444
445 a.shmid = args->arg1;
446 a.cmd = args->arg2;
447 a.buf = args->ptr;
448 return (linux_shmctl(td, &a));
449 }
450 default:
451 break;
452 }
453
454 return (EINVAL);
455 }
456
457 int
458 linux_old_select(struct thread *td, struct linux_old_select_args *args)
459 {
460 struct l_old_select_argv linux_args;
461 struct linux_select_args newsel;
462 int error;
463
464 #ifdef DEBUG
465 if (ldebug(old_select))
466 printf(ARGS(old_select, "%p"), args->ptr);
467 #endif
468
469 error = copyin(args->ptr, &linux_args, sizeof(linux_args));
470 if (error)
471 return (error);
472
473 newsel.nfds = linux_args.nfds;
474 newsel.readfds = PTRIN(linux_args.readfds);
475 newsel.writefds = PTRIN(linux_args.writefds);
476 newsel.exceptfds = PTRIN(linux_args.exceptfds);
477 newsel.timeout = PTRIN(linux_args.timeout);
478 return (linux_select(td, &newsel));
479 }
480
481 int
482 linux_fork(struct thread *td, struct linux_fork_args *args)
483 {
484 int error;
485 struct proc *p2;
486 struct thread *td2;
487
488 #ifdef DEBUG
489 if (ldebug(fork))
490 printf(ARGS(fork, ""));
491 #endif
492
493 if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2)) != 0)
494 return (error);
495
496 if (error == 0) {
497 td->td_retval[0] = p2->p_pid;
498 td->td_retval[1] = 0;
499 }
500
501 if (td->td_retval[1] == 1)
502 td->td_retval[0] = 0;
503 error = linux_proc_init(td, td->td_retval[0], 0);
504 if (error)
505 return (error);
506
507 td2 = FIRST_THREAD_IN_PROC(p2);
508
509 /*
510 * Make this runnable after we are finished with it.
511 */
512 thread_lock(td2);
513 TD_SET_CAN_RUN(td2);
514 sched_add(td2, SRQ_BORING);
515 thread_unlock(td2);
516
517 return (0);
518 }
519
520 int
521 linux_vfork(struct thread *td, struct linux_vfork_args *args)
522 {
523 int error;
524 struct proc *p2;
525 struct thread *td2;
526
527 #ifdef DEBUG
528 if (ldebug(vfork))
529 printf(ARGS(vfork, ""));
530 #endif
531
532 /* Exclude RFPPWAIT */
533 if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2)) != 0)
534 return (error);
535 if (error == 0) {
536 td->td_retval[0] = p2->p_pid;
537 td->td_retval[1] = 0;
538 }
539 /* Are we the child? */
540 if (td->td_retval[1] == 1)
541 td->td_retval[0] = 0;
542 error = linux_proc_init(td, td->td_retval[0], 0);
543 if (error)
544 return (error);
545
546 PROC_LOCK(p2);
547 p2->p_flag |= P_PPWAIT;
548 PROC_UNLOCK(p2);
549
550 td2 = FIRST_THREAD_IN_PROC(p2);
551
552 /*
553 * Make this runnable after we are finished with it.
554 */
555 thread_lock(td2);
556 TD_SET_CAN_RUN(td2);
557 sched_add(td2, SRQ_BORING);
558 thread_unlock(td2);
559
560 /* wait for the children to exit, ie. emulate vfork */
561 PROC_LOCK(p2);
562 while (p2->p_flag & P_PPWAIT)
563 msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
564 PROC_UNLOCK(p2);
565
566 return (0);
567 }
568
569 int
570 linux_clone(struct thread *td, struct linux_clone_args *args)
571 {
572 int error, ff = RFPROC | RFSTOPPED;
573 struct proc *p2;
574 struct thread *td2;
575 int exit_signal;
576 struct linux_emuldata *em;
577
578 #ifdef DEBUG
579 if (ldebug(clone)) {
580 printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, "
581 "child tid: %p"), (unsigned)args->flags,
582 args->stack, args->parent_tidptr, args->child_tidptr);
583 }
584 #endif
585
586 exit_signal = args->flags & 0x000000ff;
587 if (LINUX_SIG_VALID(exit_signal)) {
588 if (exit_signal <= LINUX_SIGTBLSZ)
589 exit_signal =
590 linux_to_bsd_signal[_SIG_IDX(exit_signal)];
591 } else if (exit_signal != 0)
592 return (EINVAL);
593
594 if (args->flags & LINUX_CLONE_VM)
595 ff |= RFMEM;
596 if (args->flags & LINUX_CLONE_SIGHAND)
597 ff |= RFSIGSHARE;
598 /*
599 * XXX: In Linux, sharing of fs info (chroot/cwd/umask)
600 * and open files is independant. In FreeBSD, its in one
601 * structure but in reality it does not cause any problems
602 * because both of these flags are usually set together.
603 */
604 if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
605 ff |= RFFDG;
606
607 /*
608 * Attempt to detect when linux_clone(2) is used for creating
609 * kernel threads. Unfortunately despite the existence of the
610 * CLONE_THREAD flag, version of linuxthreads package used in
611 * most popular distros as of beginning of 2005 doesn't make
612 * any use of it. Therefore, this detection relies on
613 * empirical observation that linuxthreads sets certain
614 * combination of flags, so that we can make more or less
615 * precise detection and notify the FreeBSD kernel that several
616 * processes are in fact part of the same threading group, so
617 * that special treatment is necessary for signal delivery
618 * between those processes and fd locking.
619 */
620 if ((args->flags & 0xffffff00) == LINUX_THREADING_FLAGS)
621 ff |= RFTHREAD;
622
623 if (args->flags & LINUX_CLONE_PARENT_SETTID)
624 if (args->parent_tidptr == NULL)
625 return (EINVAL);
626
627 error = fork1(td, ff, 0, &p2);
628 if (error)
629 return (error);
630
631 if (args->flags & (LINUX_CLONE_PARENT | LINUX_CLONE_THREAD)) {
632 sx_xlock(&proctree_lock);
633 PROC_LOCK(p2);
634 proc_reparent(p2, td->td_proc->p_pptr);
635 PROC_UNLOCK(p2);
636 sx_xunlock(&proctree_lock);
637 }
638
639 /* create the emuldata */
640 error = linux_proc_init(td, p2->p_pid, args->flags);
641 /* reference it - no need to check this */
642 em = em_find(p2, EMUL_DOLOCK);
643 KASSERT(em != NULL, ("clone: emuldata not found.\n"));
644 /* and adjust it */
645
646 if (args->flags & LINUX_CLONE_THREAD) {
647 #ifdef notyet
648 PROC_LOCK(p2);
649 p2->p_pgrp = td->td_proc->p_pgrp;
650 PROC_UNLOCK(p2);
651 #endif
652 exit_signal = 0;
653 }
654
655 if (args->flags & LINUX_CLONE_CHILD_SETTID)
656 em->child_set_tid = args->child_tidptr;
657 else
658 em->child_set_tid = NULL;
659
660 if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
661 em->child_clear_tid = args->child_tidptr;
662 else
663 em->child_clear_tid = NULL;
664
665 EMUL_UNLOCK(&emul_lock);
666
667 if (args->flags & LINUX_CLONE_PARENT_SETTID) {
668 error = copyout(&p2->p_pid, args->parent_tidptr,
669 sizeof(p2->p_pid));
670 if (error)
671 printf(LMSG("copyout failed!"));
672 }
673
674 PROC_LOCK(p2);
675 p2->p_sigparent = exit_signal;
676 PROC_UNLOCK(p2);
677 td2 = FIRST_THREAD_IN_PROC(p2);
678 /*
679 * In a case of stack = NULL, we are supposed to COW calling process
680 * stack. This is what normal fork() does, so we just keep tf_rsp arg
681 * intact.
682 */
683 if (args->stack)
684 td2->td_frame->tf_rsp = PTROUT(args->stack);
685
686 if (args->flags & LINUX_CLONE_SETTLS) {
687 struct user_segment_descriptor sd;
688 struct l_user_desc info;
689 int a[2];
690
691 error = copyin((void *)td->td_frame->tf_rsi, &info,
692 sizeof(struct l_user_desc));
693 if (error) {
694 printf(LMSG("copyin failed!"));
695 } else {
696 /* We might copy out the entry_number as GUGS32_SEL. */
697 info.entry_number = GUGS32_SEL;
698 error = copyout(&info, (void *)td->td_frame->tf_rsi,
699 sizeof(struct l_user_desc));
700 if (error)
701 printf(LMSG("copyout failed!"));
702
703 a[0] = LINUX_LDT_entry_a(&info);
704 a[1] = LINUX_LDT_entry_b(&info);
705
706 memcpy(&sd, &a, sizeof(a));
707 #ifdef DEBUG
708 if (ldebug(clone))
709 printf("Segment created in clone with "
710 "CLONE_SETTLS: lobase: %x, hibase: %x, "
711 "lolimit: %x, hilimit: %x, type: %i, "
712 "dpl: %i, p: %i, xx: %i, long: %i, "
713 "def32: %i, gran: %i\n", sd.sd_lobase,
714 sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit,
715 sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx,
716 sd.sd_long, sd.sd_def32, sd.sd_gran);
717 #endif
718 td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
719 td2->td_pcb->pcb_gs32sd = sd;
720 td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
721 td2->td_pcb->pcb_flags |= PCB_GS32BIT | PCB_32BIT;
722 }
723 }
724
725 #ifdef DEBUG
726 if (ldebug(clone))
727 printf(LMSG("clone: successful rfork to %d, "
728 "stack %p sig = %d"), (int)p2->p_pid, args->stack,
729 exit_signal);
730 #endif
731 if (args->flags & LINUX_CLONE_VFORK) {
732 PROC_LOCK(p2);
733 p2->p_flag |= P_PPWAIT;
734 PROC_UNLOCK(p2);
735 }
736
737 /*
738 * Make this runnable after we are finished with it.
739 */
740 thread_lock(td2);
741 TD_SET_CAN_RUN(td2);
742 sched_add(td2, SRQ_BORING);
743 thread_unlock(td2);
744
745 td->td_retval[0] = p2->p_pid;
746 td->td_retval[1] = 0;
747
748 if (args->flags & LINUX_CLONE_VFORK) {
749 /* wait for the children to exit, ie. emulate vfork */
750 PROC_LOCK(p2);
751 while (p2->p_flag & P_PPWAIT)
752 msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
753 PROC_UNLOCK(p2);
754 }
755
756 return (0);
757 }
758
759 #define STACK_SIZE (2 * 1024 * 1024)
760 #define GUARD_SIZE (4 * PAGE_SIZE)
761
762 static int linux_mmap_common(struct thread *, struct l_mmap_argv *);
763
764 int
765 linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
766 {
767 struct l_mmap_argv linux_args;
768
769 #ifdef DEBUG
770 if (ldebug(mmap2))
771 printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"),
772 args->addr, args->len, args->prot,
773 args->flags, args->fd, args->pgoff);
774 #endif
775
776 linux_args.addr = PTROUT(args->addr);
777 linux_args.len = args->len;
778 linux_args.prot = args->prot;
779 linux_args.flags = args->flags;
780 linux_args.fd = |