1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2004 Tim J. Robbins 5 * Copyright (c) 2002 Doug Rabson 6 * Copyright (c) 2000 Marcel Moolenaar 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer 14 * in this position and unchanged. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 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$"); 33 34 #include "opt_compat.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/imgact.h> 39 #include <sys/ktr.h> 40 #include <sys/lock.h> 41 #include <sys/mutex.h> 42 #include <sys/proc.h> 43 #include <sys/racct.h> 44 #include <sys/sched.h> 45 #include <sys/syscallsubr.h> 46 #include <sys/sx.h> 47 #include <sys/umtx.h> 48 #include <sys/unistd.h> 49 #include <sys/wait.h> 50 51 #include <vm/vm.h> 52 #include <vm/pmap.h> 53 #include <vm/vm_map.h> 54 55 #ifdef COMPAT_LINUX32 56 #include <machine/../linux32/linux.h> 57 #include <machine/../linux32/linux32_proto.h> 58 #else 59 #include <machine/../linux/linux.h> 60 #include <machine/../linux/linux_proto.h> 61 #endif 62 #include <compat/linux/linux_emul.h> 63 #include <compat/linux/linux_futex.h> 64 #include <compat/linux/linux_misc.h> 65 #include <compat/linux/linux_util.h> 66 67 #ifdef LINUX_LEGACY_SYSCALLS 68 int 69 linux_fork(struct thread *td, struct linux_fork_args *args) 70 { 71 struct fork_req fr; 72 int error; 73 struct proc *p2; 74 struct thread *td2; 75 76 #ifdef DEBUG 77 if (ldebug(fork)) 78 printf(ARGS(fork, "")); 79 #endif 80 81 bzero(&fr, sizeof(fr)); 82 fr.fr_flags = RFFDG | RFPROC | RFSTOPPED; 83 fr.fr_procp = &p2; 84 if ((error = fork1(td, &fr)) != 0) 85 return (error); 86 87 td2 = FIRST_THREAD_IN_PROC(p2); 88 89 linux_proc_init(td, td2, 0); 90 91 td->td_retval[0] = p2->p_pid; 92 93 /* 94 * Make this runnable after we are finished with it. 95 */ 96 thread_lock(td2); 97 TD_SET_CAN_RUN(td2); 98 sched_add(td2, SRQ_BORING); 99 thread_unlock(td2); 100 101 return (0); 102 } 103 104 int 105 linux_vfork(struct thread *td, struct linux_vfork_args *args) 106 { 107 struct fork_req fr; 108 int error; 109 struct proc *p2; 110 struct thread *td2; 111 112 #ifdef DEBUG 113 if (ldebug(vfork)) 114 printf(ARGS(vfork, "")); 115 #endif 116 117 bzero(&fr, sizeof(fr)); 118 fr.fr_flags = RFFDG | RFPROC | RFMEM | RFPPWAIT | RFSTOPPED; 119 fr.fr_procp = &p2; 120 if ((error = fork1(td, &fr)) != 0) 121 return (error); 122 123 td2 = FIRST_THREAD_IN_PROC(p2); 124 125 linux_proc_init(td, td2, 0); 126 127 td->td_retval[0] = p2->p_pid; 128 129 /* 130 * Make this runnable after we are finished with it. 131 */ 132 thread_lock(td2); 133 TD_SET_CAN_RUN(td2); 134 sched_add(td2, SRQ_BORING); 135 thread_unlock(td2); 136 137 return (0); 138 } 139 #endif 140 141 static int 142 linux_clone_proc(struct thread *td, struct linux_clone_args *args) 143 { 144 struct fork_req fr; 145 int error, ff = RFPROC | RFSTOPPED; 146 struct proc *p2; 147 struct thread *td2; 148 int exit_signal; 149 struct linux_emuldata *em; 150 151 #ifdef DEBUG 152 if (ldebug(clone)) { 153 printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, " 154 "child tid: %p"), (unsigned)args->flags, 155 args->stack, args->parent_tidptr, args->child_tidptr); 156 } 157 #endif 158 159 exit_signal = args->flags & 0x000000ff; 160 if (LINUX_SIG_VALID(exit_signal)) { 161 exit_signal = linux_to_bsd_signal(exit_signal); 162 } else if (exit_signal != 0) 163 return (EINVAL); 164 165 if (args->flags & LINUX_CLONE_VM) 166 ff |= RFMEM; 167 if (args->flags & LINUX_CLONE_SIGHAND) 168 ff |= RFSIGSHARE; 169 /* 170 * XXX: In Linux, sharing of fs info (chroot/cwd/umask) 171 * and open files is independent. In FreeBSD, its in one 172 * structure but in reality it does not cause any problems 173 * because both of these flags are usually set together. 174 */ 175 if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS))) 176 ff |= RFFDG; 177 178 if (args->flags & LINUX_CLONE_PARENT_SETTID) 179 if (args->parent_tidptr == NULL) 180 return (EINVAL); 181 182 if (args->flags & LINUX_CLONE_VFORK) 183 ff |= RFPPWAIT; 184 185 bzero(&fr, sizeof(fr)); 186 fr.fr_flags = ff; 187 fr.fr_procp = &p2; 188 error = fork1(td, &fr); 189 if (error) 190 return (error); 191 192 td2 = FIRST_THREAD_IN_PROC(p2); 193 194 /* create the emuldata */ 195 linux_proc_init(td, td2, args->flags); 196 197 em = em_find(td2); 198 KASSERT(em != NULL, ("clone_proc: emuldata not found.\n")); 199 200 if (args->flags & LINUX_CLONE_CHILD_SETTID) 201 em->child_set_tid = args->child_tidptr; 202 else 203 em->child_set_tid = NULL; 204 205 if (args->flags & LINUX_CLONE_CHILD_CLEARTID) 206 em->child_clear_tid = args->child_tidptr; 207 else 208 em->child_clear_tid = NULL; 209 210 if (args->flags & LINUX_CLONE_PARENT_SETTID) { 211 error = copyout(&p2->p_pid, args->parent_tidptr, 212 sizeof(p2->p_pid)); 213 if (error) 214 printf(LMSG("copyout failed!")); 215 } 216 217 PROC_LOCK(p2); 218 p2->p_sigparent = exit_signal; 219 PROC_UNLOCK(p2); 220 /* 221 * In a case of stack = NULL, we are supposed to COW calling process 222 * stack. This is what normal fork() does, so we just keep tf_rsp arg 223 * intact. 224 */ 225 linux_set_upcall_kse(td2, PTROUT(args->stack)); 226 227 if (args->flags & LINUX_CLONE_SETTLS) 228 linux_set_cloned_tls(td2, args->tls); 229 230 /* 231 * If CLONE_PARENT is set, then the parent of the new process will be 232 * the same as that of the calling process. 233 */ 234 if (args->flags & LINUX_CLONE_PARENT) { 235 sx_xlock(&proctree_lock); 236 PROC_LOCK(p2); 237 proc_reparent(p2, td->td_proc->p_pptr); 238 PROC_UNLOCK(p2); 239 sx_xunlock(&proctree_lock); 240 } 241 242 #ifdef DEBUG 243 if (ldebug(clone)) 244 printf(LMSG("clone: successful rfork to %d, " 245 "stack %p sig = %d"), (int)p2->p_pid, args->stack, 246 exit_signal); 247 #endif 248 249 /* 250 * Make this runnable after we are finished with it. 251 */ 252 thread_lock(td2); 253 TD_SET_CAN_RUN(td2); 254 sched_add(td2, SRQ_BORING); 255 thread_unlock(td2); 256 257 td->td_retval[0] = p2->p_pid; 258 259 return (0); 260 } 261 262 static int 263 linux_clone_thread(struct thread *td, struct linux_clone_args *args) 264 { 265 struct linux_emuldata *em; 266 struct thread *newtd; 267 struct proc *p; 268 int error; 269 270 #ifdef DEBUG 271 if (ldebug(clone)) { 272 printf(ARGS(clone, "thread: flags %x, stack %p, parent tid: %p, " 273 "child tid: %p"), (unsigned)args->flags, 274 args->stack, args->parent_tidptr, args->child_tidptr); 275 } 276 #endif 277 278 LINUX_CTR4(clone_thread, "thread(%d) flags %x ptid %p ctid %p", 279 td->td_tid, (unsigned)args->flags, 280 args->parent_tidptr, args->child_tidptr); 281 282 if (args->flags & LINUX_CLONE_PARENT_SETTID) 283 if (args->parent_tidptr == NULL) 284 return (EINVAL); 285 286 /* Threads should be created with own stack */ 287 if (args->stack == NULL) 288 return (EINVAL); 289 290 p = td->td_proc; 291 292 #ifdef RACCT 293 if (racct_enable) { 294 PROC_LOCK(p); 295 error = racct_add(p, RACCT_NTHR, 1); 296 PROC_UNLOCK(p); 297 if (error != 0) 298 return (EPROCLIM); 299 } 300 #endif 301 302 /* Initialize our td */ 303 error = kern_thr_alloc(p, 0, &newtd); 304 if (error) 305 goto fail; 306 307 cpu_copy_thread(newtd, td); 308 309 bzero(&newtd->td_startzero, 310 __rangeof(struct thread, td_startzero, td_endzero)); 311 bcopy(&td->td_startcopy, &newtd->td_startcopy, 312 __rangeof(struct thread, td_startcopy, td_endcopy)); 313 314 newtd->td_proc = p; 315 thread_cow_get(newtd, td); 316 317 /* create the emuldata */ 318 linux_proc_init(td, newtd, args->flags); 319 320 em = em_find(newtd); 321 KASSERT(em != NULL, ("clone_thread: emuldata not found.\n")); 322 323 if (args->flags & LINUX_CLONE_SETTLS) 324 linux_set_cloned_tls(newtd, args->tls); 325 326 if (args->flags & LINUX_CLONE_CHILD_SETTID) 327 em->child_set_tid = args->child_tidptr; 328 else 329 em->child_set_tid = NULL; 330 331 if (args->flags & LINUX_CLONE_CHILD_CLEARTID) 332 em->child_clear_tid = args->child_tidptr; 333 else 334 em->child_clear_tid = NULL; 335 336 cpu_thread_clean(newtd); 337 338 linux_set_upcall_kse(newtd, PTROUT(args->stack)); 339 340 PROC_LOCK(p); 341 p->p_flag |= P_HADTHREADS; 342 bcopy(p->p_comm, newtd->td_name, sizeof(newtd->td_name)); 343 344 if (args->flags & LINUX_CLONE_PARENT) 345 thread_link(newtd, p->p_pptr); 346 else 347 thread_link(newtd, p); 348 349 thread_lock(td); 350 /* let the scheduler know about these things. */ 351 sched_fork_thread(td, newtd); 352 thread_unlock(td); 353 if (P_SHOULDSTOP(p)) 354 newtd->td_flags |= TDF_ASTPENDING | TDF_NEEDSUSPCHK; 355 PROC_UNLOCK(p); 356 357 tidhash_add(newtd); 358 359 #ifdef DEBUG 360 if (ldebug(clone)) 361 printf(ARGS(clone, "successful clone to %d, stack %p"), 362 (int)newtd->td_tid, args->stack); 363 #endif 364 365 LINUX_CTR2(clone_thread, "thread(%d) successful clone to %d", 366 td->td_tid, newtd->td_tid); 367 368 if (args->flags & LINUX_CLONE_PARENT_SETTID) { 369 error = copyout(&newtd->td_tid, args->parent_tidptr, 370 sizeof(newtd->td_tid)); 371 if (error) 372 printf(LMSG("clone_thread: copyout failed!")); 373 } 374 375 /* 376 * Make this runnable after we are finished with it. 377 */ 378 thread_lock(newtd); 379 TD_SET_CAN_RUN(newtd); 380 sched_add(newtd, SRQ_BORING); 381 thread_unlock(newtd); 382 383 td->td_retval[0] = newtd->td_tid; 384 385 return (0); 386 387 fail: 388 #ifdef RACCT 389 if (racct_enable) { 390 PROC_LOCK(p); 391 racct_sub(p, RACCT_NTHR, 1); 392 PROC_UNLOCK(p); 393 } 394 #endif 395 return (error); 396 } 397 398 int 399 linux_clone(struct thread *td, struct linux_clone_args *args) 400 { 401 402 if (args->flags & LINUX_CLONE_THREAD) 403 return (linux_clone_thread(td, args)); 404 else 405 return (linux_clone_proc(td, args)); 406 } 407 408 int 409 linux_exit(struct thread *td, struct linux_exit_args *args) 410 { 411 struct linux_emuldata *em; 412 413 em = em_find(td); 414 KASSERT(em != NULL, ("exit: emuldata not found.\n")); 415 416 LINUX_CTR2(exit, "thread(%d) (%d)", em->em_tid, args->rval); 417 418 umtx_thread_exit(td); 419 420 linux_thread_detach(td); 421 422 /* 423 * XXX. When the last two threads of a process 424 * exit via pthread_exit() try thr_exit() first. 425 */ 426 kern_thr_exit(td); 427 exit1(td, args->rval, 0); 428 /* NOTREACHED */ 429 } 430 431 int 432 linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args) 433 { 434 struct linux_emuldata *em; 435 436 em = em_find(td); 437 KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n")); 438 439 em->child_clear_tid = args->tidptr; 440 441 td->td_retval[0] = em->em_tid; 442 443 LINUX_CTR3(set_tid_address, "tidptr(%d) %p, returns %d", 444 em->em_tid, args->tidptr, td->td_retval[0]); 445 446 return (0); 447 } 448 449 void 450 linux_thread_detach(struct thread *td) 451 { 452 struct linux_sys_futex_args cup; 453 struct linux_emuldata *em; 454 int *child_clear_tid; 455 int error; 456 457 em = em_find(td); 458 KASSERT(em != NULL, ("thread_detach: emuldata not found.\n")); 459 460 LINUX_CTR1(thread_detach, "thread(%d)", em->em_tid); 461 462 release_futexes(td, em); 463 464 child_clear_tid = em->child_clear_tid; 465 466 if (child_clear_tid != NULL) { 467 468 LINUX_CTR2(thread_detach, "thread(%d) %p", 469 em->em_tid, child_clear_tid); 470 471 error = suword32(child_clear_tid, 0); 472 if (error != 0) 473 return; 474 475 cup.uaddr = child_clear_tid; 476 cup.op = LINUX_FUTEX_WAKE; 477 cup.val = 1; /* wake one */ 478 cup.timeout = NULL; 479 cup.uaddr2 = NULL; 480 cup.val3 = 0; 481 error = linux_sys_futex(td, &cup); 482 /* 483 * this cannot happen at the moment and if this happens it 484 * probably means there is a user space bug 485 */ 486 if (error != 0) 487 linux_msg(td, "futex stuff in thread_detach failed."); 488 } 489 } 490