35#include "opt_mac.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/file.h> 40#include <sys/filedesc.h> 41/*#include <sys/ioctl.h>*/ 42#include <sys/lock.h> 43#include <sys/mac.h> 44#include <sys/mount.h> 45#include <sys/mutex.h> 46#include <sys/namei.h> 47#include <sys/proc.h> 48#include <sys/stat.h> 49#include <sys/unistd.h> 50#include <sys/vnode.h> 51 52#include <sys/sysproto.h> 53 54#include <compat/svr4/svr4.h> 55#include <compat/svr4/svr4_types.h> 56#include <compat/svr4/svr4_signal.h> 57#include <compat/svr4/svr4_proto.h> 58#include <compat/svr4/svr4_util.h> 59#include <compat/svr4/svr4_fcntl.h> 60 61static int svr4_to_bsd_flags(int); 62static u_long svr4_to_bsd_cmd(u_long); 63static int fd_revoke(struct thread *, int); 64static int fd_truncate(struct thread *, int, struct flock *); 65static int bsd_to_svr4_flags(int); 66static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *); 67static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *); 68static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *); 69static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *); 70 71static u_long 72svr4_to_bsd_cmd(cmd) 73 u_long cmd; 74{ 75 switch (cmd) { 76 case SVR4_F_DUPFD: 77 return F_DUPFD; 78 case SVR4_F_GETFD: 79 return F_GETFD; 80 case SVR4_F_SETFD: 81 return F_SETFD; 82 case SVR4_F_GETFL: 83 return F_GETFL; 84 case SVR4_F_SETFL: 85 return F_SETFL; 86 case SVR4_F_GETLK: 87 return F_GETLK; 88 case SVR4_F_SETLK: 89 return F_SETLK; 90 case SVR4_F_SETLKW: 91 return F_SETLKW; 92 default: 93 return -1; 94 } 95} 96 97static int 98svr4_to_bsd_flags(l) 99 int l; 100{ 101 int r = 0; 102 r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0; 103 r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0; 104 r |= (l & SVR4_O_RDWR) ? O_RDWR : 0; 105 r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0; 106 r |= (l & SVR4_O_APPEND) ? O_APPEND : 0; 107 r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0; 108 r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0; 109 r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0; 110 r |= (l & SVR4_O_CREAT) ? O_CREAT : 0; 111 r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0; 112 r |= (l & SVR4_O_EXCL) ? O_EXCL : 0; 113 r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0; 114 return r; 115} 116 117static int 118bsd_to_svr4_flags(l) 119 int l; 120{ 121 int r = 0; 122 r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0; 123 r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0; 124 r |= (l & O_RDWR) ? SVR4_O_RDWR : 0; 125 r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0; 126 r |= (l & O_APPEND) ? SVR4_O_APPEND : 0; 127 r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0; 128 r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0; 129 r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0; 130 r |= (l & O_CREAT) ? SVR4_O_CREAT : 0; 131 r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0; 132 r |= (l & O_EXCL) ? SVR4_O_EXCL : 0; 133 r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0; 134 return r; 135} 136 137 138static void 139bsd_to_svr4_flock(iflp, oflp) 140 struct flock *iflp; 141 struct svr4_flock *oflp; 142{ 143 switch (iflp->l_type) { 144 case F_RDLCK: 145 oflp->l_type = SVR4_F_RDLCK; 146 break; 147 case F_WRLCK: 148 oflp->l_type = SVR4_F_WRLCK; 149 break; 150 case F_UNLCK: 151 oflp->l_type = SVR4_F_UNLCK; 152 break; 153 default: 154 oflp->l_type = -1; 155 break; 156 } 157 158 oflp->l_whence = (short) iflp->l_whence; 159 oflp->l_start = (svr4_off_t) iflp->l_start; 160 oflp->l_len = (svr4_off_t) iflp->l_len; 161 oflp->l_sysid = 0; 162 oflp->l_pid = (svr4_pid_t) iflp->l_pid; 163} 164 165 166static void 167svr4_to_bsd_flock(iflp, oflp) 168 struct svr4_flock *iflp; 169 struct flock *oflp; 170{ 171 switch (iflp->l_type) { 172 case SVR4_F_RDLCK: 173 oflp->l_type = F_RDLCK; 174 break; 175 case SVR4_F_WRLCK: 176 oflp->l_type = F_WRLCK; 177 break; 178 case SVR4_F_UNLCK: 179 oflp->l_type = F_UNLCK; 180 break; 181 default: 182 oflp->l_type = -1; 183 break; 184 } 185 186 oflp->l_whence = iflp->l_whence; 187 oflp->l_start = (off_t) iflp->l_start; 188 oflp->l_len = (off_t) iflp->l_len; 189 oflp->l_pid = (pid_t) iflp->l_pid; 190 191} 192 193static void 194bsd_to_svr4_flock64(iflp, oflp) 195 struct flock *iflp; 196 struct svr4_flock64 *oflp; 197{ 198 switch (iflp->l_type) { 199 case F_RDLCK: 200 oflp->l_type = SVR4_F_RDLCK; 201 break; 202 case F_WRLCK: 203 oflp->l_type = SVR4_F_WRLCK; 204 break; 205 case F_UNLCK: 206 oflp->l_type = SVR4_F_UNLCK; 207 break; 208 default: 209 oflp->l_type = -1; 210 break; 211 } 212 213 oflp->l_whence = (short) iflp->l_whence; 214 oflp->l_start = (svr4_off64_t) iflp->l_start; 215 oflp->l_len = (svr4_off64_t) iflp->l_len; 216 oflp->l_sysid = 0; 217 oflp->l_pid = (svr4_pid_t) iflp->l_pid; 218} 219 220 221static void 222svr4_to_bsd_flock64(iflp, oflp) 223 struct svr4_flock64 *iflp; 224 struct flock *oflp; 225{ 226 switch (iflp->l_type) { 227 case SVR4_F_RDLCK: 228 oflp->l_type = F_RDLCK; 229 break; 230 case SVR4_F_WRLCK: 231 oflp->l_type = F_WRLCK; 232 break; 233 case SVR4_F_UNLCK: 234 oflp->l_type = F_UNLCK; 235 break; 236 default: 237 oflp->l_type = -1; 238 break; 239 } 240 241 oflp->l_whence = iflp->l_whence; 242 oflp->l_start = (off_t) iflp->l_start; 243 oflp->l_len = (off_t) iflp->l_len; 244 oflp->l_pid = (pid_t) iflp->l_pid; 245 246} 247 248 249static int 250fd_revoke(td, fd) 251 struct thread *td; 252 int fd; 253{ 254 struct vnode *vp; 255 struct mount *mp; 256 struct vattr vattr; 257 int error, *retval; 258 259 retval = td->td_retval; 260 if ((error = fgetvp(td, fd, &vp)) != 0) 261 return (error); 262 263 if (vp->v_type != VCHR && vp->v_type != VBLK) { 264 error = EINVAL; 265 goto out; 266 } 267 268#ifdef MAC 269 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 270 error = mac_check_vnode_revoke(td->td_ucred, vp); 271 VOP_UNLOCK(vp, 0, td); 272 if (error) 273 goto out; 274#endif 275 276 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) 277 goto out; 278 279 if (td->td_ucred->cr_uid != vattr.va_uid && 280 (error = suser(td)) != 0) 281 goto out; 282 283 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 284 goto out; 285 if (vcount(vp) > 1) 286 VOP_REVOKE(vp, REVOKEALL); 287 vn_finished_write(mp); 288out: 289 vrele(vp); 290 return error; 291} 292 293 294static int 295fd_truncate(td, fd, flp) 296 struct thread *td; 297 int fd; 298 struct flock *flp; 299{ 300 off_t start, length; 301 struct file *fp; 302 struct vnode *vp; 303 struct vattr vattr; 304 int error, *retval; 305 struct ftruncate_args ft; 306 307 retval = td->td_retval; 308 309 /* 310 * We only support truncating the file. 311 */ 312 if ((error = fget(td, fd, &fp)) != 0) 313 return (error); 314 315 vp = fp->f_data; 316 317 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 318 fdrop(fp, td); 319 return ESPIPE; 320 } 321 322 if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) { 323 fdrop(fp, td); 324 return error; 325 } 326 327 length = vattr.va_size; 328 329 switch (flp->l_whence) { 330 case SEEK_CUR: 331 start = fp->f_offset + flp->l_start; 332 break; 333 334 case SEEK_END: 335 start = flp->l_start + length; 336 break; 337 338 case SEEK_SET: 339 start = flp->l_start; 340 break; 341 342 default: 343 fdrop(fp, td); 344 return EINVAL; 345 } 346 347 if (start + flp->l_len < length) { 348 /* We don't support free'ing in the middle of the file */ 349 fdrop(fp, td); 350 return EINVAL; 351 } 352 353 ft.fd = fd; 354 ft.length = start; 355 356 error = ftruncate(td, &ft); 357 358 fdrop(fp, td); 359 return (error); 360} 361 362int 363svr4_sys_open(td, uap) 364 register struct thread *td; 365 struct svr4_sys_open_args *uap; 366{ 367 struct proc *p = td->td_proc; 368 int error, retval; 369 struct open_args cup; 370 371 caddr_t sg = stackgap_init(); 372 CHECKALTEXIST(td, &sg, uap->path); 373 374 (&cup)->path = uap->path; 375 (&cup)->flags = svr4_to_bsd_flags(uap->flags); 376 (&cup)->mode = uap->mode; 377 error = open(td, &cup); 378 379 if (error) { 380 /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path, 381 uap->flags, uap->mode, error);*/ 382 return error; 383 } 384 385 retval = td->td_retval[0]; 386 387 PROC_LOCK(p); 388 if (!(cup.flags & O_NOCTTY) && SESS_LEADER(p) && 389 !(td->td_proc->p_flag & P_CONTROLT)) { 390#if defined(NOTYET) 391 struct file *fp; 392 393 error = fget(td, retval, &fp); 394 PROC_UNLOCK(p); 395 /* 396 * we may have lost a race the above open() and 397 * another thread issuing a close() 398 */ 399 if (error) 400 return (EBADF); /* XXX: correct errno? */ 401 /* ignore any error, just give it a try */ 402 if (fp->f_type == DTYPE_VNODE) 403 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred, 404 td); 405 fdrop(fp, td); 406 } else { 407 PROC_UNLOCK(p); 408 } 409#else 410 } 411 PROC_UNLOCK(p); 412#endif 413 return error; 414} 415 416int 417svr4_sys_open64(td, uap) 418 register struct thread *td; 419 struct svr4_sys_open64_args *uap; 420{ 421 return svr4_sys_open(td, (struct svr4_sys_open_args *)uap); 422} 423 424int 425svr4_sys_creat(td, uap) 426 register struct thread *td; 427 struct svr4_sys_creat_args *uap; 428{ 429 struct open_args cup; 430 431 caddr_t sg = stackgap_init(); 432 CHECKALTEXIST(td, &sg, uap->path); 433 434 cup.path = uap->path; 435 cup.mode = uap->mode; 436 cup.flags = O_WRONLY | O_CREAT | O_TRUNC; 437 438 return open(td, &cup); 439} 440 441int 442svr4_sys_creat64(td, uap) 443 register struct thread *td; 444 struct svr4_sys_creat64_args *uap; 445{ 446 return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap); 447} 448 449int 450svr4_sys_llseek(td, uap) 451 register struct thread *td; 452 struct svr4_sys_llseek_args *uap; 453{ 454 struct lseek_args ap; 455 456 ap.fd = uap->fd; 457 458#if BYTE_ORDER == BIG_ENDIAN 459 ap.offset = (((u_int64_t) uap->offset1) << 32) | 460 uap->offset2; 461#else 462 ap.offset = (((u_int64_t) uap->offset2) << 32) | 463 uap->offset1; 464#endif 465 ap.whence = uap->whence; 466 467 return lseek(td, &ap); 468} 469 470int 471svr4_sys_access(td, uap) 472 register struct thread *td; 473 struct svr4_sys_access_args *uap; 474{ 475 struct access_args cup; 476 int *retval; 477 478 caddr_t sg = stackgap_init(); 479 CHECKALTEXIST(td, &sg, uap->path); 480 481 retval = td->td_retval; 482 483 cup.path = uap->path; 484 cup.flags = uap->flags; 485 486 return access(td, &cup); 487} 488 489#if defined(NOTYET) 490int 491svr4_sys_pread(td, uap) 492 register struct thread *td; 493 struct svr4_sys_pread_args *uap; 494{ 495 struct pread_args pra; 496 497 /* 498 * Just translate the args structure and call the NetBSD 499 * pread(2) system call (offset type is 64-bit in NetBSD). 500 */ 501 pra.fd = uap->fd; 502 pra.buf = uap->buf; 503 pra.nbyte = uap->nbyte; 504 pra.offset = uap->off; 505 506 return pread(td, &pra); 507} 508#endif 509 510#if defined(NOTYET) 511int 512svr4_sys_pread64(td, v, retval) 513 register struct thread *td; 514 void *v; 515 register_t *retval; 516{ 517 518 struct svr4_sys_pread64_args *uap = v; 519 struct sys_pread_args pra; 520 521 /* 522 * Just translate the args structure and call the NetBSD 523 * pread(2) system call (offset type is 64-bit in NetBSD). 524 */ 525 pra.fd = uap->fd; 526 pra.buf = uap->buf; 527 pra.nbyte = uap->nbyte; 528 pra.offset = uap->off; 529 530 return (sys_pread(td, &pra, retval)); 531} 532#endif /* NOTYET */ 533 534#if defined(NOTYET) 535int 536svr4_sys_pwrite(td, uap) 537 register struct thread *td; 538 struct svr4_sys_pwrite_args *uap; 539{ 540 struct pwrite_args pwa; 541 542 /* 543 * Just translate the args structure and call the NetBSD 544 * pwrite(2) system call (offset type is 64-bit in NetBSD). 545 */ 546 pwa.fd = uap->fd; 547 pwa.buf = uap->buf; 548 pwa.nbyte = uap->nbyte; 549 pwa.offset = uap->off; 550 551 return pwrite(td, &pwa); 552} 553#endif 554 555#if defined(NOTYET) 556int 557svr4_sys_pwrite64(td, v, retval) 558 register struct thread *td; 559 void *v; 560 register_t *retval; 561{ 562 struct svr4_sys_pwrite64_args *uap = v; 563 struct sys_pwrite_args pwa; 564 565 /* 566 * Just translate the args structure and call the NetBSD 567 * pwrite(2) system call (offset type is 64-bit in NetBSD). 568 */ 569 pwa.fd = uap->fd; 570 pwa.buf = uap->buf; 571 pwa.nbyte = uap->nbyte; 572 pwa.offset = uap->off; 573 574 return (sys_pwrite(td, &pwa, retval)); 575} 576#endif /* NOTYET */ 577 578int 579svr4_sys_fcntl(td, uap) 580 register struct thread *td; 581 struct svr4_sys_fcntl_args *uap; 582{ 583 int error; 584 struct fcntl_args fa; 585 int *retval; 586 587 retval = td->td_retval; 588 589 fa.fd = uap->fd; 590 fa.cmd = svr4_to_bsd_cmd(uap->cmd); 591 592 switch (fa.cmd) { 593 case F_DUPFD: 594 case F_GETFD: 595 case F_SETFD: 596 fa.arg = (long) uap->arg; 597 return fcntl(td, &fa); 598 599 case F_GETFL: 600 fa.arg = (long) uap->arg; 601 error = fcntl(td, &fa); 602 if (error) 603 return error; 604 *retval = bsd_to_svr4_flags(*retval); 605 return error; 606 607 case F_SETFL: 608 { 609 /* 610 * we must save the O_ASYNC flag, as that is 611 * handled by ioctl(_, I_SETSIG, _) emulation. 612 */ 613 long cmd; 614 int flags; 615 616 DPRINTF(("Setting flags %p\n", uap->arg)); 617 cmd = fa.cmd; /* save it for a while */ 618 619 fa.cmd = F_GETFL; 620 if ((error = fcntl(td, &fa)) != 0) 621 return error; 622 flags = *retval; 623 flags &= O_ASYNC; 624 flags |= svr4_to_bsd_flags((u_long) uap->arg); 625 fa.cmd = cmd; 626 fa.arg = (long) flags; 627 return fcntl(td, &fa); 628 } 629 630 case F_GETLK: 631 case F_SETLK: 632 case F_SETLKW: 633 { 634 struct svr4_flock ifl; 635 struct flock *flp, fl; 636 caddr_t sg = stackgap_init(); 637 638 flp = stackgap_alloc(&sg, sizeof(struct flock)); 639 fa.arg = (long) flp; 640 641 error = copyin(uap->arg, &ifl, sizeof ifl); 642 if (error) 643 return error; 644 645 svr4_to_bsd_flock(&ifl, &fl); 646 647 error = copyout(&fl, flp, sizeof fl); 648 if (error) 649 return error; 650 651 error = fcntl(td, &fa); 652 if (error || fa.cmd != F_GETLK) 653 return error; 654 655 error = copyin(flp, &fl, sizeof fl); 656 if (error) 657 return error; 658 659 bsd_to_svr4_flock(&fl, &ifl); 660 661 return copyout(&ifl, uap->arg, sizeof ifl); 662 } 663 case -1: 664 switch (uap->cmd) { 665 case SVR4_F_DUP2FD: 666 { 667 struct dup2_args du; 668 669 du.from = uap->fd; 670 du.to = (int)uap->arg; 671 error = dup2(td, &du); 672 if (error) 673 return error; 674 *retval = du.to; 675 return 0; 676 } 677 678 case SVR4_F_FREESP: 679 { 680 struct svr4_flock ifl; 681 struct flock fl; 682 683 error = copyin(uap->arg, &ifl, 684 sizeof ifl); 685 if (error) 686 return error; 687 svr4_to_bsd_flock(&ifl, &fl); 688 return fd_truncate(td, uap->fd, &fl); 689 } 690 691 case SVR4_F_GETLK64: 692 case SVR4_F_SETLK64: 693 case SVR4_F_SETLKW64: 694 { 695 struct svr4_flock64 ifl; 696 struct flock *flp, fl; 697 caddr_t sg = stackgap_init(); 698 699 flp = stackgap_alloc(&sg, sizeof(struct flock)); 700 fa.arg = (long) flp; 701 702 error = copyin(uap->arg, &ifl, 703 sizeof ifl); 704 if (error) 705 return error; 706 707 svr4_to_bsd_flock64(&ifl, &fl); 708 709 error = copyout(&fl, flp, sizeof fl); 710 if (error) 711 return error; 712 713 error = fcntl(td, &fa); 714 if (error || fa.cmd != F_GETLK) 715 return error; 716 717 error = copyin(flp, &fl, sizeof fl); 718 if (error) 719 return error; 720 721 bsd_to_svr4_flock64(&fl, &ifl); 722 723 return copyout(&ifl, uap->arg, 724 sizeof ifl); 725 } 726 727 case SVR4_F_FREESP64: 728 { 729 struct svr4_flock64 ifl; 730 struct flock fl; 731 732 error = copyin(uap->arg, &ifl, 733 sizeof ifl); 734 if (error) 735 return error; 736 svr4_to_bsd_flock64(&ifl, &fl); 737 return fd_truncate(td, uap->fd, &fl); 738 } 739 740 case SVR4_F_REVOKE: 741 return fd_revoke(td, uap->fd); 742 743 default: 744 return ENOSYS; 745 } 746 747 default: 748 return ENOSYS; 749 } 750}
|