1 /* $NetBSD: linux32_unistd.c,v 1.20 2008/02/02 22:57:05 dsl 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.20 2008/02/02 22:57:05 dsl 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 50 #include <machine/types.h> 51 52 #include <sys/syscallargs.h> 53 54 #include <compat/netbsd32/netbsd32.h> 55 #include <compat/netbsd32/netbsd32_conv.h> 56 #include <compat/netbsd32/netbsd32_syscallargs.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/linux_syscallargs.h> 64 65 #include <compat/linux32/common/linux32_types.h> 66 #include <compat/linux32/common/linux32_signal.h> 67 #include <compat/linux32/common/linux32_machdep.h> 68 #include <compat/linux32/common/linux32_sysctl.h> 69 #include <compat/linux32/common/linux32_socketcall.h> 70 #include <compat/linux32/linux32_syscallargs.h> 71 72 static int linux32_select1(struct lwp *, register_t *, 73 int, fd_set *, fd_set *, fd_set *, struct timeval *); 74 75 int 76 linux32_sys_brk(struct lwp *l, const struct linux32_sys_brk_args *uap, register_t *retval) 77 { 78 /* { 79 syscallarg(netbsd32_charp) nsize; 80 } */ 81 struct linux_sys_brk_args ua; 82 83 NETBSD32TOP_UAP(nsize, char); 84 return linux_sys_brk(l, &ua, retval); 85 } 86 87 int 88 linux32_sys_llseek(struct lwp *l, const struct linux32_sys_llseek_args *uap, register_t *retval) 89 { 90 /* { 91 syscallcarg(int) fd; 92 syscallarg(u_int32_t) ohigh; 93 syscallarg(u_int32_t) olow; 94 syscallarg(netbsd32_caddr_t) res; 95 syscallcarg(int) whence; 96 } */ 97 struct linux_sys_llseek_args ua; 98 99 NETBSD32TO64_UAP(fd); 100 NETBSD32TO64_UAP(ohigh); 101 NETBSD32TO64_UAP(olow); 102 NETBSD32TOP_UAP(res, char); 103 NETBSD32TO64_UAP(whence); 104 105 return linux_sys_llseek(l, &ua, retval); 106 } 107 108 int 109 linux32_sys_select(struct lwp *l, const struct linux32_sys_select_args *uap, register_t *retval) 110 { 111 /* { 112 syscallarg(int) nfds; 113 syscallarg(netbsd32_fd_setp_t) readfds; 114 syscallarg(netbsd32_fd_setp_t) writefds; 115 syscallarg(netbsd32_fd_setp_t) exceptfds; 116 syscallarg(netbsd32_timevalp_t) timeout; 117 } */ 118 119 return linux32_select1(l, retval, SCARG(uap, nfds), 120 SCARG_P32(uap, readfds), 121 SCARG_P32(uap, writefds), 122 SCARG_P32(uap, exceptfds), 123 SCARG_P32(uap, timeout)); 124 } 125 126 int 127 linux32_sys_oldselect(struct lwp *l, const struct linux32_sys_oldselect_args *uap, register_t *retval) 128 { 129 /* { 130 syscallarg(linux32_oldselectp_t) lsp; 131 } */ 132 struct linux32_oldselect lsp32; 133 int error; 134 135 if ((error = copyin(SCARG_P32(uap, lsp), &lsp32, sizeof(lsp32))) != 0) 136 return error; 137 138 return linux32_select1(l, retval, lsp32.nfds, 139 NETBSD32PTR64(lsp32.readfds), NETBSD32PTR64(lsp32.writefds), 140 NETBSD32PTR64(lsp32.exceptfds), NETBSD32PTR64(lsp32.timeout)); 141 } 142 143 static int 144 linux32_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout) 145 struct lwp *l; 146 register_t *retval; 147 int nfds; 148 fd_set *readfds, *writefds, *exceptfds; 149 struct timeval *timeout; 150 { 151 struct timeval tv0, tv1, utv, *tv = NULL; 152 struct netbsd32_timeval utv32; 153 int error; 154 155 timerclear(&utv); /* XXX GCC4 */ 156 157 /* 158 * Store current time for computation of the amount of 159 * time left. 160 */ 161 if (timeout) { 162 if ((error = copyin(timeout, &utv32, sizeof(utv32)))) 163 return error; 164 165 netbsd32_to_timeval(&utv32, &utv); 166 167 if (itimerfix(&utv)) { 168 /* 169 * The timeval was invalid. Convert it to something 170 * valid that will act as it does under Linux. 171 */ 172 utv.tv_sec += utv.tv_usec / 1000000; 173 utv.tv_usec %= 1000000; 174 if (utv.tv_usec < 0) { 175 utv.tv_sec -= 1; 176 utv.tv_usec += 1000000; 177 } 178 if (utv.tv_sec < 0) 179 timerclear(&utv); 180 } 181 microtime(&tv0); 182 tv = &utv; 183 } 184 185 error = selcommon(l, retval, nfds, 186 readfds, writefds, exceptfds, tv, NULL); 187 188 if (error) { 189 /* 190 * See fs/select.c in the Linux kernel. Without this, 191 * Maelstrom doesn't work. 192 */ 193 if (error == ERESTART) 194 error = EINTR; 195 return error; 196 } 197 198 if (timeout) { 199 if (*retval) { 200 /* 201 * Compute how much time was left of the timeout, 202 * by subtracting the current time and the time 203 * before we started the call, and subtracting 204 * that result from the user-supplied value. 205 */ 206 microtime(&tv1); 207 timersub(&tv1, &tv0, &tv1); 208 timersub(&utv, &tv1, &utv); 209 if (utv.tv_sec < 0) 210 timerclear(&utv); 211 } else { 212 timerclear(&utv); 213 } 214 215 netbsd32_from_timeval(&utv, &utv32); 216 217 if ((error = copyout(&utv32, timeout, sizeof(utv32)))) 218 return error; 219 } 220 221 return 0; 222 } 223 224 int 225 linux32_sys_pipe(struct lwp *l, const struct linux32_sys_pipe_args *uap, register_t *retval) 226 { 227 /* { 228 syscallarg(netbsd32_intp) fd; 229 } */ 230 int error; 231 int pfds[2]; 232 233 if ((error = sys_pipe(l, 0, retval))) 234 return error; 235 236 pfds[0] = (int)retval[0]; 237 pfds[1] = (int)retval[1]; 238 239 if ((error = copyout(pfds, SCARG_P32(uap, fd), 2 * sizeof (int))) != 0) 240 return error; 241 242 retval[0] = 0; 243 retval[1] = 0; 244 245 return 0; 246 } 247 248 249 int 250 linux32_sys_unlink(struct lwp *l, const struct linux32_sys_unlink_args *uap, register_t *retval) 251 { 252 /* { 253 syscallarg(const netbsd32_charp) path; 254 } */ 255 struct linux_sys_unlink_args ua; 256 257 NETBSD32TOP_UAP(path, const char); 258 259 return linux_sys_unlink(l, &ua, retval); 260 } 261 262 int 263 linux32_sys_creat(struct lwp *l, const struct linux32_sys_creat_args *uap, register_t *retval) 264 { 265 /* { 266 syscallarg(const netbsd32_charp) path; 267 syscallarg(int) mode; 268 } */ 269 struct sys_open_args ua; 270 271 NETBSD32TOP_UAP(path, const char); 272 SCARG(&ua, flags) = O_CREAT | O_TRUNC | O_WRONLY; 273 NETBSD32TO64_UAP(mode); 274 275 return sys_open(l, &ua, retval); 276 } 277 278 int 279 linux32_sys_mknod(struct lwp *l, const struct linux32_sys_mknod_args *uap, register_t *retval) 280 { 281 /* { 282 syscallarg(const netbsd32_charp) path; 283 syscallarg(int) mode; 284 syscallarg(int) dev; 285 } */ 286 struct linux_sys_mknod_args ua; 287 288 NETBSD32TOP_UAP(path, const char); 289 NETBSD32TO64_UAP(mode); 290 NETBSD32TO64_UAP(dev); 291 292 return linux_sys_mknod(l, &ua, retval); 293 } 294 295 int 296 linux32_sys_break(struct lwp *l, const struct linux32_sys_break_args *uap, register_t *retval) 297 { 298 #if 0 299 /* { 300 syscallarg(const netbsd32_charp) nsize; 301 } */ 302 #endif 303 304 return ENOSYS; 305 } 306 307 int 308 linux32_sys_rename(struct lwp *l, const struct linux32_sys_rename_args *uap, register_t *retval) 309 { 310 /* { 311 syscallarg(const netbsd32_charp) from; 312 syscallarg(const netbsd32_charp) to; 313 } */ 314 struct sys___posix_rename_args ua; 315 316 NETBSD32TOP_UAP(from, const char); 317 NETBSD32TOP_UAP(to, const char); 318 319 return sys___posix_rename(l, &ua, retval); 320 } 321 322 int 323 linux32_sys_swapon(struct lwp *l, const struct linux32_sys_swapon_args *uap, register_t *retval) 324 { 325 /* { 326 syscallarg(const netbsd32_charp) name; 327 } */ 328 struct sys_swapctl_args ua; 329 330 SCARG(&ua, cmd) = SWAP_ON; 331 SCARG(&ua, arg) = SCARG_P32(uap, name); 332 SCARG(&ua, misc) = 0; /* priority */ 333 return (sys_swapctl(l, &ua, retval)); 334 } 335 336 int 337 linux32_sys_swapoff(struct lwp *l, const struct linux32_sys_swapoff_args *uap, register_t *retval) 338 { 339 /* { 340 syscallarg(const netbsd32_charp) path; 341 } */ 342 struct sys_swapctl_args ua; 343 344 SCARG(&ua, cmd) = SWAP_OFF; 345 SCARG(&ua, arg) = SCARG_P32(uap, path); 346 SCARG(&ua, misc) = 0; /* priority */ 347 return (sys_swapctl(l, &ua, retval)); 348 } 349 350 351 int 352 linux32_sys_reboot(struct lwp *l, const struct linux32_sys_reboot_args *uap, register_t *retval) 353 { 354 /* { 355 syscallarg(int) magic1; 356 syscallarg(int) magic2; 357 syscallarg(int) cmd; 358 syscallarg(netbsd32_voidp) arg; 359 } */ 360 struct linux_sys_reboot_args ua; 361 362 NETBSD32TO64_UAP(magic1); 363 NETBSD32TO64_UAP(magic2); 364 NETBSD32TO64_UAP(cmd); 365 NETBSD32TOP_UAP(arg, void); 366 367 return linux_sys_reboot(l, &ua, retval); 368 } 369 370 int 371 linux32_sys_truncate(struct lwp *l, const struct linux32_sys_truncate_args *uap, register_t *retval) 372 { 373 /* { 374 syscallarg(const netbsd32_charp) path; 375 syscallarg(netbsd32_charp) buf; 376 syscallarg(int) count; 377 } */ 378 struct compat_43_sys_truncate_args ua; 379 380 NETBSD32TOP_UAP(path, const char); 381 NETBSD32TO64_UAP(length); 382 383 return compat_43_sys_truncate(l, &ua, retval); 384 } 385 386 int 387 linux32_sys_setresuid(struct lwp *l, const struct linux32_sys_setresuid_args *uap, register_t *retval) 388 { 389 /* { 390 syscallarg(uid_t) ruid; 391 syscallarg(uid_t) euid; 392 syscallarg(uid_t) suid; 393 } */ 394 struct linux_sys_setresuid_args ua; 395 396 SCARG(&ua, ruid) = (SCARG(uap, ruid) == -1) ? -1 : SCARG(uap, ruid); 397 SCARG(&ua, euid) = (SCARG(uap, euid) == -1) ? -1 : SCARG(uap, euid); 398 SCARG(&ua, suid) = (SCARG(uap, suid) == -1) ? -1 : SCARG(uap, suid); 399 400 return linux_sys_setresuid(l, &ua, retval); 401 } 402 403 int 404 linux32_sys_setresgid(struct lwp *l, const struct linux32_sys_setresgid_args *uap, register_t *retval) 405 { 406 /* { 407 syscallarg(gid_t) rgid; 408 syscallarg(gid_t) egid; 409 syscallarg(gid_t) sgid; 410 } */ 411 struct linux_sys_setresgid_args ua; 412 413 SCARG(&ua, rgid) = (SCARG(uap, rgid) == -1) ? -1 : SCARG(uap, rgid); 414 SCARG(&ua, egid) = (SCARG(uap, egid) == -1) ? -1 : SCARG(uap, egid); 415 SCARG(&ua, sgid) = (SCARG(uap, sgid) == -1) ? -1 : SCARG(uap, sgid); 416 417 return linux_sys_setresgid(l, &ua, retval); 418 } 419 420 int 421 linux32_sys_nice(struct lwp *l, const struct linux32_sys_nice_args *uap, register_t *retval) 422 { 423 /* { 424 syscallarg(int) incr; 425 } */ 426 struct netbsd32_setpriority_args bsa; 427 428 SCARG(&bsa, which) = PRIO_PROCESS; 429 SCARG(&bsa, who) = 0; 430 SCARG(&bsa, prio) = SCARG(uap, incr); 431 432 return netbsd32_setpriority(l, &bsa, retval); 433 } 434 435 int 436 linux32_sys_alarm(struct lwp *l, const struct linux32_sys_alarm_args *uap, register_t *retval) 437 { 438 /* { 439 syscallarg(unsigned int) secs; 440 } */ 441 struct linux_sys_alarm_args ua; 442 443 NETBSD32TO64_UAP(secs); 444 445 return linux_sys_alarm(l, &ua, retval); 446 } 447 448 int 449 linux32_sys_fdatasync(struct lwp *l, const struct linux32_sys_fdatasync_args *uap, register_t *retval) 450 { 451 /* { 452 syscallarg(int) fd; 453 } */ 454 struct linux_sys_fdatasync_args ua; 455 456 NETBSD32TO64_UAP(fd); 457 458 return linux_sys_fdatasync(l, &ua, retval); 459 } 460 461 int 462 linux32_sys_setfsuid(struct lwp *l, const struct linux32_sys_setfsuid_args *uap, register_t *retval) 463 { 464 /* { 465 syscallarg(uid_t) uid; 466 } */ 467 struct linux_sys_setfsuid_args ua; 468 469 NETBSD32TO64_UAP(uid); 470 471 return linux_sys_setfsuid(l, &ua, retval); 472 } 473 474 int 475 linux32_sys_setfsgid(struct lwp *l, const struct linux32_sys_setfsgid_args *uap, register_t *retval) 476 { 477 /* { 478 syscallarg(gid_t) gid; 479 } */ 480 struct linux_sys_setfsgid_args ua; 481 482 NETBSD32TO64_UAP(gid); 483 484 return linux_sys_setfsgid(l, &ua, retval); 485 } 486 487 /* 488 * pread(2). 489 */ 490 int 491 linux32_sys_pread(struct lwp *l, 492 const struct linux32_sys_pread_args *uap, register_t *retval) 493 { 494 /* { 495 syscallarg(int) fd; 496 syscallarg(void *) buf; 497 syscallarg(netbsd32_size_t) nbyte; 498 syscallarg(int32_t) offset; 499 } */ 500 struct sys_pread_args pra; 501 502 SCARG(&pra, fd) = SCARG(uap, fd); 503 SCARG(&pra, buf) = SCARG(uap, buf); 504 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 505 SCARG(&pra, offset) = SCARG(uap, offset); 506 507 return sys_pread(l, &pra, retval); 508 } 509 510 /* 511 * pwrite(2). 512 */ 513 int 514 linux32_sys_pwrite(struct lwp *l, 515 const struct linux32_sys_pwrite_args *uap, register_t *retval) 516 { 517 /* { 518 syscallarg(int) fd; 519 syscallarg(void *) buf; 520 syscallarg(netbsd32_size_t) nbyte; 521 syscallarg(int32_t) offset; 522 } */ 523 struct sys_pwrite_args pra; 524 525 SCARG(&pra, fd) = SCARG(uap, fd); 526 SCARG(&pra, buf) = SCARG(uap, buf); 527 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 528 SCARG(&pra, offset) = SCARG(uap, offset); 529 530 return sys_pwrite(l, &pra, retval); 531 } 532 533