xref: /freebsd/sys/cddl/compat/opensolaris/kern/opensolaris_acl.c (revision e32fecd0c2c3ee37c47ee100f169e7eb0282a873)
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