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