/* * Retrieve NFSv4 ACL, skipping access checks. Must be used in UFS code * instead of VOP_GETACL() when we don't want to be restricted by the user * not having ACL_READ_ACL permission, e.g. when calculating inherited ACL * or in ufs_vnops.c:ufs_accessx(). */ int ufs_getacl_nfs4_internal(struct vnode *vp, struct acl *aclp, struct thread *td) { int error, len; struct inode *ip = VTOI(vp); len = sizeof(*aclp); bzero(aclp, len); error = vn_extattr_get(vp, IO_NODELOCKED, NFS4_ACL_EXTATTR_NAMESPACE, NFS4_ACL_EXTATTR_NAME, &len, (char *) aclp, td); aclp->acl_maxcnt = ACL_MAX_ENTRIES; if (error == ENOATTR) { /* * Legitimately no ACL set on object, purely * emulate it through the inode. */ acl_nfs4_sync_acl_from_mode(aclp, ip->i_mode, ip->i_uid); return (0); } if (error) return (error); if (len != sizeof(*aclp)) { /* * A short (or long) read, meaning that for * some reason the ACL is corrupted. Return * EPERM since the object DAC protections * are unsafe. */ printf("ufs_getacl_nfs4(): Loaded invalid ACL (" "%d bytes), inumber %ju on %s\n", len, (uintmax_t)ip->i_number, ip->i_fs->fs_fsmnt); return (EPERM); } error = acl_nfs4_check(aclp, vp->v_type == VDIR); if (error) { printf("ufs_getacl_nfs4(): Loaded invalid ACL " "(failed acl_nfs4_check), inumber %ju on %s\n", (uintmax_t)ip->i_number, ip->i_fs->fs_fsmnt); return (EPERM); } return (0); }
static acl_t _nfs4_acl_strip_np(const acl_t aclp, int canonical_six) { acl_t newacl; mode_t mode = 0; newacl = acl_init(ACL_MAX_ENTRIES); if (newacl == NULL) { errno = ENOMEM; return (NULL); } _acl_brand_as(newacl, ACL_BRAND_NFS4); acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl)); if (canonical_six) acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1); else acl_nfs4_trivial_from_mode(&(newacl->ats_acl), mode); return (newacl); }