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