/* * Let avp handle security attributes (acl's). */ static int devfs_getsecattr(struct vnode *vp, struct vsecattr *vsap, int flags, struct cred *cr) { dvnode_t *dv = VTODV(vp); struct vnode *avp; int error; dcmn_err2(("devfs_getsecattr %s\n", dv->dv_name)); ASSERT(vp->v_type == VDIR || vp->v_type == VCHR || vp->v_type == VBLK); rw_enter(&dv->dv_contents, RW_READER); avp = dv->dv_attrvp; /* fabricate the acl */ if (avp == NULL) { error = fs_fab_acl(vp, vsap, flags, cr); rw_exit(&dv->dv_contents); return (error); } error = VOP_GETSECATTR(avp, vsap, flags, cr); dsysdebug(error, ("vop_getsecattr %s %d\n", VTODV(vp)->dv_name, error)); rw_exit(&dv->dv_contents); return (error); }
/* ARGSUSED */ void acl2_getacl(GETACL2args *args, GETACL2res *resp, struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) { int error; vnode_t *vp; vattr_t va; vp = nfs_fhtovp(&args->fh, exi); if (vp == NULL) { resp->status = NFSERR_STALE; return; } bzero((caddr_t)&resp->resok.acl, sizeof (resp->resok.acl)); resp->resok.acl.vsa_mask = args->mask; error = VOP_GETSECATTR(vp, &resp->resok.acl, 0, cr, NULL); if ((error == ENOSYS) && !(exi->exi_export.ex_flags & EX_NOACLFAB)) { /* * If the underlying file system doesn't support * aclent_t type acls, fabricate an acl. This is * required in order to to support existing clients * that require the call to VOP_GETSECATTR to * succeed while making the assumption that all * file systems support aclent_t type acls. This * causes problems for servers exporting ZFS file * systems because ZFS supports ace_t type acls, * and fails (with ENOSYS) when asked for aclent_t * type acls. * * Note: if the fs_fab_acl() fails, we have other problems. * This error should be returned to the caller. */ error = fs_fab_acl(vp, &resp->resok.acl, 0, cr, NULL); } if (error) { VN_RELE(vp); resp->status = puterrno(error); return; } va.va_mask = AT_ALL; error = rfs4_delegated_getattr(vp, &va, 0, cr); VN_RELE(vp); /* check for overflowed values */ if (!error) { error = vattr_to_nattr(&va, &resp->resok.attr); } if (error) { resp->status = puterrno(error); if (resp->resok.acl.vsa_aclcnt > 0 && resp->resok.acl.vsa_aclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_aclentp, resp->resok.acl.vsa_aclcnt * sizeof (aclent_t)); } if (resp->resok.acl.vsa_dfaclcnt > 0 && resp->resok.acl.vsa_dfaclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp, resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t)); } return; } resp->status = NFS_OK; if (!(args->mask & NA_ACL)) { if (resp->resok.acl.vsa_aclcnt > 0 && resp->resok.acl.vsa_aclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_aclentp, resp->resok.acl.vsa_aclcnt * sizeof (aclent_t)); } resp->resok.acl.vsa_aclentp = NULL; } if (!(args->mask & NA_DFACL)) { if (resp->resok.acl.vsa_dfaclcnt > 0 && resp->resok.acl.vsa_dfaclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp, resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t)); } resp->resok.acl.vsa_dfaclentp = NULL; } }
/* ARGSUSED */ void acl3_getacl(GETACL3args *args, GETACL3res *resp, struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) { int error; vnode_t *vp; vattr_t *vap; vattr_t va; vap = NULL; vp = nfs3_fhtovp(&args->fh, exi); if (vp == NULL) { error = ESTALE; goto out; } va.va_mask = AT_ALL; vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; bzero((caddr_t)&resp->resok.acl, sizeof (resp->resok.acl)); resp->resok.acl.vsa_mask = args->mask; error = VOP_GETSECATTR(vp, &resp->resok.acl, 0, cr, NULL); if ((error == ENOSYS) && !(exi->exi_export.ex_flags & EX_NOACLFAB)) { /* * If the underlying file system doesn't support * aclent_t type acls, fabricate an acl. This is * required in order to to support existing clients * that require the call to VOP_GETSECATTR to * succeed while making the assumption that all * file systems support aclent_t type acls. This * causes problems for servers exporting ZFS file * systems because ZFS supports ace_t type acls, * and fails (with ENOSYS) when asked for aclent_t * type acls. * * Note: if the fs_fab_acl() fails, we have other problems. * This error should be returned to the caller. */ error = fs_fab_acl(vp, &resp->resok.acl, 0, cr, NULL); } if (error) goto out; va.va_mask = AT_ALL; vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; VN_RELE(vp); resp->status = NFS3_OK; vattr_to_post_op_attr(vap, &resp->resok.attr); if (!(args->mask & NA_ACL)) { if (resp->resok.acl.vsa_aclcnt > 0 && resp->resok.acl.vsa_aclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_aclentp, resp->resok.acl.vsa_aclcnt * sizeof (aclent_t)); } resp->resok.acl.vsa_aclentp = NULL; } if (!(args->mask & NA_DFACL)) { if (resp->resok.acl.vsa_dfaclcnt > 0 && resp->resok.acl.vsa_dfaclentp != NULL) { kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp, resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t)); } resp->resok.acl.vsa_dfaclentp = NULL; } return; out: if (curthread->t_flag & T_WOULDBLOCK) { curthread->t_flag &= ~T_WOULDBLOCK; resp->status = NFS3ERR_JUKEBOX; } else resp->status = puterrno3(error); out1: if (vp != NULL) VN_RELE(vp); vattr_to_post_op_attr(vap, &resp->resfail.attr); }