1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 36 #include <sys/param.h> 37 #include <sys/isa_defs.h> 38 #include <sys/types.h> 39 #include <sys/sysmacros.h> 40 #include <sys/systm.h> 41 #include <sys/errno.h> 42 #include <sys/fcntl.h> 43 #include <sys/flock.h> 44 #include <sys/vnode.h> 45 #include <sys/file.h> 46 #include <sys/mode.h> 47 #include <sys/proc.h> 48 #include <sys/filio.h> 49 #include <sys/share.h> 50 #include <sys/debug.h> 51 #include <sys/rctl.h> 52 #include <sys/nbmlock.h> 53 54 #include <sys/cmn_err.h> 55 56 static int flock_check(vnode_t *, flock64_t *, offset_t, offset_t); 57 static int flock_get_start(vnode_t *, flock64_t *, offset_t, u_offset_t *); 58 static void fd_too_big(proc_t *); 59 60 /* 61 * File control. 62 */ 63 int 64 fcntl(int fdes, int cmd, intptr_t arg) 65 { 66 int iarg; 67 int error = 0; 68 int retval; 69 proc_t *p; 70 file_t *fp; 71 vnode_t *vp; 72 u_offset_t offset; 73 u_offset_t start; 74 struct vattr vattr; 75 int in_crit; 76 int flag; 77 struct flock sbf; 78 struct flock64 bf; 79 struct o_flock obf; 80 struct flock64_32 bf64_32; 81 struct fshare fsh; 82 struct shrlock shr; 83 struct shr_locowner shr_own; 84 offset_t maxoffset; 85 model_t datamodel; 86 int fdres; 87 88 #if defined(_ILP32) && !defined(lint) && defined(_SYSCALL32) 89 ASSERT(sizeof (struct flock) == sizeof (struct flock32)); 90 ASSERT(sizeof (struct flock64) == sizeof (struct flock64_32)); 91 #endif 92 #if defined(_LP64) && !defined(lint) && defined(_SYSCALL32) 93 ASSERT(sizeof (struct flock) == sizeof (struct flock64_64)); 94 ASSERT(sizeof (struct flock64) == sizeof (struct flock64_64)); 95 #endif 96 97 /* 98 * First, for speed, deal with the subset of cases 99 * that do not require getf() / releasef(). 100 */ 101 switch (cmd) { 102 case F_GETFD: 103 if ((error = f_getfd_error(fdes, &flag)) == 0) 104 retval = flag; 105 goto out; 106 107 case F_SETFD: 108 error = f_setfd_error(fdes, (int)arg); 109 retval = 0; 110 goto out; 111 112 case F_GETFL: 113 if ((error = f_getfl(fdes, &flag)) == 0) { 114 retval = (flag & (FMASK | FASYNC)); 115 if ((flag & (FSEARCH | FEXEC)) == 0) 116 retval += FOPEN; 117 else 118 retval |= (flag & (FSEARCH | FEXEC)); 119 } 120 goto out; 121 122 case F_GETXFL: 123 if ((error = f_getfl(fdes, &flag)) == 0) { 124 retval = flag; 125 if ((flag & (FSEARCH | FEXEC)) == 0) 126 retval += FOPEN; 127 } 128 goto out; 129 130 case F_BADFD: 131 if ((error = f_badfd(fdes, &fdres, (int)arg)) == 0) 132 retval = fdres; 133 goto out; 134 } 135 136 /* 137 * Second, for speed, deal with the subset of cases that 138 * require getf() / releasef() but do not require copyin. 139 */ 140 if ((fp = getf(fdes)) == NULL) { 141 error = EBADF; 142 goto out; 143 } 144 iarg = (int)arg; 145 146 switch (cmd) { 147 case F_DUPFD: 148 case F_DUPFD_CLOEXEC: 149 p = curproc; 150 if ((uint_t)iarg >= p->p_fno_ctl) { 151 if (iarg >= 0) 152 fd_too_big(p); 153 error = EINVAL; 154 goto done; 155 } 156 /* 157 * We need to increment the f_count reference counter 158 * before allocating a new file descriptor. 159 * Doing it other way round opens a window for race condition 160 * with closeandsetf() on the target file descriptor which can 161 * close the file still referenced by the original 162 * file descriptor. 163 */ 164 mutex_enter(&fp->f_tlock); 165 fp->f_count++; 166 mutex_exit(&fp->f_tlock); 167 if ((retval = ufalloc_file(iarg, fp)) == -1) { 168 /* 169 * New file descriptor can't be allocated. 170 * Revert the reference count. 171 */ 172 mutex_enter(&fp->f_tlock); 173 fp->f_count--; 174 mutex_exit(&fp->f_tlock); 175 error = EMFILE; 176 } else { 177 if (cmd == F_DUPFD_CLOEXEC) { 178 f_setfd(retval, FD_CLOEXEC); 179 } 180 } 181 182 if (error == 0 && fp->f_vnode != NULL) { 183 (void) VOP_IOCTL(fp->f_vnode, F_ASSOCI_PID, 184 (intptr_t)p->p_pidp->pid_id, FKIOCTL, kcred, 185 NULL, NULL); 186 } 187 188 goto done; 189 190 case F_DUP2FD_CLOEXEC: 191 if (fdes == iarg) { 192 error = EINVAL; 193 goto done; 194 } 195 196 /*FALLTHROUGH*/ 197 198 case F_DUP2FD: 199 p = curproc; 200 if (fdes == iarg) { 201 retval = iarg; 202 } else if ((uint_t)iarg >= p->p_fno_ctl) { 203 if (iarg >= 0) 204 fd_too_big(p); 205 error = EBADF; 206 } else { 207 /* 208 * We can't hold our getf(fdes) across the call to 209 * closeandsetf() because it creates a window for 210 * deadlock: if one thread is doing dup2(a, b) while 211 * another is doing dup2(b, a), each one will block 212 * waiting for the other to call releasef(). The 213 * solution is to increment the file reference count 214 * (which we have to do anyway), then releasef(fdes), 215 * then closeandsetf(). Incrementing f_count ensures 216 * that fp won't disappear after we call releasef(). 217 * When closeandsetf() fails, we try avoid calling 218 * closef() because of all the side effects. 219 */ 220 mutex_enter(&fp->f_tlock); 221 fp->f_count++; 222 mutex_exit(&fp->f_tlock); 223 releasef(fdes); 224 225 /* assume we have forked successfully */ 226 if (fp->f_vnode != NULL) { 227 (void) VOP_IOCTL(fp->f_vnode, F_ASSOCI_PID, 228 (intptr_t)p->p_pidp->pid_id, FKIOCTL, 229 kcred, NULL, NULL); 230 } 231 232 if ((error = closeandsetf(iarg, fp)) == 0) { 233 if (cmd == F_DUP2FD_CLOEXEC) { 234 f_setfd(iarg, FD_CLOEXEC); 235 } 236 retval = iarg; 237 } else { 238 mutex_enter(&fp->f_tlock); 239 if (fp->f_count > 1) { 240 fp->f_count--; 241 mutex_exit(&fp->f_tlock); 242 if (fp->f_vnode != NULL) { 243 (void) VOP_IOCTL(fp->f_vnode, 244 F_DASSOC_PID, 245 (intptr_t)p->p_pidp->pid_id, 246 FKIOCTL, kcred, NULL, NULL); 247 } 248 249 } else { 250 mutex_exit(&fp->f_tlock); 251 (void) closef(fp); 252 } 253 } 254 goto out; 255 } 256 goto done; 257 258 case F_SETFL: 259 vp = fp->f_vnode; 260 flag = fp->f_flag; 261 if ((iarg & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY)) 262 iarg &= ~FNDELAY; 263 if ((error = VOP_SETFL(vp, flag, iarg, fp->f_cred, NULL)) == 264 0) { 265 iarg &= FMASK; 266 mutex_enter(&fp->f_tlock); 267 fp->f_flag &= ~FMASK | (FREAD|FWRITE); 268 fp->f_flag |= (iarg - FOPEN) & ~(FREAD|FWRITE); 269 mutex_exit(&fp->f_tlock); 270 } 271 retval = 0; 272 goto done; 273 } 274 275 /* 276 * Finally, deal with the expensive cases. 277 */ 278 retval = 0; 279 in_crit = 0; 280 maxoffset = MAXOFF_T; 281 datamodel = DATAMODEL_NATIVE; 282 #if defined(_SYSCALL32_IMPL) 283 if ((datamodel = get_udatamodel()) == DATAMODEL_ILP32) 284 maxoffset = MAXOFF32_T; 285 #endif 286 287 vp = fp->f_vnode; 288 flag = fp->f_flag; 289 offset = fp->f_offset; 290 291 switch (cmd) { 292 /* 293 * The file system and vnode layers understand and implement 294 * locking with flock64 structures. So here once we pass through 295 * the test for compatibility as defined by LFS API, (for F_SETLK, 296 * F_SETLKW, F_GETLK, F_GETLKW, F_FREESP) we transform 297 * the flock structure to a flock64 structure and send it to the 298 * lower layers. Similarly in case of GETLK the returned flock64 299 * structure is transformed to a flock structure if everything fits 300 * in nicely, otherwise we return EOVERFLOW. 301 */ 302 303 case F_GETLK: 304 case F_O_GETLK: 305 case F_SETLK: 306 case F_SETLKW: 307 case F_SETLK_NBMAND: 308 309 /* 310 * Copy in input fields only. 311 */ 312 313 if (cmd == F_O_GETLK) { 314 if (datamodel != DATAMODEL_ILP32) { 315 error = EINVAL; 316 break; 317 } 318 319 if (copyin((void *)arg, &obf, sizeof (obf))) { 320 error = EFAULT; 321 break; 322 } 323 bf.l_type = obf.l_type; 324 bf.l_whence = obf.l_whence; 325 bf.l_start = (off64_t)obf.l_start; 326 bf.l_len = (off64_t)obf.l_len; 327 bf.l_sysid = (int)obf.l_sysid; 328 bf.l_pid = obf.l_pid; 329 } else if (datamodel == DATAMODEL_NATIVE) { 330 if (copyin((void *)arg, &sbf, sizeof (sbf))) { 331 error = EFAULT; 332 break; 333 } 334 /* 335 * XXX In an LP64 kernel with an LP64 application 336 * there's no need to do a structure copy here 337 * struct flock == struct flock64. However, 338 * we did it this way to avoid more conditional 339 * compilation. 340 */ 341 bf.l_type = sbf.l_type; 342 bf.l_whence = sbf.l_whence; 343 bf.l_start = (off64_t)sbf.l_start; 344 bf.l_len = (off64_t)sbf.l_len; 345 bf.l_sysid = sbf.l_sysid; 346 bf.l_pid = sbf.l_pid; 347 } 348 #if defined(_SYSCALL32_IMPL) 349 else { 350 struct flock32 sbf32; 351 if (copyin((void *)arg, &sbf32, sizeof (sbf32))) { 352 error = EFAULT; 353 break; 354 } 355 bf.l_type = sbf32.l_type; 356 bf.l_whence = sbf32.l_whence; 357 bf.l_start = (off64_t)sbf32.l_start; 358 bf.l_len = (off64_t)sbf32.l_len; 359 bf.l_sysid = sbf32.l_sysid; 360 bf.l_pid = sbf32.l_pid; 361 } 362 #endif /* _SYSCALL32_IMPL */ 363 364 /* 365 * 64-bit support: check for overflow for 32-bit lock ops 366 */ 367 if ((error = flock_check(vp, &bf, offset, maxoffset)) != 0) 368 break; 369 370 /* 371 * Not all of the filesystems understand F_O_GETLK, and 372 * there's no need for them to know. Map it to F_GETLK. 373 */ 374 if ((error = VOP_FRLOCK(vp, (cmd == F_O_GETLK) ? F_GETLK : cmd, 375 &bf, flag, offset, NULL, fp->f_cred, NULL)) != 0) 376 break; 377 378 /* 379 * If command is GETLK and no lock is found, only 380 * the type field is changed. 381 */ 382 if ((cmd == F_O_GETLK || cmd == F_GETLK) && 383 bf.l_type == F_UNLCK) { 384 /* l_type always first entry, always a short */ 385 if (copyout(&bf.l_type, &((struct flock *)arg)->l_type, 386 sizeof (bf.l_type))) 387 error = EFAULT; 388 break; 389 } 390 391 if (cmd == F_O_GETLK) { 392 /* 393 * Return an SVR3 flock structure to the user. 394 */ 395 obf.l_type = (int16_t)bf.l_type; 396 obf.l_whence = (int16_t)bf.l_whence; 397 obf.l_start = (int32_t)bf.l_start; 398 obf.l_len = (int32_t)bf.l_len; 399 if (bf.l_sysid > SHRT_MAX || bf.l_pid > SHRT_MAX) { 400 /* 401 * One or both values for the above fields 402 * is too large to store in an SVR3 flock 403 * structure. 404 */ 405 error = EOVERFLOW; 406 break; 407 } 408 obf.l_sysid = (int16_t)bf.l_sysid; 409 obf.l_pid = (int16_t)bf.l_pid; 410 if (copyout(&obf, (void *)arg, sizeof (obf))) 411 error = EFAULT; 412 } else if (cmd == F_GETLK) { 413 /* 414 * Copy out SVR4 flock. 415 */ 416 int i; 417 418 if (bf.l_start > maxoffset || bf.l_len > maxoffset) { 419 error = EOVERFLOW; 420 break; 421 } 422 423 if (datamodel == DATAMODEL_NATIVE) { 424 for (i = 0; i < 4; i++) 425 sbf.l_pad[i] = 0; 426 /* 427 * XXX In an LP64 kernel with an LP64 428 * application there's no need to do a 429 * structure copy here as currently 430 * struct flock == struct flock64. 431 * We did it this way to avoid more 432 * conditional compilation. 433 */ 434 sbf.l_type = bf.l_type; 435 sbf.l_whence = bf.l_whence; 436 sbf.l_start = (off_t)bf.l_start; 437 sbf.l_len = (off_t)bf.l_len; 438 sbf.l_sysid = bf.l_sysid; 439 sbf.l_pid = bf.l_pid; 440 if (copyout(&sbf, (void *)arg, sizeof (sbf))) 441 error = EFAULT; 442 } 443 #if defined(_SYSCALL32_IMPL) 444 else { 445 struct flock32 sbf32; 446 if (bf.l_start > MAXOFF32_T || 447 bf.l_len > MAXOFF32_T) { 448 error = EOVERFLOW; 449 break; 450 } 451 for (i = 0; i < 4; i++) 452 sbf32.l_pad[i] = 0; 453 sbf32.l_type = (int16_t)bf.l_type; 454 sbf32.l_whence = (int16_t)bf.l_whence; 455 sbf32.l_start = (off32_t)bf.l_start; 456 sbf32.l_len = (off32_t)bf.l_len; 457 sbf32.l_sysid = (int32_t)bf.l_sysid; 458 sbf32.l_pid = (pid32_t)bf.l_pid; 459 if (copyout(&sbf32, 460 (void *)arg, sizeof (sbf32))) 461 error = EFAULT; 462 } 463 #endif 464 } 465 break; 466 467 case F_CHKFL: 468 /* 469 * This is for internal use only, to allow the vnode layer 470 * to validate a flags setting before applying it. User 471 * programs can't issue it. 472 */ 473 error = EINVAL; 474 break; 475 476 case F_ALLOCSP: 477 case F_FREESP: 478 case F_ALLOCSP64: 479 case F_FREESP64: 480 /* 481 * Test for not-a-regular-file (and returning EINVAL) 482 * before testing for open-for-writing (and returning EBADF). 483 * This is relied upon by posix_fallocate() in libc. 484 */ 485 if (vp->v_type != VREG) { 486 error = EINVAL; 487 break; 488 } 489 490 if ((flag & FWRITE) == 0) { 491 error = EBADF; 492 break; 493 } 494 495 if (datamodel != DATAMODEL_ILP32 && 496 (cmd == F_ALLOCSP64 || cmd == F_FREESP64)) { 497 error = EINVAL; 498 break; 499 } 500 501 #if defined(_ILP32) || defined(_SYSCALL32_IMPL) 502 if (datamodel == DATAMODEL_ILP32 && 503 (cmd == F_ALLOCSP || cmd == F_FREESP)) { 504 struct flock32 sbf32; 505 /* 506 * For compatibility we overlay an SVR3 flock on an SVR4 507 * flock. This works because the input field offsets 508 * in "struct flock" were preserved. 509 */ 510 if (copyin((void *)arg, &sbf32, sizeof (sbf32))) { 511 error = EFAULT; 512 break; 513 } else { 514 bf.l_type = sbf32.l_type; 515 bf.l_whence = sbf32.l_whence; 516 bf.l_start = (off64_t)sbf32.l_start; 517 bf.l_len = (off64_t)sbf32.l_len; 518 bf.l_sysid = sbf32.l_sysid; 519 bf.l_pid = sbf32.l_pid; 520 } 521 } 522 #endif /* _ILP32 || _SYSCALL32_IMPL */ 523 524 #if defined(_LP64) 525 if (datamodel == DATAMODEL_LP64 && 526 (cmd == F_ALLOCSP || cmd == F_FREESP)) { 527 if (copyin((void *)arg, &bf, sizeof (bf))) { 528 error = EFAULT; 529 break; 530 } 531 } 532 #endif /* defined(_LP64) */ 533 534 #if !defined(_LP64) || defined(_SYSCALL32_IMPL) 535 if (datamodel == DATAMODEL_ILP32 && 536 (cmd == F_ALLOCSP64 || cmd == F_FREESP64)) { 537 if (copyin((void *)arg, &bf64_32, sizeof (bf64_32))) { 538 error = EFAULT; 539 break; 540 } else { 541 /* 542 * Note that the size of flock64 is different in 543 * the ILP32 and LP64 models, due to the l_pad 544 * field. We do not want to assume that the 545 * flock64 structure is laid out the same in 546 * ILP32 and LP64 environments, so we will 547 * copy in the ILP32 version of flock64 548 * explicitly and copy it to the native 549 * flock64 structure. 550 */ 551 bf.l_type = (short)bf64_32.l_type; 552 bf.l_whence = (short)bf64_32.l_whence; 553 bf.l_start = bf64_32.l_start; 554 bf.l_len = bf64_32.l_len; 555 bf.l_sysid = (int)bf64_32.l_sysid; 556 bf.l_pid = (pid_t)bf64_32.l_pid; 557 } 558 } 559 #endif /* !defined(_LP64) || defined(_SYSCALL32_IMPL) */ 560 561 if (cmd == F_ALLOCSP || cmd == F_FREESP) 562 error = flock_check(vp, &bf, offset, maxoffset); 563 else if (cmd == F_ALLOCSP64 || cmd == F_FREESP64) 564 error = flock_check(vp, &bf, offset, MAXOFFSET_T); 565 if (error) 566 break; 567 568 if (vp->v_type == VREG && bf.l_len == 0 && 569 bf.l_start > OFFSET_MAX(fp)) { 570 error = EFBIG; 571 break; 572 } 573 574 /* 575 * Make sure that there are no conflicting non-blocking 576 * mandatory locks in the region being manipulated. If 577 * there are such locks then return EACCES. 578 */ 579 if ((error = flock_get_start(vp, &bf, offset, &start)) != 0) 580 break; 581 582 if (nbl_need_check(vp)) { 583 u_offset_t begin; 584 ssize_t length; 585 586 nbl_start_crit(vp, RW_READER); 587 in_crit = 1; 588 vattr.va_mask = AT_SIZE; 589 if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) 590 != 0) 591 break; 592 begin = start > vattr.va_size ? vattr.va_size : start; 593 length = vattr.va_size > start ? vattr.va_size - start : 594 start - vattr.va_size; 595 if (nbl_conflict(vp, NBL_WRITE, begin, length, 0, 596 NULL)) { 597 error = EACCES; 598 break; 599 } 600 } 601 602 if (cmd == F_ALLOCSP64) 603 cmd = F_ALLOCSP; 604 else if (cmd == F_FREESP64) 605 cmd = F_FREESP; 606 607 error = VOP_SPACE(vp, cmd, &bf, flag, offset, fp->f_cred, NULL); 608 609 break; 610 611 #if !defined(_LP64) || defined(_SYSCALL32_IMPL) 612 case F_GETLK64: 613 case F_SETLK64: 614 case F_SETLKW64: 615 case F_SETLK64_NBMAND: 616 /* 617 * Large Files: Here we set cmd as *LK and send it to 618 * lower layers. *LK64 is only for the user land. 619 * Most of the comments described above for F_SETLK 620 * applies here too. 621 * Large File support is only needed for ILP32 apps! 622 */ 623 if (datamodel != DATAMODEL_ILP32) { 624 error = EINVAL; 625 break; 626 } 627 628 if (cmd == F_GETLK64) 629 cmd = F_GETLK; 630 else if (cmd == F_SETLK64) 631 cmd = F_SETLK; 632 else if (cmd == F_SETLKW64) 633 cmd = F_SETLKW; 634 else if (cmd == F_SETLK64_NBMAND) 635 cmd = F_SETLK_NBMAND; 636 637 /* 638 * Note that the size of flock64 is different in the ILP32 639 * and LP64 models, due to the sucking l_pad field. 640 * We do not want to assume that the flock64 structure is 641 * laid out in the same in ILP32 and LP64 environments, so 642 * we will copy in the ILP32 version of flock64 explicitly 643 * and copy it to the native flock64 structure. 644 */ 645 646 if (copyin((void *)arg, &bf64_32, sizeof (bf64_32))) { 647 error = EFAULT; 648 break; 649 } 650 651 bf.l_type = (short)bf64_32.l_type; 652 bf.l_whence = (short)bf64_32.l_whence; 653 bf.l_start = bf64_32.l_start; 654 bf.l_len = bf64_32.l_len; 655 bf.l_sysid = (int)bf64_32.l_sysid; 656 bf.l_pid = (pid_t)bf64_32.l_pid; 657 658 if ((error = flock_check(vp, &bf, offset, MAXOFFSET_T)) != 0) 659 break; 660 661 if ((error = VOP_FRLOCK(vp, cmd, &bf, flag, offset, 662 NULL, fp->f_cred, NULL)) != 0) 663 break; 664 665 if ((cmd == F_GETLK) && bf.l_type == F_UNLCK) { 666 if (copyout(&bf.l_type, &((struct flock *)arg)->l_type, 667 sizeof (bf.l_type))) 668 error = EFAULT; 669 break; 670 } 671 672 if (cmd == F_GETLK) { 673 int i; 674 675 /* 676 * We do not want to assume that the flock64 structure 677 * is laid out in the same in ILP32 and LP64 678 * environments, so we will copy out the ILP32 version 679 * of flock64 explicitly after copying the native 680 * flock64 structure to it. 681 */ 682 for (i = 0; i < 4; i++) 683 bf64_32.l_pad[i] = 0; 684 bf64_32.l_type = (int16_t)bf.l_type; 685 bf64_32.l_whence = (int16_t)bf.l_whence; 686 bf64_32.l_start = bf.l_start; 687 bf64_32.l_len = bf.l_len; 688 bf64_32.l_sysid = (int32_t)bf.l_sysid; 689 bf64_32.l_pid = (pid32_t)bf.l_pid; 690 if (copyout(&bf64_32, (void *)arg, sizeof (bf64_32))) 691 error = EFAULT; 692 } 693 break; 694 #endif /* !defined(_LP64) || defined(_SYSCALL32_IMPL) */ 695 696 case F_SHARE: 697 case F_SHARE_NBMAND: 698 case F_UNSHARE: 699 700 /* 701 * Copy in input fields only. 702 */ 703 if (copyin((void *)arg, &fsh, sizeof (fsh))) { 704 error = EFAULT; 705 break; 706 } 707 708 /* 709 * Local share reservations always have this simple form 710 */ 711 shr.s_access = fsh.f_access; 712 shr.s_deny = fsh.f_deny; 713 shr.s_sysid = 0; 714 shr.s_pid = ttoproc(curthread)->p_pid; 715 shr_own.sl_pid = shr.s_pid; 716 shr_own.sl_id = fsh.f_id; 717 shr.s_own_len = sizeof (shr_own); 718 shr.s_owner = (caddr_t)&shr_own; 719 error = VOP_SHRLOCK(vp, cmd, &shr, flag, fp->f_cred, NULL); 720 break; 721 722 default: 723 error = EINVAL; 724 break; 725 } 726 727 if (in_crit) 728 nbl_end_crit(vp); 729 730 done: 731 releasef(fdes); 732 out: 733 if (error) 734 return (set_errno(error)); 735 return (retval); 736 } 737 738 int 739 flock_check(vnode_t *vp, flock64_t *flp, offset_t offset, offset_t max) 740 { 741 struct vattr vattr; 742 int error; 743 u_offset_t start, end; 744 745 /* 746 * Determine the starting point of the request 747 */ 748 switch (flp->l_whence) { 749 case 0: /* SEEK_SET */ 750 start = (u_offset_t)flp->l_start; 751 if (start > max) 752 return (EINVAL); 753 break; 754 case 1: /* SEEK_CUR */ 755 if (flp->l_start > (max - offset)) 756 return (EOVERFLOW); 757 start = (u_offset_t)(flp->l_start + offset); 758 if (start > max) 759 return (EINVAL); 760 break; 761 case 2: /* SEEK_END */ 762 vattr.va_mask = AT_SIZE; 763 if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) 764 return (error); 765 if (flp->l_start > (max - (offset_t)vattr.va_size)) 766 return (EOVERFLOW); 767 start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size); 768 if (start > max) 769 return (EINVAL); 770 break; 771 default: 772 return (EINVAL); 773 } 774 775 /* 776 * Determine the range covered by the request. 777 */ 778 if (flp->l_len == 0) 779 end = MAXEND; 780 else if ((offset_t)flp->l_len > 0) { 781 if (flp->l_len > (max - start + 1)) 782 return (EOVERFLOW); 783 end = (u_offset_t)(start + (flp->l_len - 1)); 784 ASSERT(end <= max); 785 } else { 786 /* 787 * Negative length; why do we even allow this ? 788 * Because this allows easy specification of 789 * the last n bytes of the file. 790 */ 791 end = start; 792 start += (u_offset_t)flp->l_len; 793 (start)++; 794 if (start > max) 795 return (EINVAL); 796 ASSERT(end <= max); 797 } 798 ASSERT(start <= max); 799 if (flp->l_type == F_UNLCK && flp->l_len > 0 && 800 end == (offset_t)max) { 801 flp->l_len = 0; 802 } 803 if (start > end) 804 return (EINVAL); 805 return (0); 806 } 807 808 static int 809 flock_get_start(vnode_t *vp, flock64_t *flp, offset_t offset, u_offset_t *start) 810 { 811 struct vattr vattr; 812 int error; 813 814 /* 815 * Determine the starting point of the request. Assume that it is 816 * a valid starting point. 817 */ 818 switch (flp->l_whence) { 819 case 0: /* SEEK_SET */ 820 *start = (u_offset_t)flp->l_start; 821 break; 822 case 1: /* SEEK_CUR */ 823 *start = (u_offset_t)(flp->l_start + offset); 824 break; 825 case 2: /* SEEK_END */ 826 vattr.va_mask = AT_SIZE; 827 if (error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) 828 return (error); 829 *start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size); 830 break; 831 default: 832 return (EINVAL); 833 } 834 835 return (0); 836 } 837 838 /* 839 * Take rctl action when the requested file descriptor is too big. 840 */ 841 static void 842 fd_too_big(proc_t *p) 843 { 844 mutex_enter(&p->p_lock); 845 (void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE], 846 p->p_rctls, p, RCA_SAFE); 847 mutex_exit(&p->p_lock); 848 }