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