Print this page
    
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.c
          +++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_acl.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.
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
  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 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
       25 + *
       26 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25   27   */
  26   28  
  27   29  /*
  28   30   * ACL support for smbfs
  29   31   */
  30   32  
  31   33  #include <sys/systm.h>  /* bcopy, ... */
  32   34  #include <sys/errno.h>
  33   35  #include <sys/cred.h>
  34   36  #include <sys/cmn_err.h>
  35   37  #include <sys/kmem.h>
  36   38  #include <sys/sunddi.h>
  37   39  #include <sys/acl.h>
  38   40  #include <sys/vnode.h>
  39   41  #include <sys/vfs.h>
  40   42  #include <sys/byteorder.h>
  41   43  
  42   44  #include <netsmb/mchain.h>
  43   45  #include <netsmb/smb.h>
  44   46  #include <netsmb/smb_conn.h>
  45   47  #include <netsmb/smb_osdep.h>
  46   48  #include <netsmb/smb_subr.h>
  47   49  
  48   50  #include <smbfs/smbfs.h>
  49   51  #include <smbfs/smbfs_node.h>
  50   52  #include <smbfs/smbfs_subr.h>
  51   53  
  52   54  #include <sys/fs/smbfs_ioctl.h>
  53   55  #include <fs/fs_subr.h>
  54   56  #include "smbfs_ntacl.h"
  55   57  
  56   58  /* Sanity check SD sizes */
  57   59  #define MAX_RAW_SD_SIZE 32768
  58   60  #define SMALL_SD_SIZE   1024
  59   61  
  60   62  /*
  61   63   * smbfs_getsd() is a common function used by both
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
  62   64   * smbfs_ioctl SMBFSIO_GETSD and VOP_GETSECATTR.
  63   65   * Handles required rights, tmpopen/tmpclose.
  64   66   *
  65   67   * Note: smbfs_getsd allocates and returns an mblk chain,
  66   68   * which the caller must free.
  67   69   */
  68   70  static int
  69   71  smbfs_getsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
  70   72  {
  71   73          struct smb_cred scred;
  72      -        int error, cerror;
  73   74          smbmntinfo_t *smi;
  74   75          smbnode_t       *np;
  75      -        u_int16_t       fid = SMB_FID_UNUSED;
       76 +        smb_fh_t        *fid = NULL;
  76   77          uint32_t        sdlen = SMALL_SD_SIZE;
  77   78          uint32_t        rights = STD_RIGHT_READ_CONTROL_ACCESS;
       79 +        int error;
  78   80  
  79   81          if (selector & SACL_SECURITY_INFORMATION)
  80   82                  rights |= SEC_RIGHT_SYSTEM_SECURITY;
  81   83  
  82   84          np = VTOSMB(vp);
  83   85          smi = VTOSMI(vp);
  84   86  
  85      -        /* Shared lock for (possible) n_fid use. */
  86      -        if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
  87      -                return (EINTR);
  88   87          smb_credinit(&scred, cr);
  89   88  
  90   89          error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
  91   90          if (error)
  92   91                  goto out;
  93   92  
  94   93  again:
  95   94          /*
  96   95           * This does the OTW Get
  97   96           */
  98      -        error = smbfs_smb_getsec_m(smi->smi_share, fid,
  99      -            &scred, selector, mp, &sdlen);
       97 +        error = smbfs_smb_getsec(smi->smi_share, fid,
       98 +            selector, mp, &sdlen, &scred);
 100   99          /*
 101  100           * Server may give us an error indicating that we
 102  101           * need a larger data buffer to receive the SD,
 103  102           * and the size we'll need.  Use the given size,
 104  103           * but only after a sanity check.
 105  104           *
 106  105           * Let's check for specific error values here.
 107  106           * The NT error is: STATUS_BUFFER_TOO_SMALL,
 108  107           * or with old error codes, one of these:
 109  108           * ERRSRV/ERRnoroom, ERRDOS/122, ERRDOS/111
 110  109           * Those are mapped to: EMOREDATA, which is
 111  110           * later converted to E2BIG.
 112  111           */
 113  112          if (error == E2BIG &&
 114  113              sdlen > SMALL_SD_SIZE &&
 115  114              sdlen <= MAX_RAW_SD_SIZE)
 116  115                  goto again;
 117  116  
 118      -        cerror = smbfs_smb_tmpclose(np, fid, &scred);
 119      -        if (cerror)
 120      -                SMBVDEBUG("error %d closing file %s\n",
 121      -                    cerror, np->n_rpath);
      117 +        smbfs_smb_tmpclose(np, fid);
 122  118  
 123  119  out:
 124  120          smb_credrele(&scred);
 125      -        smbfs_rw_exit(&np->r_lkserlock);
 126  121  
 127  122          return (error);
 128  123  }
 129  124  
 130  125  /*
 131  126   * smbfs_setsd() is a common function used by both
 132  127   * smbfs_ioctl SMBFSIO_SETSD and VOP_SETSECATTR.
 133  128   * Handles required rights, tmpopen/tmpclose.
 134  129   *
 135  130   * Note: smbfs_setsd _consumes_ the passed *mp and
 136  131   * clears the pointer (so the caller won't free it)
 137  132   */
 138  133  static int
 139  134  smbfs_setsd(vnode_t *vp, uint32_t selector, mblk_t **mp, cred_t *cr)
 140  135  {
 141  136          struct smb_cred scred;
 142      -        int error, cerror;
 143  137          smbmntinfo_t *smi;
 144  138          smbnode_t       *np;
 145  139          uint32_t        rights;
 146      -        u_int16_t       fid = SMB_FID_UNUSED;
      140 +        smb_fh_t        *fid = NULL;
      141 +        int error;
 147  142  
 148  143          np = VTOSMB(vp);
 149  144          smi = VTOSMI(vp);
 150  145  
 151  146          /*
 152  147           * Which parts of the SD are we setting?
 153  148           * What rights do we need for that?
 154  149           */
 155  150          if (selector == 0)
 156  151                  return (0);
 157  152  
 158  153          rights = 0;
 159  154          if (selector & (OWNER_SECURITY_INFORMATION |
 160  155              GROUP_SECURITY_INFORMATION))
 161  156                  rights |= STD_RIGHT_WRITE_OWNER_ACCESS;
 162  157          if (selector & DACL_SECURITY_INFORMATION)
 163  158                  rights |= STD_RIGHT_WRITE_DAC_ACCESS;
 164  159          if (selector & SACL_SECURITY_INFORMATION)
 165  160                  rights |= SEC_RIGHT_SYSTEM_SECURITY;
 166  161  
 167      -        /* Shared lock for (possible) n_fid use. */
 168      -        if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
 169      -                return (EINTR);
 170  162          smb_credinit(&scred, cr);
 171  163  
 172  164          error = smbfs_smb_tmpopen(np, rights, &scred, &fid);
 173  165          if (error)
 174  166                  goto out;
 175  167  
 176  168          /*
 177  169           * We're setting the remote ACL now, so
 178  170           * invalidate our cached ACL just in case
 179  171           * the server doesn't do exactly as we ask.
 180  172           */
 181  173          mutex_enter(&np->r_statelock);
 182  174          np->r_sectime = gethrtime();
 183  175          mutex_exit(&np->r_statelock);
 184  176  
 185  177          /*
 186  178           * This does the OTW Set
 187  179           */
 188      -        error = smbfs_smb_setsec_m(smi->smi_share, fid,
 189      -            &scred, selector, mp);
      180 +        error = smbfs_smb_setsec(smi->smi_share, fid,
      181 +            selector, mp, &scred);
 190  182  
 191      -        cerror = smbfs_smb_tmpclose(np, fid, &scred);
 192      -        if (cerror)
 193      -                SMBVDEBUG("error %d closing file %s\n",
 194      -                    cerror, np->n_rpath);
      183 +        smbfs_smb_tmpclose(np, fid);
 195  184  
 196  185  out:
 197  186          smb_credrele(&scred);
 198      -        smbfs_rw_exit(&np->r_lkserlock);
 199  187  
 200  188          return (error);
 201  189  }
 202  190  
 203  191  /*
 204  192   * Helper for VOP_IOCTL: SMBFSIO_GETSD
 205  193   */
 206  194  int
 207  195  smbfs_acl_iocget(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
 208  196  {
 209  197          ioc_sdbuf_t iocb;
 210  198          mdchain_t *mdp, md_store;
 211  199          mblk_t *m;
 212  200          void *ubuf;
 213  201          int error;
 214  202  
 215  203          /*
 216  204           * Get the buffer information
 217  205           */
 218  206          if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
 219  207                  return (EFAULT);
 220  208  
 221  209          /*
 222  210           * This does the OTW Get (and maybe open, close)
 223  211           * Allocates and returns an mblk in &m.
 224  212           */
 225  213          error = smbfs_getsd(vp, iocb.selector, &m, cr);
 226  214          if (error)
 227  215                  return (error);
 228  216  
 229  217          /*
 230  218           * Have m.  Must free it before return.
 231  219           */
 232  220          mdp = &md_store;
 233  221          md_initm(mdp, m);
 234  222          iocb.used = m_fixhdr(m);
 235  223  
 236  224          /*
 237  225           * Always copyout the buffer information,
 238  226           * so the user can realloc and try again
 239  227           * after an EOVERFLOW return.
 240  228           */
 241  229          if (ddi_copyout(&iocb, (void *)arg, sizeof (iocb), flag)) {
 242  230                  error = EFAULT;
 243  231                  goto out;
 244  232          }
 245  233  
 246  234          if (iocb.used > iocb.alloc) {
 247  235                  error = EOVERFLOW;
 248  236                  goto out;
 249  237          }
 250  238  
 251  239          /*
 252  240           * Copyout the buffer contents (SD)
 253  241           */
 254  242          ubuf = (void *)(uintptr_t)iocb.addr;
 255  243          error = md_get_mem(mdp, ubuf, iocb.used, MB_MUSER);
 256  244  
 257  245  out:
 258  246          /* Note: m_freem(m) is done by... */
 259  247          md_done(mdp);
 260  248  
 261  249          return (error);
 262  250  }
 263  251  
 264  252  /*
 265  253   * Helper for VOP_IOCTL: SMBFSIO_SETSD
 266  254   */
 267  255  int
 268  256  smbfs_acl_iocset(vnode_t *vp, intptr_t arg, int flag, cred_t *cr)
 269  257  {
 270  258          ioc_sdbuf_t iocb;
 271  259          mbchain_t *mbp, mb_store;
 272  260          void *ubuf;
 273  261          int error;
 274  262  
 275  263          /*
 276  264           * Get the buffer information
 277  265           */
 278  266          if (ddi_copyin((void *)arg, &iocb, sizeof (iocb), flag))
 279  267                  return (EFAULT);
 280  268  
 281  269          if (iocb.used < sizeof (ntsecdesc_t) ||
 282  270              iocb.used >= MAX_RAW_SD_SIZE)
 283  271                  return (EINVAL);
 284  272  
 285  273          /*
 286  274           * Get the buffer contents (security descriptor data)
 287  275           */
 288  276          mbp = &mb_store;
 289  277          (void) mb_init(mbp);
 290  278          ubuf = (void *)(uintptr_t)iocb.addr;
 291  279          error = mb_put_mem(mbp, ubuf, iocb.used, MB_MUSER);
 292  280          if (error)
 293  281                  goto out;
 294  282  
 295  283          /*
 296  284           * This does the OTW Set (and maybe open, close)
 297  285           * It clears mb_top when consuming the message.
 298  286           */
 299  287          error = smbfs_setsd(vp, iocb.selector, &mbp->mb_top, cr);
 300  288  
 301  289  out:
 302  290          mb_done(mbp);
 303  291          return (error);
 304  292  
 305  293  }
 306  294  
 307  295  /*
 308  296   * Refresh our cached copy of the security attributes
 309  297   */
 310  298  static int
 311  299  smbfs_acl_refresh(vnode_t *vp, cred_t *cr)
 312  300  {
 313  301          smbnode_t *np;
 314  302          smbmntinfo_t *smi;
 315  303          mdchain_t *mdp, md_store;
 316  304          mblk_t *m = NULL;
 317  305          i_ntsd_t *sd = NULL;
 318  306          vsecattr_t vsa, ovsa;
 319  307          uint32_t selector;
 320  308          uid_t uid;
 321  309          gid_t gid;
 322  310          int error;
 323  311  
 324  312          np = VTOSMB(vp);
 325  313          smi = VTOSMI(vp);
 326  314  
 327  315          bzero(&md_store, sizeof (md_store));
 328  316          mdp = &md_store;
 329  317  
 330  318          /*
 331  319           * Which parts of the SD we request.
 332  320           * Not getting the SACL for now.
 333  321           */
 334  322          selector = DACL_SECURITY_INFORMATION |
 335  323              OWNER_SECURITY_INFORMATION |
 336  324              GROUP_SECURITY_INFORMATION;
 337  325  
 338  326          /*
 339  327           * This does the OTW Get (and maybe open, close)
 340  328           * Allocates and returns an mblk in &m.
 341  329           */
 342  330          error = smbfs_getsd(vp, selector, &m, cr);
 343  331          if (error)
 344  332                  goto out;
 345  333          /* Note: allocated *m */
 346  334          md_initm(mdp, m);
 347  335  
 348  336          /*
 349  337           * Parse the OtW security descriptor,
 350  338           * storing in our internal form.
 351  339           */
 352  340          error = md_get_ntsd(mdp, &sd);
 353  341          if (error)
 354  342                  goto out;
 355  343  
 356  344          /*
 357  345           * Convert the Windows security descriptor to a
 358  346           * ZFS ACL (and owner ID, primary group ID).
 359  347           */
 360  348          bzero(&vsa, sizeof (vsa));
 361  349          vsa.vsa_mask = VSA_ACE | VSA_ACECNT;
 362  350          error = smbfs_acl_sd2zfs(sd, &vsa, &uid, &gid);
 363  351          if (error)
 364  352                  goto out;
 365  353  
 366  354          ASSERT(vsa.vsa_aclentp != NULL);
 367  355          SMBVDEBUG("uid=%u, gid=%u", uid, gid);
 368  356  
 369  357          /*
 370  358           * Store the results in r_secattr, n_uid, n_gid
 371  359           */
 372  360          mutex_enter(&np->r_statelock);
 373  361          ovsa = np->r_secattr;
 374  362          np->r_secattr = vsa;
 375  363          np->n_uid = uid;
 376  364          np->n_gid = gid;
 377  365          /*
 378  366           * ACLs don't change frequently, so cache these
 379  367           * for a relatively long time (ac dir max).
 380  368           */
 381  369          np->r_sectime = gethrtime() + smi->smi_acdirmax;
 382  370          mutex_exit(&np->r_statelock);
 383  371  
 384  372          /* Allocated in: smbfs_acl_sd2zfs */
 385  373          if (ovsa.vsa_aclentp != NULL)
 386  374                  kmem_free(ovsa.vsa_aclentp, ovsa.vsa_aclentsz);
 387  375  
 388  376  out:
 389  377          if (sd != NULL)
 390  378                  smbfs_acl_free_sd(sd);
 391  379          /* Note: m_freem(m) is done by... */
 392  380          md_done(mdp);
 393  381  
 394  382          return (error);
 395  383  }
 396  384  
 397  385  /*
 398  386   * Helper for smbfsgetattr()
 399  387   *
 400  388   * Just refresh the ACL cache if needed,
 401  389   * which updates n_uid/n_gid
 402  390   */
 403  391  int
 404  392  smbfs_acl_getids(vnode_t *vp, cred_t *cr)
 405  393  {
 406  394          smbnode_t *np;
 407  395          int error;
 408  396  
 409  397          np = VTOSMB(vp);
 410  398  
 411  399          /*
 412  400           * NB: extended attribute files and directories
 413  401           * do not have ACLs separate from the parent.
 414  402           * Let the caller do ACL fabrication.
 415  403           */
 416  404          if (np->n_flag & N_XATTR)
 417  405                  return (ENOSYS);
 418  406  
 419  407          mutex_enter(&np->r_statelock);
 420  408          if (gethrtime() >= np->r_sectime) {
 421  409                  /* Need to update r_secattr */
 422  410                  mutex_exit(&np->r_statelock);
 423  411                  error = smbfs_acl_refresh(vp, cr);
 424  412                  return (error);
 425  413          }
 426  414          mutex_exit(&np->r_statelock);
 427  415  
 428  416          return (0);
 429  417  }
 430  418  
 431  419  /*
 432  420   * Helper for VOP_GETSECATTR
 433  421   *
 434  422   * Refresh the ACL cache if needed, then
 435  423   * duplicate the requested parts of the vsecattr.
 436  424   */
 437  425  /* ARGSUSED */
 438  426  int
 439  427  smbfs_acl_getvsa(vnode_t *vp, vsecattr_t *vsa,
 440  428          int flag, cred_t *cr)
 441  429  {
 442  430          smbnode_t *np;
 443  431          int error;
 444  432  
 445  433          np = VTOSMB(vp);
 446  434  
 447  435          /*
 448  436           * NB: extended attribute files and directories
 449  437           * do not have ACLs separate from the parent.
 450  438           * Let the caller do ACL fabrication.
 451  439           */
 452  440          if (np->n_flag & N_XATTR)
 453  441                  return (ENOSYS);
 454  442  
 455  443          mutex_enter(&np->r_statelock);
 456  444  
 457  445          if (np->r_secattr.vsa_aclentp == NULL ||
 458  446              gethrtime() >= np->r_sectime) {
 459  447                  /* Need to update r_secattr */
 460  448                  mutex_exit(&np->r_statelock);
 461  449  
 462  450                  error = smbfs_acl_refresh(vp, cr);
 463  451                  if (error)
 464  452                          return (error);
 465  453  
 466  454                  mutex_enter(&np->r_statelock);
 467  455          }
 468  456          ASSERT(np->r_secattr.vsa_aclentp != NULL);
 469  457  
 470  458          /*
 471  459           * Duplicate requested parts of r_secattr
 472  460           */
 473  461  
 474  462          if (vsa->vsa_mask & VSA_ACECNT)
 475  463                  vsa->vsa_aclcnt = np->r_secattr.vsa_aclcnt;
 476  464  
 477  465          if (vsa->vsa_mask & VSA_ACE) {
 478  466                  vsa->vsa_aclentsz = np->r_secattr.vsa_aclentsz;
 479  467                  vsa->vsa_aclentp = kmem_alloc(vsa->vsa_aclentsz, KM_SLEEP);
 480  468                  bcopy(np->r_secattr.vsa_aclentp, vsa->vsa_aclentp,
 481  469                      vsa->vsa_aclentsz);
 482  470          }
 483  471  
 484  472          mutex_exit(&np->r_statelock);
 485  473          return (0);
 486  474  }
 487  475  
 488  476  /*
 489  477   * Helper for smbfs_acl_setids, smbfs_acl_setvsa
 490  478   */
 491  479  static int
 492  480  smbfs_acl_store(vnode_t *vp, vsecattr_t *vsa, uid_t uid, gid_t gid,
 493  481          uint32_t selector, cred_t *cr)
 494  482  {
 495  483          mbchain_t *mbp, mb_store;
 496  484          i_ntsd_t *sd;
 497  485          int error;
 498  486  
 499  487          ASSERT(selector != 0);
 500  488  
 501  489          sd = NULL;
 502  490          bzero(&mb_store, sizeof (mb_store));
 503  491          mbp = &mb_store;
 504  492  
 505  493          /*
 506  494           * Convert a ZFS ACL (and owner ID, group ID)
 507  495           * into an NT SD, internal form.
 508  496           */
 509  497          error = smbfs_acl_zfs2sd(vsa, uid, gid, selector, &sd);
 510  498          if (error)
 511  499                  goto out;
 512  500  
 513  501          /*
 514  502           * Marshall the internal form SD into an
 515  503           * OtW security descriptor.
 516  504           */
 517  505          (void) mb_init(mbp);
 518  506          error = mb_put_ntsd(mbp, sd);
 519  507          if (error)
 520  508                  goto out;
 521  509  
 522  510          /*
 523  511           * This does the OTW Set (and maybe open, close)
 524  512           * It clears mb_top when consuming the message.
 525  513           */
 526  514          error = smbfs_setsd(vp, selector, &mbp->mb_top, cr);
 527  515  
 528  516  out:
 529  517          if (sd != NULL)
 530  518                  smbfs_acl_free_sd(sd);
 531  519          mb_done(mbp);
 532  520          return (error);
 533  521  }
 534  522  
 535  523  /*
 536  524   * Helper for smbfs_setattr()
 537  525   *
 538  526   * Set the passed UID/GID as indicated by va_mask.
 539  527   */
 540  528  int
 541  529  smbfs_acl_setids(vnode_t *vp, vattr_t *vap, cred_t *cr)
 542  530  {
 543  531          uid_t uid = (uid_t)-1;
 544  532          gid_t gid = (uid_t)-1;
 545  533          uint32_t selector = 0;
 546  534          int error;
 547  535  
 548  536          if (vap->va_mask & AT_UID) {
 549  537                  selector |= OWNER_SECURITY_INFORMATION;
 550  538                  uid = vap->va_uid;
 551  539          }
 552  540  
 553  541          if (vap->va_mask & AT_GID) {
 554  542                  selector |= GROUP_SECURITY_INFORMATION;
 555  543                  gid = vap->va_gid;
 556  544          }
 557  545  
 558  546          if (selector == 0)
 559  547                  return (0);
 560  548  
 561  549          error = smbfs_acl_store(vp, NULL, uid, gid, selector, cr);
 562  550          return (error);
 563  551  }
 564  552  
 565  553  /*
 566  554   * Helper for VOP_SETSECATTR
 567  555   * Convert ZFS to NT form, call smbfs_setsd.
 568  556   */
 569  557  /* ARGSUSED */
 570  558  int
 571  559  smbfs_acl_setvsa(vnode_t *vp, vsecattr_t *vsa,
 572  560          int flag, cred_t *cr)
 573  561  {
 574  562          uint32_t selector = DACL_SECURITY_INFORMATION;
 575  563          smbnode_t *np = VTOSMB(vp);
 576  564          int error;
 577  565  
 578  566          /*
 579  567           * NB: extended attribute files and directories
 580  568           * do not have ACLs separate from the parent.
 581  569           */
 582  570          if (np->n_flag & N_XATTR)
 583  571                  return (ENOSYS);
 584  572  
 585  573          /*
 586  574           * When handling ACE_OWNER or ACE_GROUP entries,
 587  575           * we need the current owner and group.
 588  576           */
 589  577          error = smbfs_acl_getids(vp, cr);
 590  578          if (error)
 591  579                  return (error);
 592  580  
 593  581          error = smbfs_acl_store(vp, vsa, np->n_uid, np->n_gid, selector, cr);
 594  582          return (error);
 595  583  }
  
    | 
      ↓ open down ↓ | 
    387 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX