]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/cddl/compat/opensolaris/kern/opensolaris_acl.c
MFC r289195:
[FreeBSD/stable/10.git] / sys / cddl / compat / opensolaris / kern / opensolaris_acl.c
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_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
75 static 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
89 static 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
103 int
104 acl_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
173 void
174 aces_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 }