opensolaris_acl.c revision 290893
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: stable/10/sys/cddl/compat/opensolaris/kern/opensolaris_acl.c 290893 2015-11-15 23:54:34Z ngie $");
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
38struct zfs2bsd {
39	uint32_t	zb_zfs;
40	int		zb_bsd;
41};
42
43struct 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
59struct 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_INHERITED_ACE,
68			    ACL_ENTRY_INHERITED},
69			{ACE_SUCCESSFUL_ACCESS_ACE_FLAG,
70			    ACL_ENTRY_SUCCESSFUL_ACCESS},
71			{ACE_FAILED_ACCESS_ACE_FLAG,
72			    ACL_ENTRY_FAILED_ACCESS},
73			{0, 0}};
74
75static int
76_bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table)
77{
78	const struct zfs2bsd *tmp;
79	int bsd = 0;
80
81	for (tmp = table; tmp->zb_zfs != 0; tmp++) {
82		if (zfs & tmp->zb_zfs)
83			bsd |= tmp->zb_bsd;
84	}
85
86	return (bsd);
87}
88
89static uint32_t
90_zfs_from_bsd(int bsd, const struct zfs2bsd *table)
91{
92	const struct zfs2bsd *tmp;
93	uint32_t zfs = 0;
94
95	for (tmp = table; tmp->zb_bsd != 0; tmp++) {
96		if (bsd & tmp->zb_bsd)
97			zfs |= tmp->zb_zfs;
98	}
99
100	return (zfs);
101}
102
103int
104acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries)
105{
106	int i;
107	struct acl_entry *entry;
108	const ace_t *ace;
109
110	if (nentries < 1) {
111		printf("acl_from_aces: empty ZFS ACL; returning EINVAL.\n");
112		return (EINVAL);
113	}
114
115	if (nentries > ACL_MAX_ENTRIES) {
116		/*
117		 * I believe it may happen only when moving a pool
118		 * from SunOS to FreeBSD.
119		 */
120		printf("acl_from_aces: ZFS ACL too big to fit "
121		    "into 'struct acl'; returning EINVAL.\n");
122		return (EINVAL);
123	}
124
125	bzero(aclp, sizeof(*aclp));
126	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
127	aclp->acl_cnt = nentries;
128
129	for (i = 0; i < nentries; i++) {
130		entry = &(aclp->acl_entry[i]);
131		ace = &(aces[i]);
132
133		if (ace->a_flags & ACE_OWNER)
134			entry->ae_tag = ACL_USER_OBJ;
135		else if (ace->a_flags & ACE_GROUP)
136			entry->ae_tag = ACL_GROUP_OBJ;
137		else if (ace->a_flags & ACE_EVERYONE)
138			entry->ae_tag = ACL_EVERYONE;
139		else if (ace->a_flags & ACE_IDENTIFIER_GROUP)
140			entry->ae_tag = ACL_GROUP;
141		else
142			entry->ae_tag = ACL_USER;
143
144		if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP)
145			entry->ae_id = ace->a_who;
146		else
147			entry->ae_id = ACL_UNDEFINED_ID;
148
149		entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms);
150		entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags);
151
152		switch (ace->a_type) {
153		case ACE_ACCESS_ALLOWED_ACE_TYPE:
154			entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW;
155			break;
156		case ACE_ACCESS_DENIED_ACE_TYPE:
157			entry->ae_entry_type = ACL_ENTRY_TYPE_DENY;
158			break;
159		case ACE_SYSTEM_AUDIT_ACE_TYPE:
160			entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT;
161			break;
162		case ACE_SYSTEM_ALARM_ACE_TYPE:
163			entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM;
164			break;
165		default:
166			panic("acl_from_aces: a_type is 0x%x", ace->a_type);
167		}
168	}
169
170	return (0);
171}
172
173void
174aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp)
175{
176	int i;
177	const struct acl_entry *entry;
178	ace_t *ace;
179
180	bzero(aces, sizeof(*aces) * aclp->acl_cnt);
181
182	*nentries = aclp->acl_cnt;
183
184	for (i = 0; i < aclp->acl_cnt; i++) {
185		entry = &(aclp->acl_entry[i]);
186		ace = &(aces[i]);
187
188		ace->a_who = entry->ae_id;
189
190		if (entry->ae_tag == ACL_USER_OBJ)
191			ace->a_flags = ACE_OWNER;
192		else if (entry->ae_tag == ACL_GROUP_OBJ)
193			ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP);
194		else if (entry->ae_tag == ACL_GROUP)
195			ace->a_flags = ACE_IDENTIFIER_GROUP;
196		else if (entry->ae_tag == ACL_EVERYONE)
197			ace->a_flags = ACE_EVERYONE;
198		else /* ACL_USER */
199			ace->a_flags = 0;
200
201		ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms);
202		ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags);
203
204		switch (entry->ae_entry_type) {
205		case ACL_ENTRY_TYPE_ALLOW:
206			ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
207			break;
208		case ACL_ENTRY_TYPE_DENY:
209			ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
210			break;
211		case ACL_ENTRY_TYPE_ALARM:
212			ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
213			break;
214		case ACL_ENTRY_TYPE_AUDIT:
215			ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
216			break;
217		default:
218			panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type);
219		}
220	}
221}
222