Print this page
    
OS-4098 move open, close and fcntl into the kernel
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/syscall/open.c
          +++ new/usr/src/uts/common/syscall/open.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   */
  25   25  
  26   26  /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
  27   27  /*        All Rights Reserved   */
  28   28  
  29   29  /*
  30   30   * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
  31   31   */
  32   32  /*
  33   33   * Portions of this source code were derived from Berkeley 4.3 BSD
  34   34   * under license from the Regents of the University of California.
  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/user.h>
  42   42  #include <sys/systm.h>
  43   43  #include <sys/errno.h>
  44   44  #include <sys/fcntl.h>
  45   45  #include <sys/stat.h>
  46   46  #include <sys/vnode.h>
  47   47  #include <sys/vfs.h>
  48   48  #include <sys/file.h>
  49   49  #include <sys/mode.h>
  50   50  #include <sys/uio.h>
  51   51  #include <sys/debug.h>
  52   52  #include <c2/audit.h>
  53   53  
  54   54  /*
  55   55   * Common code for openat().  Check permissions, allocate an open
  56   56   * file structure, and call the device open routine (if any).
  57   57   */
  58   58  
  59   59  static int
  60   60  copen(int startfd, char *fname, int filemode, int createmode)
  61   61  {
  62   62          struct pathname pn;
  63   63          vnode_t *vp, *sdvp;
  64   64          file_t *fp, *startfp;
  65   65          enum vtype type;
  66   66          int error;
  
    | 
      ↓ open down ↓ | 
    66 lines elided | 
    
      ↑ open up ↑ | 
  
  67   67          int fd, dupfd;
  68   68          vnode_t *startvp;
  69   69          proc_t *p = curproc;
  70   70          uio_seg_t seg = UIO_USERSPACE;
  71   71          char *open_filename = fname;
  72   72          uint32_t auditing = AU_AUDITING();
  73   73          char startchar;
  74   74  
  75   75          if (filemode & (FSEARCH|FEXEC)) {
  76   76                  /*
  77      -                 * Must be one or the other and neither FREAD nor FWRITE
       77 +                 * Must be one or the other.
  78   78                   * Must not be any of FAPPEND FCREAT FTRUNC FXATTR FXATTRDIROPEN
  79      -                 * XXX: Should these just be silently ignored?
       79 +                 * XXX: Should these just be silently ignored like we
       80 +                 * silently ignore FREAD|FWRITE?
  80   81                   */
  81      -                if ((filemode & (FREAD|FWRITE)) ||
  82      -                    (filemode & (FSEARCH|FEXEC)) == (FSEARCH|FEXEC) ||
       82 +                if ((filemode & (FSEARCH|FEXEC)) == (FSEARCH|FEXEC) ||
  83   83                      (filemode & (FAPPEND|FCREAT|FTRUNC|FXATTR|FXATTRDIROPEN)))
  84   84                          return (set_errno(EINVAL));
  85   85          }
  86   86  
  87   87          if (startfd == AT_FDCWD) {
  88   88                  /*
  89   89                   * Regular open()
  90   90                   */
  91   91                  startvp = NULL;
  92   92          } else {
  93   93                  /*
  94   94                   * We're here via openat()
  95   95                   */
  96   96                  if (copyin(fname, &startchar, sizeof (char)))
  97   97                          return (set_errno(EFAULT));
  98   98  
  99   99                  /*
 100  100                   * if startchar is / then startfd is ignored
 101  101                   */
 102  102                  if (startchar == '/')
 103  103                          startvp = NULL;
 104  104                  else {
 105  105                          if ((startfp = getf(startfd)) == NULL)
 106  106                                  return (set_errno(EBADF));
 107  107                          startvp = startfp->f_vnode;
 108  108                          VN_HOLD(startvp);
 109  109                          releasef(startfd);
 110  110                  }
 111  111          }
 112  112  
 113  113          /*
 114  114           * Handle __openattrdirat() requests
 115  115           */
 116  116          if (filemode & FXATTRDIROPEN) {
 117  117                  if (auditing && startvp != NULL)
 118  118                          audit_setfsat_path(1);
 119  119                  if (error = lookupnameat(fname, seg, FOLLOW,
 120  120                      NULLVPP, &vp, startvp))
 121  121                          return (set_errno(error));
 122  122                  if (startvp != NULL)
 123  123                          VN_RELE(startvp);
 124  124  
 125  125                  startvp = vp;
 126  126          }
 127  127  
 128  128          /*
 129  129           * Do we need to go into extended attribute space?
 130  130           */
 131  131          if (filemode & FXATTR) {
 132  132                  if (startfd == AT_FDCWD) {
 133  133                          if (copyin(fname, &startchar, sizeof (char)))
 134  134                                  return (set_errno(EFAULT));
 135  135  
 136  136                          /*
 137  137                           * If startchar == '/' then no extended attributes
 138  138                           * are looked up.
 139  139                           */
 140  140                          if (startchar == '/') {
 141  141                                  startvp = NULL;
 142  142                          } else {
 143  143                                  mutex_enter(&p->p_lock);
 144  144                                  startvp = PTOU(p)->u_cdir;
 145  145                                  VN_HOLD(startvp);
 146  146                                  mutex_exit(&p->p_lock);
 147  147                          }
 148  148                  }
 149  149  
 150  150                  /*
 151  151                   * Make sure we have a valid extended attribute request.
 152  152                   * We must either have a real fd or AT_FDCWD and a relative
 153  153                   * pathname.
 154  154                   */
 155  155                  if (startvp == NULL) {
 156  156                          goto noxattr;
 157  157                  }
 158  158          }
 159  159  
 160  160          if (filemode & (FXATTR|FXATTRDIROPEN)) {
 161  161                  vattr_t vattr;
 162  162  
 163  163                  if (error = pn_get(fname, UIO_USERSPACE, &pn)) {
 164  164                          goto out;
 165  165                  }
 166  166  
 167  167                  /*
 168  168                   * In order to access hidden attribute directory the
 169  169                   * user must be able to stat() the file
 170  170                   */
 171  171                  vattr.va_mask = AT_ALL;
 172  172                  if (error = VOP_GETATTR(startvp, &vattr, 0, CRED(), NULL)) {
 173  173                          pn_free(&pn);
 174  174                          goto out;
 175  175                  }
 176  176  
 177  177                  if ((startvp->v_vfsp->vfs_flag & VFS_XATTR) != 0 ||
 178  178                      vfs_has_feature(startvp->v_vfsp, VFSFT_SYSATTR_VIEWS)) {
 179  179                          error = VOP_LOOKUP(startvp, "", &sdvp, &pn,
 180  180                              (filemode & FXATTRDIROPEN) ? LOOKUP_XATTR :
 181  181                              LOOKUP_XATTR|CREATE_XATTR_DIR, rootvp, CRED(),
 182  182                              NULL, NULL, NULL);
 183  183                  } else {
 184  184                          error = EINVAL;
 185  185                  }
 186  186  
 187  187                  /*
 188  188                   * For __openattrdirat() use "." as filename to open
 189  189                   * as part of vn_openat()
 190  190                   */
 191  191                  if (error == 0 && (filemode & FXATTRDIROPEN)) {
 192  192                          open_filename = ".";
 193  193                          seg = UIO_SYSSPACE;
 194  194                  }
 195  195  
 196  196                  pn_free(&pn);
 197  197                  if (error != 0)
 198  198                          goto out;
 199  199  
 200  200                  VN_RELE(startvp);
 201  201                  startvp = sdvp;
 202  202          }
 203  203  
 204  204  noxattr:
 205  205          if ((filemode & (FREAD|FWRITE|FSEARCH|FEXEC|FXATTRDIROPEN)) != 0) {
 206  206                  if ((filemode & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY))
 207  207                          filemode &= ~FNDELAY;
 208  208                  error = falloc((vnode_t *)NULL, filemode, &fp, &fd);
 209  209                  if (error == 0) {
 210  210                          if (auditing && startvp != NULL)
 211  211                                  audit_setfsat_path(1);
 212  212                          /*
 213  213                           * Last arg is a don't-care term if
 214  214                           * !(filemode & FCREAT).
 215  215                           */
 216  216                          error = vn_openat(open_filename, seg, filemode,
 217  217                              (int)(createmode & MODEMASK),
 218  218                              &vp, CRCREAT, PTOU(curproc)->u_cmask,
 219  219                              startvp, fd);
 220  220  
 221  221                          if (startvp != NULL)
 222  222                                  VN_RELE(startvp);
 223  223                          if (error == 0) {
 224  224                                  if ((vp->v_flag & VDUP) == 0) {
 225  225                                          fp->f_vnode = vp;
 226  226                                          mutex_exit(&fp->f_tlock);
 227  227                                          /*
 228  228                                           * We must now fill in the slot
 229  229                                           * falloc reserved.
 230  230                                           */
 231  231                                          setf(fd, fp);
 232  232                                          if ((filemode & FCLOEXEC) != 0) {
 233  233                                                  f_setfd(fd, FD_CLOEXEC);
 234  234                                          }
 235  235                                          return (fd);
 236  236                                  } else {
 237  237                                          /*
 238  238                                           * Special handling for /dev/fd.
 239  239                                           * Give up the file pointer
 240  240                                           * and dup the indicated file descriptor
 241  241                                           * (in v_rdev). This is ugly, but I've
 242  242                                           * seen worse.
 243  243                                           */
 244  244                                          unfalloc(fp);
 245  245                                          dupfd = getminor(vp->v_rdev);
 246  246                                          type = vp->v_type;
 247  247                                          mutex_enter(&vp->v_lock);
 248  248                                          vp->v_flag &= ~VDUP;
 249  249                                          mutex_exit(&vp->v_lock);
 250  250                                          VN_RELE(vp);
 251  251                                          if (type != VCHR)
 252  252                                                  return (set_errno(EINVAL));
 253  253                                          if ((fp = getf(dupfd)) == NULL) {
 254  254                                                  setf(fd, NULL);
 255  255                                                  return (set_errno(EBADF));
 256  256                                          }
 257  257                                          mutex_enter(&fp->f_tlock);
 258  258                                          fp->f_count++;
 259  259                                          mutex_exit(&fp->f_tlock);
 260  260                                          setf(fd, fp);
 261  261                                          if ((filemode & FCLOEXEC) != 0) {
 262  262                                                  f_setfd(fd, FD_CLOEXEC);
 263  263                                          }
 264  264                                          releasef(dupfd);
 265  265                                  }
 266  266                                  return (fd);
 267  267                          } else {
 268  268                                  setf(fd, NULL);
 269  269                                  unfalloc(fp);
 270  270                                  return (set_errno(error));
 271  271                          }
 272  272                  }
 273  273          } else {
 274  274                  error = EINVAL;
 275  275          }
 276  276  out:
 277  277          if (startvp != NULL)
 278  278                  VN_RELE(startvp);
 279  279          return (set_errno(error));
 280  280  }
 281  281  
 282  282  #define OPENMODE32(fmode)       (((fmode) & (FSEARCH | FEXEC))? \
 283  283                                      (fmode) : (fmode) - FOPEN)
 284  284  #define OPENMODE64(fmode)       (OPENMODE32(fmode) | FOFFMAX)
 285  285  #ifdef _LP64
 286  286  #define OPENMODE(fmode)         OPENMODE64(fmode)
 287  287  #else
 288  288  #define OPENMODE(fmode)         OPENMODE32(fmode)
 289  289  #endif
 290  290  
 291  291  /*
 292  292   * Open a file.
 293  293   */
 294  294  int
 295  295  openat(int fd, char *path, int fmode, int cmode)
 296  296  {
 297  297          return (copen(fd, path, OPENMODE(fmode), cmode));
 298  298  }
 299  299  
 300  300  int
 301  301  open(char *path, int fmode, int cmode)
 302  302  {
 303  303          return (openat(AT_FDCWD, path, fmode, cmode));
 304  304  }
 305  305  
 306  306  #if defined(_ILP32) || defined(_SYSCALL32_IMPL)
 307  307  /*
 308  308   * Open for large files in 32-bit environment. Sets the FOFFMAX flag.
 309  309   */
 310  310  int
 311  311  openat64(int fd, char *path, int fmode, int cmode)
 312  312  {
 313  313          return (copen(fd, path, OPENMODE64(fmode), cmode));
 314  314  }
 315  315  
 316  316  int
 317  317  open64(char *path, int fmode, int cmode)
 318  318  {
 319  319          return (openat64(AT_FDCWD, path, fmode, cmode));
 320  320  }
 321  321  
 322  322  #endif  /* _ILP32 || _SYSCALL32_IMPL */
 323  323  
 324  324  #ifdef _SYSCALL32_IMPL
 325  325  /*
 326  326   * Open for 32-bit compatibility on 64-bit kernel
 327  327   */
 328  328  int
 329  329  openat32(int fd, char *path, int fmode, int cmode)
 330  330  {
 331  331          return (copen(fd, path, OPENMODE32(fmode), cmode));
 332  332  }
 333  333  
 334  334  int
 335  335  open32(char *path, int fmode, int cmode)
 336  336  {
 337  337          return (openat32(AT_FDCWD, path, fmode, cmode));
 338  338  }
 339  339  
 340  340  #endif  /* _SYSCALL32_IMPL */
  
    | 
      ↓ open down ↓ | 
    248 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX