1 /* $NetBSD: linux32_unistd.c,v 1.24 2008/10/03 22:39:36 njoly 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.24 2008/10/03 22:39:36 njoly 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 57 #include <compat/linux/common/linux_types.h> 58 #include <compat/linux/common/linux_signal.h> 59 #include <compat/linux/common/linux_machdep.h> 60 #include <compat/linux/common/linux_misc.h> 61 #include <compat/linux/common/linux_oldolduname.h> 62 #include <compat/linux/linux_syscallargs.h> 63 64 #include <compat/linux32/common/linux32_types.h> 65 #include <compat/linux32/common/linux32_signal.h> 66 #include <compat/linux32/common/linux32_machdep.h> 67 #include <compat/linux32/common/linux32_sysctl.h> 68 #include <compat/linux32/common/linux32_socketcall.h> 69 #include <compat/linux32/linux32_syscallargs.h> 70 71 static int linux32_select1(struct lwp *, register_t *, 72 int, fd_set *, fd_set *, fd_set *, struct timeval *); 73 74 int 75 linux32_sys_brk(struct lwp *l, const struct linux32_sys_brk_args *uap, register_t *retval) 76 { 77 /* { 78 syscallarg(netbsd32_charp) nsize; 79 } */ 80 struct linux_sys_brk_args ua; 81 82 NETBSD32TOP_UAP(nsize, char); 83 return linux_sys_brk(l, &ua, retval); 84 } 85 86 int 87 linux32_sys_llseek(struct lwp *l, const struct linux32_sys_llseek_args *uap, register_t *retval) 88 { 89 /* { 90 syscallcarg(int) fd; 91 syscallarg(u_int32_t) ohigh; 92 syscallarg(u_int32_t) olow; 93 syscallarg(netbsd32_caddr_t) res; 94 syscallcarg(int) whence; 95 } */ 96 struct linux_sys_llseek_args ua; 97 98 NETBSD32TO64_UAP(fd); 99 NETBSD32TO64_UAP(ohigh); 100 NETBSD32TO64_UAP(olow); 101 NETBSD32TOP_UAP(res, char); 102 NETBSD32TO64_UAP(whence); 103 104 return linux_sys_llseek(l, &ua, retval); 105 } 106 107 int 108 linux32_sys_select(struct lwp *l, const struct linux32_sys_select_args *uap, register_t *retval) 109 { 110 /* { 111 syscallarg(int) nfds; 112 syscallarg(netbsd32_fd_setp_t) readfds; 113 syscallarg(netbsd32_fd_setp_t) writefds; 114 syscallarg(netbsd32_fd_setp_t) exceptfds; 115 syscallarg(netbsd32_timevalp_t) timeout; 116 } */ 117 118 return linux32_select1(l, retval, SCARG(uap, nfds), 119 SCARG_P32(uap, readfds), 120 SCARG_P32(uap, writefds), 121 SCARG_P32(uap, exceptfds), 122 SCARG_P32(uap, timeout)); 123 } 124 125 int 126 linux32_sys_oldselect(struct lwp *l, const struct linux32_sys_oldselect_args *uap, register_t *retval) 127 { 128 /* { 129 syscallarg(linux32_oldselectp_t) lsp; 130 } */ 131 struct linux32_oldselect lsp32; 132 int error; 133 134 if ((error = copyin(SCARG_P32(uap, lsp), &lsp32, sizeof(lsp32))) != 0) 135 return error; 136 137 return linux32_select1(l, retval, lsp32.nfds, 138 NETBSD32PTR64(lsp32.readfds), NETBSD32PTR64(lsp32.writefds), 139 NETBSD32PTR64(lsp32.exceptfds), NETBSD32PTR64(lsp32.timeout)); 140 } 141 142 static int 143 linux32_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout) 144 struct lwp *l; 145 register_t *retval; 146 int nfds; 147 fd_set *readfds, *writefds, *exceptfds; 148 struct timeval *timeout; 149 { 150 struct timeval tv0, tv1, utv, *tv = NULL; 151 struct netbsd32_timeval 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_timeval(&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_timeval(&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 SCARG(&ua, ruid) = (SCARG(uap, ruid) == -1) ? -1 : SCARG(uap, ruid); 365 SCARG(&ua, euid) = (SCARG(uap, euid) == -1) ? -1 : SCARG(uap, euid); 366 SCARG(&ua, suid) = (SCARG(uap, suid) == -1) ? -1 : SCARG(uap, suid); 367 368 return linux_sys_setresuid(l, &ua, retval); 369 } 370 371 int 372 linux32_sys_setresgid(struct lwp *l, const struct linux32_sys_setresgid_args *uap, register_t *retval) 373 { 374 /* { 375 syscallarg(gid_t) rgid; 376 syscallarg(gid_t) egid; 377 syscallarg(gid_t) sgid; 378 } */ 379 struct linux_sys_setresgid_args ua; 380 381 SCARG(&ua, rgid) = (SCARG(uap, rgid) == -1) ? -1 : SCARG(uap, rgid); 382 SCARG(&ua, egid) = (SCARG(uap, egid) == -1) ? -1 : SCARG(uap, egid); 383 SCARG(&ua, sgid) = (SCARG(uap, sgid) == -1) ? -1 : SCARG(uap, sgid); 384 385 return linux_sys_setresgid(l, &ua, retval); 386 } 387 388 int 389 linux32_sys_nice(struct lwp *l, const struct linux32_sys_nice_args *uap, register_t *retval) 390 { 391 /* { 392 syscallarg(int) incr; 393 } */ 394 struct proc *p = l->l_proc; 395 struct sys_setpriority_args bsa; 396 397 SCARG(&bsa, which) = PRIO_PROCESS; 398 SCARG(&bsa, who) = 0; 399 SCARG(&bsa, prio) = p->p_nice - NZERO + SCARG(uap, incr); 400 401 return sys_setpriority(l, &bsa, retval); 402 } 403 404 int 405 linux32_sys_alarm(struct lwp *l, const struct linux32_sys_alarm_args *uap, register_t *retval) 406 { 407 /* { 408 syscallarg(unsigned int) secs; 409 } */ 410 struct linux_sys_alarm_args ua; 411 412 NETBSD32TO64_UAP(secs); 413 414 return linux_sys_alarm(l, &ua, retval); 415 } 416 417 int 418 linux32_sys_fdatasync(struct lwp *l, const struct linux32_sys_fdatasync_args *uap, register_t *retval) 419 { 420 /* { 421 syscallarg(int) fd; 422 } */ 423 struct linux_sys_fdatasync_args ua; 424 425 NETBSD32TO64_UAP(fd); 426 427 return linux_sys_fdatasync(l, &ua, retval); 428 } 429 430 int 431 linux32_sys_setfsuid(struct lwp *l, const struct linux32_sys_setfsuid_args *uap, register_t *retval) 432 { 433 /* { 434 syscallarg(uid_t) uid; 435 } */ 436 struct linux_sys_setfsuid_args ua; 437 438 NETBSD32TO64_UAP(uid); 439 440 return linux_sys_setfsuid(l, &ua, retval); 441 } 442 443 int 444 linux32_sys_setfsgid(struct lwp *l, const struct linux32_sys_setfsgid_args *uap, register_t *retval) 445 { 446 /* { 447 syscallarg(gid_t) gid; 448 } */ 449 struct linux_sys_setfsgid_args ua; 450 451 NETBSD32TO64_UAP(gid); 452 453 return linux_sys_setfsgid(l, &ua, retval); 454 } 455 456 /* 457 * pread(2). 458 */ 459 int 460 linux32_sys_pread(struct lwp *l, 461 const struct linux32_sys_pread_args *uap, register_t *retval) 462 { 463 /* { 464 syscallarg(int) fd; 465 syscallarg(netbsd32_voidp) buf; 466 syscallarg(netbsd32_size_t) nbyte; 467 syscallarg(linux32_off_t) offset; 468 } */ 469 struct sys_pread_args pra; 470 471 SCARG(&pra, fd) = SCARG(uap, fd); 472 SCARG(&pra, buf) = SCARG_P32(uap, buf); 473 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 474 SCARG(&pra, offset) = SCARG(uap, offset); 475 476 return sys_pread(l, &pra, retval); 477 } 478 479 /* 480 * pwrite(2). 481 */ 482 int 483 linux32_sys_pwrite(struct lwp *l, 484 const struct linux32_sys_pwrite_args *uap, register_t *retval) 485 { 486 /* { 487 syscallarg(int) fd; 488 syscallarg(const netbsd32_voidp) buf; 489 syscallarg(netbsd32_size_t) nbyte; 490 syscallarg(linux32_off_t) offset; 491 } */ 492 struct sys_pwrite_args pra; 493 494 SCARG(&pra, fd) = SCARG(uap, fd); 495 SCARG(&pra, buf) = SCARG_P32(uap, buf); 496 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 497 SCARG(&pra, offset) = SCARG(uap, offset); 498 499 return sys_pwrite(l, &pra, retval); 500 } 501 502