1 /*- 2 * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/types.h> 32 #include <sys/malloc.h> 33 #include <sys/errno.h> 34 #include <sys/zfs_acl.h> 35 #include <sys/acl.h> 36 37 struct zfs2bsd { 38 uint32_t zb_zfs; 39 int zb_bsd; 40 }; 41 42 struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA}, 43 {ACE_WRITE_DATA, ACL_WRITE_DATA}, 44 {ACE_EXECUTE, ACL_EXECUTE}, 45 {ACE_APPEND_DATA, ACL_APPEND_DATA}, 46 {ACE_DELETE_CHILD, ACL_DELETE_CHILD}, 47 {ACE_DELETE, ACL_DELETE}, 48 {ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 49 {ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 50 {ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 51 {ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 52 {ACE_READ_ACL, ACL_READ_ACL}, 53 {ACE_WRITE_ACL, ACL_WRITE_ACL}, 54 {ACE_WRITE_OWNER, ACL_WRITE_OWNER}, 55 {ACE_SYNCHRONIZE, ACL_SYNCHRONIZE}, 56 {0, 0}}; 57 58 struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE, 59 ACL_ENTRY_FILE_INHERIT}, 60 {ACE_DIRECTORY_INHERIT_ACE, 61 ACL_ENTRY_DIRECTORY_INHERIT}, 62 {ACE_NO_PROPAGATE_INHERIT_ACE, 63 ACL_ENTRY_NO_PROPAGATE_INHERIT}, 64 {ACE_INHERIT_ONLY_ACE, 65 ACL_ENTRY_INHERIT_ONLY}, 66 {ACE_INHERITED_ACE, 67 ACL_ENTRY_INHERITED}, 68 {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, 69 ACL_ENTRY_SUCCESSFUL_ACCESS}, 70 {ACE_FAILED_ACCESS_ACE_FLAG, 71 ACL_ENTRY_FAILED_ACCESS}, 72 {0, 0}}; 73 74 static int 75 _bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) 76 { 77 const struct zfs2bsd *tmp; 78 int bsd = 0; 79 80 for (tmp = table; tmp->zb_zfs != 0; tmp++) { 81 if (zfs & tmp->zb_zfs) 82 bsd |= tmp->zb_bsd; 83 } 84 85 return (bsd); 86 } 87 88 static uint32_t 89 _zfs_from_bsd(int bsd, const struct zfs2bsd *table) 90 { 91 const struct zfs2bsd *tmp; 92 uint32_t zfs = 0; 93 94 for (tmp = table; tmp->zb_bsd != 0; tmp++) { 95 if (bsd & tmp->zb_bsd) 96 zfs |= tmp->zb_zfs; 97 } 98 99 return (zfs); 100 } 101 102 int 103 acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) 104 { 105 int i; 106 struct acl_entry *entry; 107 const ace_t *ace; 108 109 if (nentries < 1) { 110 printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n"); 111 return (EINVAL); 112 } 113 114 if (nentries > ACL_MAX_ENTRIES) { 115 /* 116 * I believe it may happen only when moving a pool 117 * from SunOS to FreeBSD. 118 */ 119 printf("acl_from_aces: ZFS ACL too big to fit " 120 "into 'struct acl'; returning EINVAL.\n"); 121 return (EINVAL); 122 } 123 124 bzero(aclp, sizeof(*aclp)); 125 aclp->acl_maxcnt = ACL_MAX_ENTRIES; 126 aclp->acl_cnt = nentries; 127 128 for (i = 0; i < nentries; i++) { 129 entry = &(aclp->acl_entry[i]); 130 ace = &(aces[i]); 131 132 if (ace->a_flags & ACE_OWNER) 133 entry->ae_tag = ACL_USER_OBJ; 134 else if (ace->a_flags & ACE_GROUP) 135 entry->ae_tag = ACL_GROUP_OBJ; 136 else if (ace->a_flags & ACE_EVERYONE) 137 entry->ae_tag = ACL_EVERYONE; 138 else if (ace->a_flags & ACE_IDENTIFIER_GROUP) 139 entry->ae_tag = ACL_GROUP; 140 else 141 entry->ae_tag = ACL_USER; 142 143 if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) 144 entry->ae_id = ace->a_who; 145 else 146 entry->ae_id = ACL_UNDEFINED_ID; 147 148 entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); 149 entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); 150 151 switch (ace->a_type) { 152 case ACE_ACCESS_ALLOWED_ACE_TYPE: 153 entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; 154 break; 155 case ACE_ACCESS_DENIED_ACE_TYPE: 156 entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; 157 break; 158 case ACE_SYSTEM_AUDIT_ACE_TYPE: 159 entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; 160 break; 161 case ACE_SYSTEM_ALARM_ACE_TYPE: 162 entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; 163 break; 164 default: 165 panic("acl_from_aces: a_type is 0x%x", ace->a_type); 166 } 167 } 168 169 return (0); 170 } 171 172 void 173 aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) 174 { 175 int i; 176 const struct acl_entry *entry; 177 ace_t *ace; 178 179 bzero(aces, sizeof(*aces) * aclp->acl_cnt); 180 181 *nentries = aclp->acl_cnt; 182 183 for (i = 0; i < aclp->acl_cnt; i++) { 184 entry = &(aclp->acl_entry[i]); 185 ace = &(aces[i]); 186 187 ace->a_who = entry->ae_id; 188 189 if (entry->ae_tag == ACL_USER_OBJ) 190 ace->a_flags = ACE_OWNER; 191 else if (entry->ae_tag == ACL_GROUP_OBJ) 192 ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); 193 else if (entry->ae_tag == ACL_GROUP) 194 ace->a_flags = ACE_IDENTIFIER_GROUP; 195 else if (entry->ae_tag == ACL_EVERYONE) 196 ace->a_flags = ACE_EVERYONE; 197 else /* ACL_USER */ 198 ace->a_flags = 0; 199 200 ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); 201 ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); 202 203 switch (entry->ae_entry_type) { 204 case ACL_ENTRY_TYPE_ALLOW: 205 ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 206 break; 207 case ACL_ENTRY_TYPE_DENY: 208 ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; 209 break; 210 case ACL_ENTRY_TYPE_ALARM: 211 ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; 212 break; 213 case ACL_ENTRY_TYPE_AUDIT: 214 ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; 215 break; 216 default: 217 panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type); 218 } 219 } 220 } 221