diff options
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r-- | fs/nfsd/nfs4acl.c | 147 |
1 files changed, 39 insertions, 108 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 6c52658e9a26..2797051cd2b4 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -128,74 +128,58 @@ struct ace_container { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | static short ace2type(struct nfs4_ace *); | 130 | static short ace2type(struct nfs4_ace *); |
131 | static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); | 131 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, |
132 | int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | 132 | unsigned int); |
133 | void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | ||
133 | 134 | ||
134 | struct nfs4_acl * | 135 | struct nfs4_acl * |
135 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 136 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, |
136 | unsigned int flags) | 137 | unsigned int flags) |
137 | { | 138 | { |
138 | struct nfs4_acl *acl; | 139 | struct nfs4_acl *acl; |
139 | int error = -EINVAL; | 140 | int size = 0; |
140 | 141 | ||
141 | if ((pacl != NULL && | 142 | if (pacl) { |
142 | (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) || | 143 | if (posix_acl_valid(pacl) < 0) |
143 | (dpacl != NULL && | 144 | return ERR_PTR(-EINVAL); |
144 | (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0))) | 145 | size += 2*pacl->a_count; |
145 | goto out_err; | ||
146 | |||
147 | acl = nfs4_acl_new(); | ||
148 | if (acl == NULL) { | ||
149 | error = -ENOMEM; | ||
150 | goto out_err; | ||
151 | } | 146 | } |
152 | 147 | if (dpacl) { | |
153 | if (pacl != NULL) { | 148 | if (posix_acl_valid(dpacl) < 0) |
154 | error = _posix_to_nfsv4_one(pacl, acl, | 149 | return ERR_PTR(-EINVAL); |
155 | flags & ~NFS4_ACL_TYPE_DEFAULT); | 150 | size += 2*dpacl->a_count; |
156 | if (error < 0) | ||
157 | goto out_acl; | ||
158 | } | 151 | } |
159 | 152 | ||
160 | if (dpacl != NULL) { | 153 | /* Allocate for worst case: one (deny, allow) pair each: */ |
161 | error = _posix_to_nfsv4_one(dpacl, acl, | 154 | acl = nfs4_acl_new(size); |
162 | flags | NFS4_ACL_TYPE_DEFAULT); | 155 | if (acl == NULL) |
163 | if (error < 0) | 156 | return ERR_PTR(-ENOMEM); |
164 | goto out_acl; | ||
165 | } | ||
166 | 157 | ||
167 | return acl; | 158 | if (pacl) |
159 | _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT); | ||
168 | 160 | ||
169 | out_acl: | 161 | if (dpacl) |
170 | nfs4_acl_free(acl); | 162 | _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT); |
171 | out_err: | ||
172 | acl = ERR_PTR(error); | ||
173 | 163 | ||
174 | return acl; | 164 | return acl; |
175 | } | 165 | } |
176 | 166 | ||
177 | static int | 167 | static void |
178 | nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, | 168 | nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, |
179 | uid_t owner, unsigned int flags) | 169 | uid_t owner, unsigned int flags) |
180 | { | 170 | { |
181 | int error; | 171 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, |
182 | |||
183 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | ||
184 | eflag, mask, whotype, owner); | 172 | eflag, mask, whotype, owner); |
185 | if (error < 0) | 173 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
186 | return error; | ||
187 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | ||
188 | eflag, deny_mask(mask, flags), whotype, owner); | 174 | eflag, deny_mask(mask, flags), whotype, owner); |
189 | return error; | ||
190 | } | 175 | } |
191 | 176 | ||
192 | /* We assume the acl has been verified with posix_acl_valid. */ | 177 | /* We assume the acl has been verified with posix_acl_valid. */ |
193 | static int | 178 | static void |
194 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | 179 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, |
195 | unsigned int flags) | 180 | unsigned int flags) |
196 | { | 181 | { |
197 | struct posix_acl_entry *pa, *pe, *group_owner_entry; | 182 | struct posix_acl_entry *pa, *pe, *group_owner_entry; |
198 | int error = -EINVAL; | ||
199 | u32 mask, mask_mask; | 183 | u32 mask, mask_mask; |
200 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? | 184 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? |
201 | NFS4_INHERITANCE_FLAGS : 0); | 185 | NFS4_INHERITANCE_FLAGS : 0); |
@@ -211,23 +195,16 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
211 | pa = pacl->a_entries; | 195 | pa = pacl->a_entries; |
212 | BUG_ON(pa->e_tag != ACL_USER_OBJ); | 196 | BUG_ON(pa->e_tag != ACL_USER_OBJ); |
213 | mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); | 197 | mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); |
214 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags); | 198 | nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags); |
215 | if (error < 0) | ||
216 | goto out; | ||
217 | pa++; | 199 | pa++; |
218 | 200 | ||
219 | while (pa->e_tag == ACL_USER) { | 201 | while (pa->e_tag == ACL_USER) { |
220 | mask = mask_from_posix(pa->e_perm, flags); | 202 | mask = mask_from_posix(pa->e_perm, flags); |
221 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 203 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
222 | eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); | 204 | eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); |
223 | if (error < 0) | ||
224 | goto out; | ||
225 | 205 | ||
226 | 206 | nfs4_acl_add_pair(acl, eflag, mask, | |
227 | error = nfs4_acl_add_pair(acl, eflag, mask, | ||
228 | NFS4_ACL_WHO_NAMED, pa->e_id, flags); | 207 | NFS4_ACL_WHO_NAMED, pa->e_id, flags); |
229 | if (error < 0) | ||
230 | goto out; | ||
231 | pa++; | 208 | pa++; |
232 | } | 209 | } |
233 | 210 | ||
@@ -238,34 +215,25 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
238 | 215 | ||
239 | if (pacl->a_count > 3) { | 216 | if (pacl->a_count > 3) { |
240 | BUG_ON(pa->e_tag != ACL_GROUP_OBJ); | 217 | BUG_ON(pa->e_tag != ACL_GROUP_OBJ); |
241 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 218 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
242 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | 219 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, |
243 | NFS4_ACL_WHO_GROUP, 0); | 220 | NFS4_ACL_WHO_GROUP, 0); |
244 | if (error < 0) | ||
245 | goto out; | ||
246 | } | 221 | } |
247 | group_owner_entry = pa; | 222 | group_owner_entry = pa; |
248 | mask = mask_from_posix(pa->e_perm, flags); | 223 | mask = mask_from_posix(pa->e_perm, flags); |
249 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 224 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, |
250 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | 225 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, |
251 | NFS4_ACL_WHO_GROUP, 0); | 226 | NFS4_ACL_WHO_GROUP, 0); |
252 | if (error < 0) | ||
253 | goto out; | ||
254 | pa++; | 227 | pa++; |
255 | 228 | ||
256 | while (pa->e_tag == ACL_GROUP) { | 229 | while (pa->e_tag == ACL_GROUP) { |
257 | mask = mask_from_posix(pa->e_perm, flags); | 230 | mask = mask_from_posix(pa->e_perm, flags); |
258 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 231 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
259 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | 232 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, |
260 | NFS4_ACL_WHO_NAMED, pa->e_id); | 233 | NFS4_ACL_WHO_NAMED, pa->e_id); |
261 | if (error < 0) | 234 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, |
262 | goto out; | ||
263 | |||
264 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | ||
265 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | 235 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, |
266 | NFS4_ACL_WHO_NAMED, pa->e_id); | 236 | NFS4_ACL_WHO_NAMED, pa->e_id); |
267 | if (error < 0) | ||
268 | goto out; | ||
269 | pa++; | 237 | pa++; |
270 | } | 238 | } |
271 | 239 | ||
@@ -273,19 +241,15 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
273 | 241 | ||
274 | pa = group_owner_entry; | 242 | pa = group_owner_entry; |
275 | mask = mask_from_posix(pa->e_perm, flags); | 243 | mask = mask_from_posix(pa->e_perm, flags); |
276 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 244 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
277 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 245 | NFS4_ACE_IDENTIFIER_GROUP | eflag, |
278 | deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); | 246 | deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); |
279 | if (error < 0) | ||
280 | goto out; | ||
281 | pa++; | 247 | pa++; |
282 | while (pa->e_tag == ACL_GROUP) { | 248 | while (pa->e_tag == ACL_GROUP) { |
283 | mask = mask_from_posix(pa->e_perm, flags); | 249 | mask = mask_from_posix(pa->e_perm, flags); |
284 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 250 | nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, |
285 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 251 | NFS4_ACE_IDENTIFIER_GROUP | eflag, |
286 | deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); | 252 | deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); |
287 | if (error < 0) | ||
288 | goto out; | ||
289 | pa++; | 253 | pa++; |
290 | } | 254 | } |
291 | 255 | ||
@@ -293,10 +257,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
293 | pa++; | 257 | pa++; |
294 | BUG_ON(pa->e_tag != ACL_OTHER); | 258 | BUG_ON(pa->e_tag != ACL_OTHER); |
295 | mask = mask_from_posix(pa->e_perm, flags); | 259 | mask = mask_from_posix(pa->e_perm, flags); |
296 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); | 260 | nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); |
297 | |||
298 | out: | ||
299 | return error; | ||
300 | } | 261 | } |
301 | 262 | ||
302 | static void | 263 | static void |
@@ -640,7 +601,7 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, | |||
640 | if (ret) | 601 | if (ret) |
641 | goto out_estate; | 602 | goto out_estate; |
642 | ret = -EINVAL; | 603 | ret = -EINVAL; |
643 | list_for_each_entry(ace, &acl->ace_head, l_ace) { | 604 | for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { |
644 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && | 605 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && |
645 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) | 606 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) |
646 | goto out_dstate; | 607 | goto out_dstate; |
@@ -705,48 +666,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4); | |||
705 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); | 666 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); |
706 | 667 | ||
707 | struct nfs4_acl * | 668 | struct nfs4_acl * |
708 | nfs4_acl_new(void) | 669 | nfs4_acl_new(int n) |
709 | { | 670 | { |
710 | struct nfs4_acl *acl; | 671 | struct nfs4_acl *acl; |
711 | 672 | ||
712 | if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) | 673 | acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL); |
674 | if (acl == NULL) | ||
713 | return NULL; | 675 | return NULL; |
714 | |||
715 | acl->naces = 0; | 676 | acl->naces = 0; |
716 | INIT_LIST_HEAD(&acl->ace_head); | ||
717 | |||
718 | return acl; | 677 | return acl; |
719 | } | 678 | } |
720 | 679 | ||
721 | void | 680 | void |
722 | nfs4_acl_free(struct nfs4_acl *acl) | ||
723 | { | ||
724 | struct list_head *h; | ||
725 | struct nfs4_ace *ace; | ||
726 | |||
727 | if (!acl) | ||
728 | return; | ||
729 | |||
730 | while (!list_empty(&acl->ace_head)) { | ||
731 | h = acl->ace_head.next; | ||
732 | list_del(h); | ||
733 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
734 | kfree(ace); | ||
735 | } | ||
736 | |||
737 | kfree(acl); | ||
738 | |||
739 | return; | ||
740 | } | ||
741 | |||
742 | int | ||
743 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | 681 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, |
744 | int whotype, uid_t who) | 682 | int whotype, uid_t who) |
745 | { | 683 | { |
746 | struct nfs4_ace *ace; | 684 | struct nfs4_ace *ace = acl->aces + acl->naces; |
747 | |||
748 | if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) | ||
749 | return -ENOMEM; | ||
750 | 685 | ||
751 | ace->type = type; | 686 | ace->type = type; |
752 | ace->flag = flag; | 687 | ace->flag = flag; |
@@ -754,10 +689,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | |||
754 | ace->whotype = whotype; | 689 | ace->whotype = whotype; |
755 | ace->who = who; | 690 | ace->who = who; |
756 | 691 | ||
757 | list_add_tail(&ace->l_ace, &acl->ace_head); | ||
758 | acl->naces++; | 692 | acl->naces++; |
759 | |||
760 | return 0; | ||
761 | } | 693 | } |
762 | 694 | ||
763 | static struct { | 695 | static struct { |
@@ -811,7 +743,6 @@ nfs4_acl_write_who(int who, char *p) | |||
811 | } | 743 | } |
812 | 744 | ||
813 | EXPORT_SYMBOL(nfs4_acl_new); | 745 | EXPORT_SYMBOL(nfs4_acl_new); |
814 | EXPORT_SYMBOL(nfs4_acl_free); | ||
815 | EXPORT_SYMBOL(nfs4_acl_add_ace); | 746 | EXPORT_SYMBOL(nfs4_acl_add_ace); |
816 | EXPORT_SYMBOL(nfs4_acl_get_whotype); | 747 | EXPORT_SYMBOL(nfs4_acl_get_whotype); |
817 | EXPORT_SYMBOL(nfs4_acl_write_who); | 748 | EXPORT_SYMBOL(nfs4_acl_write_who); |