1 /* $NetBSD: linux32_unistd.c,v 1.31 2009/03/15 15:56:50 cegger Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 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. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Emmanuel Dreyfus 17 * 4. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 36 __KERNEL_RCSID(0, "$NetBSD: linux32_unistd.c,v 1.31 2009/03/15 15:56:50 cegger Exp $"); 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/fstypes.h> 41 #include <sys/signal.h> 42 #include <sys/dirent.h> 43 #include <sys/kernel.h> 44 #include <sys/fcntl.h> 45 #include <sys/select.h> 46 #include <sys/proc.h> 47 #include <sys/ucred.h> 48 #include <sys/swap.h> 49 #include <sys/kauth.h> 50 51 #include <machine/types.h> 52 53 #include <sys/syscallargs.h> 54 55 #include <compat/netbsd32/netbsd32.h> 56 #include <compat/netbsd32/netbsd32_conv.h> 57 58 #include <compat/linux/common/linux_types.h> 59 #include <compat/linux/common/linux_signal.h> 60 #include <compat/linux/common/linux_machdep.h> 61 #include <compat/linux/common/linux_misc.h> 62 #include <compat/linux/common/linux_oldolduname.h> 63 #include <compat/linux/common/linux_ipc.h> 64 #include <compat/linux/common/linux_sem.h> 65 #include <compat/linux/linux_syscallargs.h> 66 67 #include <compat/linux32/common/linux32_types.h> 68 #include <compat/linux32/common/linux32_signal.h> 69 #include <compat/linux32/common/linux32_machdep.h> 70 #include <compat/linux32/common/linux32_sysctl.h> 71 #include <compat/linux32/common/linux32_socketcall.h> 72 #include <compat/linux32/linux32_syscallargs.h> 73 74 static int linux32_select1(struct lwp *, register_t *, 75 int, fd_set *, fd_set *, fd_set *, struct timeval *); 76 77 int 78 linux32_sys_brk(struct lwp *l, const struct linux32_sys_brk_args *uap, register_t *retval) 79 { 80 /* { 81 syscallarg(netbsd32_charp) nsize; 82 } */ 83 struct linux_sys_brk_args ua; 84 85 NETBSD32TOP_UAP(nsize, char); 86 return linux_sys_brk(l, &ua, retval); 87 } 88 89 int 90 linux32_sys_llseek(struct lwp *l, const struct linux32_sys_llseek_args *uap, register_t *retval) 91 { 92 /* { 93 syscallarg(int) fd; 94 syscallarg(u_int32_t) ohigh; 95 syscallarg(u_int32_t) olow; 96 syscallarg(netbsd32_voidp) res; 97 syscallarg(int) whence; 98 } */ 99 struct linux_sys_llseek_args ua; 100 101 NETBSD32TO64_UAP(fd); 102 NETBSD32TO64_UAP(ohigh); 103 NETBSD32TO64_UAP(olow); 104 NETBSD32TOP_UAP(res, void); 105 NETBSD32TO64_UAP(whence); 106 107 return linux_sys_llseek(l, &ua, retval); 108 } 109 110 int 111 linux32_sys_select(struct lwp *l, const struct linux32_sys_select_args *uap, register_t *retval) 112 { 113 /* { 114 syscallarg(int) nfds; 115 syscallarg(netbsd32_fd_setp_t) readfds; 116 syscallarg(netbsd32_fd_setp_t) writefds; 117 syscallarg(netbsd32_fd_setp_t) exceptfds; 118 syscallarg(netbsd32_timeval50p_t) timeout; 119 } */ 120 121 return linux32_select1(l, retval, SCARG(uap, nfds), 122 SCARG_P32(uap, readfds), 123 SCARG_P32(uap, writefds), 124 SCARG_P32(uap, exceptfds), 125 SCARG_P32(uap, timeout)); 126 } 127 128 int 129 linux32_sys_oldselect(struct lwp *l, const struct linux32_sys_oldselect_args *uap, register_t *retval) 130 { 131 /* { 132 syscallarg(linux32_oldselectp_t) lsp; 133 } */ 134 struct linux32_oldselect lsp32; 135 int error; 136 137 if ((error = copyin(SCARG_P32(uap, lsp), &lsp32, sizeof(lsp32))) != 0) 138 return error; 139 140 return linux32_select1(l, retval, lsp32.nfds, 141 NETBSD32PTR64(lsp32.readfds), NETBSD32PTR64(lsp32.writefds), 142 NETBSD32PTR64(lsp32.exceptfds), NETBSD32PTR64(lsp32.timeout)); 143 } 144 145 static int 146 linux32_select1(struct lwp *l, register_t *retval, int nfds, 147 fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 148 struct timeval *timeout) 149 { 150 struct timeval tv0, tv1, utv, *tv = NULL; 151 struct netbsd32_timeval50 utv32; 152 int error; 153 154 timerclear(&utv); /* XXX GCC4 */ 155 156 /* 157 * Store current time for computation of the amount of 158 * time left. 159 */ 160 if (timeout) { 161 if ((error = copyin(timeout, &utv32, sizeof(utv32)))) 162 return error; 163 164 netbsd32_to_timeval50(&utv32, &utv); 165 166 if (itimerfix(&utv)) { 167 /* 168 * The timeval was invalid. Convert it to something 169 * valid that will act as it does under Linux. 170 */ 171 utv.tv_sec += utv.tv_usec / 1000000; 172 utv.tv_usec %= 1000000; 173 if (utv.tv_usec < 0) { 174 utv.tv_sec -= 1; 175 utv.tv_usec += 1000000; 176 } 177 if (utv.tv_sec < 0) 178 timerclear(&utv); 179 } 180 microtime(&tv0); 181 tv = &utv; 182 } 183 184 error = selcommon(l, retval, nfds, 185 readfds, writefds, exceptfds, tv, NULL); 186 187 if (error) { 188 /* 189 * See fs/select.c in the Linux kernel. Without this, 190 * Maelstrom doesn't work. 191 */ 192 if (error == ERESTART) 193 error = EINTR; 194 return error; 195 } 196 197 if (timeout) { 198 if (*retval) { 199 /* 200 * Compute how much time was left of the timeout, 201 * by subtracting the current time and the time 202 * before we started the call, and subtracting 203 * that result from the user-supplied value. 204 */ 205 microtime(&tv1); 206 timersub(&tv1, &tv0, &tv1); 207 timersub(&utv, &tv1, &utv); 208 if (utv.tv_sec < 0) 209 timerclear(&utv); 210 } else { 211 timerclear(&utv); 212 } 213 214 netbsd32_from_timeval50(&utv, &utv32); 215 216 if ((error = copyout(&utv32, timeout, sizeof(utv32)))) 217 return error; 218 } 219 220 return 0; 221 } 222 223 int 224 linux32_sys_pipe(struct lwp *l, const struct linux32_sys_pipe_args *uap, register_t *retval) 225 { 226 /* { 227 syscallarg(netbsd32_intp) fd; 228 } */ 229 int error; 230 int pfds[2]; 231 232 if ((error = sys_pipe(l, 0, retval))) 233 return error; 234 235 pfds[0] = (int)retval[0]; 236 pfds[1] = (int)retval[1]; 237 238 if ((error = copyout(pfds, SCARG_P32(uap, fd), 2 * sizeof (int))) != 0) 239 return error; 240 241 retval[0] = 0; 242 retval[1] = 0; 243 244 return 0; 245 } 246 247 248 int 249 linux32_sys_unlink(struct lwp *l, const struct linux32_sys_unlink_args *uap, register_t *retval) 250 { 251 /* { 252 syscallarg(const netbsd32_charp) path; 253 } */ 254 struct linux_sys_unlink_args ua; 255 256 NETBSD32TOP_UAP(path, const char); 257 258 return linux_sys_unlink(l, &ua, retval); 259 } 260 261 int 262 linux32_sys_creat(struct lwp *l, const struct linux32_sys_creat_args *uap, register_t *retval) 263 { 264 /* { 265 syscallarg(const netbsd32_charp) path; 266 syscallarg(int) mode; 267 } */ 268 struct sys_open_args ua; 269 270 NETBSD32TOP_UAP(path, const char); 271 SCARG(&ua, flags) = O_CREAT | O_TRUNC | O_WRONLY; 272 NETBSD32TO64_UAP(mode); 273 274 return sys_open(l, &ua, retval); 275 } 276 277 int 278 linux32_sys_mknod(struct lwp *l, const struct linux32_sys_mknod_args *uap, register_t *retval) 279 { 280 /* { 281 syscallarg(const netbsd32_charp) path; 282 syscallarg(int) mode; 283 syscallarg(int) dev; 284 } */ 285 struct linux_sys_mknod_args ua; 286 287 NETBSD32TOP_UAP(path, const char); 288 NETBSD32TO64_UAP(mode); 289 NETBSD32TO64_UAP(dev); 290 291 return linux_sys_mknod(l, &ua, retval); 292 } 293 294 int 295 linux32_sys_break(struct lwp *l, const struct linux32_sys_break_args *uap, register_t *retval) 296 { 297 #if 0 298 /* { 299 syscallarg(const netbsd32_charp) nsize; 300 } */ 301 #endif 302 303 return ENOSYS; 304 } 305 306 int 307 linux32_sys_swapon(struct lwp *l, const struct linux32_sys_swapon_args *uap, register_t *retval) 308 { 309 /* { 310 syscallarg(const netbsd32_charp) name; 311 } */ 312 struct sys_swapctl_args ua; 313 314 SCARG(&ua, cmd) = SWAP_ON; 315 SCARG(&ua, arg) = SCARG_P32(uap, name); 316 SCARG(&ua, misc) = 0; /* priority */ 317 return (sys_swapctl(l, &ua, retval)); 318 } 319 320 int 321 linux32_sys_swapoff(struct lwp *l, const struct linux32_sys_swapoff_args *uap, register_t *retval) 322 { 323 /* { 324 syscallarg(const netbsd32_charp) path; 325 } */ 326 struct sys_swapctl_args ua; 327 328 SCARG(&ua, cmd) = SWAP_OFF; 329 SCARG(&ua, arg) = SCARG_P32(uap, path); 330 SCARG(&ua, misc) = 0; /* priority */ 331 return (sys_swapctl(l, &ua, retval)); 332 } 333 334 335 int 336 linux32_sys_reboot(struct lwp *l, const struct linux32_sys_reboot_args *uap, register_t *retval) 337 { 338 /* { 339 syscallarg(int) magic1; 340 syscallarg(int) magic2; 341 syscallarg(int) cmd; 342 syscallarg(netbsd32_voidp) arg; 343 } */ 344 struct linux_sys_reboot_args ua; 345 346 NETBSD32TO64_UAP(magic1); 347 NETBSD32TO64_UAP(magic2); 348 NETBSD32TO64_UAP(cmd); 349 NETBSD32TOP_UAP(arg, void); 350 351 return linux_sys_reboot(l, &ua, retval); 352 } 353 354 int 355 linux32_sys_setresuid(struct lwp *l, const struct linux32_sys_setresuid_args *uap, register_t *retval) 356 { 357 /* { 358 syscallarg(uid_t) ruid; 359 syscallarg(uid_t) euid; 360 syscallarg(uid_t) suid; 361 } */ 362 struct linux_sys_setresuid_args ua; 363 364 NETBSD32TO64_UAP(ruid); 365 NETBSD32TO64_UAP(euid); 366 NETBSD32TO64_UAP(suid); 367 368 return linux_sys_setresuid(l, &ua, retval); 369 } 370 371 int 372 linux32_sys_getresuid(struct lwp *l, const struct linux32_sys_getresuid_args *uap, register_t *retval) 373 { 374 /* { 375 syscallarg(linux32_uidp_t) ruid; 376 syscallarg(linux32_uidp_t) euid; 377 syscallarg(linux32_uidp_t) suid; 378 } */ 379 kauth_cred_t pc = l->l_cred; 380 int error; 381 uid_t uid; 382 383 uid = kauth_cred_getuid(pc); 384 if ((error = copyout(&uid, SCARG_P32(uap, ruid), sizeof(uid_t))) != 0) 385 return error; 386 387 uid = kauth_cred_geteuid(pc); 388 if ((error = copyout(&uid, SCARG_P32(uap, euid), sizeof(uid_t))) != 0) 389 return error; 390 391 uid = kauth_cred_getsvuid(pc); 392 return copyout(&uid, SCARG_P32(uap, suid), sizeof(uid_t)); 393 } 394 395 int 396 linux32_sys_setresgid(struct lwp *l, const struct linux32_sys_setresgid_args *uap, register_t *retval) 397 { 398 /* { 399 syscallarg(gid_t) rgid; 400 syscallarg(gid_t) egid; 401 syscallarg(gid_t) sgid; 402 } */ 403 struct linux_sys_setresgid_args ua; 404 405 NETBSD32TO64_UAP(rgid); 406 NETBSD32TO64_UAP(egid); 407 NETBSD32TO64_UAP(sgid); 408 409 return linux_sys_setresgid(l, &ua, retval); 410 } 411 412 int 413 linux32_sys_getresgid(struct lwp *l, const struct linux32_sys_getresgid_args *uap, register_t *retval) 414 { 415 /* { 416 syscallarg(linux32_gidp_t) rgid; 417 syscallarg(linux32_gidp_t) egid; 418 syscallarg(linux32_gidp_t) sgid; 419 } */ 420 kauth_cred_t pc = l->l_cred; 421 int error; 422 gid_t gid; 423 424 gid = kauth_cred_getgid(pc); 425 if ((error = copyout(&gid, SCARG_P32(uap, rgid), sizeof(gid_t))) != 0) 426 return error; 427 428 gid = kauth_cred_getegid(pc); 429 if ((error = copyout(&gid, SCARG_P32(uap, egid), sizeof(gid_t))) != 0) 430 return error; 431 432 gid = kauth_cred_getsvgid(pc); 433 return copyout(&gid, SCARG_P32(uap, sgid), sizeof(gid_t)); 434 } 435 436 int 437 linux32_sys_nice(struct lwp *l, const struct linux32_sys_nice_args *uap, register_t *retval) 438 { 439 /* { 440 syscallarg(int) incr; 441 } */ 442 struct proc *p = l->l_proc; 443 struct sys_setpriority_args bsa; 444 445 SCARG(&bsa, which) = PRIO_PROCESS; 446 SCARG(&bsa, who) = 0; 447 SCARG(&bsa, prio) = p->p_nice - NZERO + SCARG(uap, incr); 448 449 return sys_setpriority(l, &bsa, retval); 450 } 451 452 int 453 linux32_sys_alarm(struct lwp *l, const struct linux32_sys_alarm_args *uap, register_t *retval) 454 { 455 /* { 456 syscallarg(unsigned int) secs; 457 } */ 458 struct linux_sys_alarm_args ua; 459 460 NETBSD32TO64_UAP(secs); 461 462 return linux_sys_alarm(l, &ua, retval); 463 } 464 465 int 466 linux32_sys_fdatasync(struct lwp *l, const struct linux32_sys_fdatasync_args *uap, register_t *retval) 467 { 468 /* { 469 syscallarg(int) fd; 470 } */ 471 struct linux_sys_fdatasync_args ua; 472 473 NETBSD32TO64_UAP(fd); 474 475 return linux_sys_fdatasync(l, &ua, retval); 476 } 477 478 int 479 linux32_sys_setfsuid(struct lwp *l, const struct linux32_sys_setfsuid_args *uap, register_t *retval) 480 { 481 /* { 482 syscallarg(uid_t) uid; 483 } */ 484 struct linux_sys_setfsuid_args ua; 485 486 NETBSD32TO64_UAP(uid); 487 488 return linux_sys_setfsuid(l, &ua, retval); 489 } 490 491 int 492 linux32_sys_setfsgid(struct lwp *l, const struct linux32_sys_setfsgid_args *uap, register_t *retval) 493 { 494 /* { 495 syscallarg(gid_t) gid; 496 } */ 497 struct linux_sys_setfsgid_args ua; 498 499 NETBSD32TO64_UAP(gid); 500 501 return linux_sys_setfsgid(l, &ua, retval); 502 } 503 504 /* 505 * pread(2). 506 */ 507 int 508 linux32_sys_pread(struct lwp *l, 509 const struct linux32_sys_pread_args *uap, register_t *retval) 510 { 511 /* { 512 syscallarg(int) fd; 513 syscallarg(netbsd32_voidp) buf; 514 syscallarg(netbsd32_size_t) nbyte; 515 syscallarg(linux32_off_t) offset; 516 } */ 517 struct sys_pread_args pra; 518 519 SCARG(&pra, fd) = SCARG(uap, fd); 520 SCARG(&pra, buf) = SCARG_P32(uap, buf); 521 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 522 SCARG(&pra, offset) = SCARG(uap, offset); 523 524 return sys_pread(l, &pra, retval); 525 } 526 527 /* 528 * pwrite(2). 529 */ 530 int 531 linux32_sys_pwrite(struct lwp *l, 532 const struct linux32_sys_pwrite_args *uap, register_t *retval) 533 { 534 /* { 535 syscallarg(int) fd; 536 syscallarg(const netbsd32_voidp) buf; 537 syscallarg(netbsd32_size_t) nbyte; 538 syscallarg(linux32_off_t) offset; 539 } */ 540 struct sys_pwrite_args pra; 541 542 SCARG(&pra, fd) = SCARG(uap, fd); 543 SCARG(&pra, buf) = SCARG_P32(uap, buf); 544 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 545 SCARG(&pra, offset) = SCARG(uap, offset); 546 547 return sys_pwrite(l, &pra, retval); 548 } 549 550