0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <linux/fs.h>
0038 #include <linux/slab.h>
0039 #include <linux/posix_acl.h>
0040
0041 #include "nfsfh.h"
0042 #include "nfsd.h"
0043 #include "acl.h"
0044 #include "vfs.h"
0045
0046 #define NFS4_ACL_TYPE_DEFAULT 0x01
0047 #define NFS4_ACL_DIR 0x02
0048 #define NFS4_ACL_OWNER 0x04
0049
0050
0051 #define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
0052 #define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
0053 #define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
0054 #define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
0055 #define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
0056
0057
0058 #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
0059 | NFS4_ACE_DIRECTORY_INHERIT_ACE)
0060
0061 #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \
0062 | NFS4_ACE_INHERIT_ONLY_ACE \
0063 | NFS4_ACE_IDENTIFIER_GROUP)
0064
0065 static u32
0066 mask_from_posix(unsigned short perm, unsigned int flags)
0067 {
0068 int mask = NFS4_ANYONE_MODE;
0069
0070 if (flags & NFS4_ACL_OWNER)
0071 mask |= NFS4_OWNER_MODE;
0072 if (perm & ACL_READ)
0073 mask |= NFS4_READ_MODE;
0074 if (perm & ACL_WRITE)
0075 mask |= NFS4_WRITE_MODE;
0076 if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
0077 mask |= NFS4_ACE_DELETE_CHILD;
0078 if (perm & ACL_EXECUTE)
0079 mask |= NFS4_EXECUTE_MODE;
0080 return mask;
0081 }
0082
0083 static u32
0084 deny_mask_from_posix(unsigned short perm, u32 flags)
0085 {
0086 u32 mask = 0;
0087
0088 if (perm & ACL_READ)
0089 mask |= NFS4_READ_MODE;
0090 if (perm & ACL_WRITE)
0091 mask |= NFS4_WRITE_MODE;
0092 if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
0093 mask |= NFS4_ACE_DELETE_CHILD;
0094 if (perm & ACL_EXECUTE)
0095 mask |= NFS4_EXECUTE_MODE;
0096 return mask;
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 static void
0109 low_mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
0110 {
0111 u32 write_mode = NFS4_WRITE_MODE;
0112
0113 if (flags & NFS4_ACL_DIR)
0114 write_mode |= NFS4_ACE_DELETE_CHILD;
0115 *mode = 0;
0116 if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
0117 *mode |= ACL_READ;
0118 if ((perm & write_mode) == write_mode)
0119 *mode |= ACL_WRITE;
0120 if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
0121 *mode |= ACL_EXECUTE;
0122 }
0123
0124 static short ace2type(struct nfs4_ace *);
0125 static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
0126 unsigned int);
0127
0128 int
0129 nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
0130 struct nfs4_acl **acl)
0131 {
0132 struct inode *inode = d_inode(dentry);
0133 int error = 0;
0134 struct posix_acl *pacl = NULL, *dpacl = NULL;
0135 unsigned int flags = 0;
0136 int size = 0;
0137
0138 pacl = get_acl(inode, ACL_TYPE_ACCESS);
0139 if (!pacl)
0140 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
0141
0142 if (IS_ERR(pacl))
0143 return PTR_ERR(pacl);
0144
0145
0146 size += 2 * pacl->a_count;
0147
0148 if (S_ISDIR(inode->i_mode)) {
0149 flags = NFS4_ACL_DIR;
0150 dpacl = get_acl(inode, ACL_TYPE_DEFAULT);
0151 if (IS_ERR(dpacl)) {
0152 error = PTR_ERR(dpacl);
0153 goto rel_pacl;
0154 }
0155
0156 if (dpacl)
0157 size += 2 * dpacl->a_count;
0158 }
0159
0160 *acl = kmalloc(nfs4_acl_bytes(size), GFP_KERNEL);
0161 if (*acl == NULL) {
0162 error = -ENOMEM;
0163 goto out;
0164 }
0165 (*acl)->naces = 0;
0166
0167 _posix_to_nfsv4_one(pacl, *acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
0168
0169 if (dpacl)
0170 _posix_to_nfsv4_one(dpacl, *acl, flags | NFS4_ACL_TYPE_DEFAULT);
0171
0172 out:
0173 posix_acl_release(dpacl);
0174 rel_pacl:
0175 posix_acl_release(pacl);
0176 return error;
0177 }
0178
0179 struct posix_acl_summary {
0180 unsigned short owner;
0181 unsigned short users;
0182 unsigned short group;
0183 unsigned short groups;
0184 unsigned short other;
0185 unsigned short mask;
0186 };
0187
0188 static void
0189 summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
0190 {
0191 struct posix_acl_entry *pa, *pe;
0192
0193
0194
0195
0196
0197
0198 memset(pas, 0, sizeof(*pas));
0199 pas->mask = 07;
0200
0201 pe = acl->a_entries + acl->a_count;
0202
0203 FOREACH_ACL_ENTRY(pa, acl, pe) {
0204 switch (pa->e_tag) {
0205 case ACL_USER_OBJ:
0206 pas->owner = pa->e_perm;
0207 break;
0208 case ACL_GROUP_OBJ:
0209 pas->group = pa->e_perm;
0210 break;
0211 case ACL_USER:
0212 pas->users |= pa->e_perm;
0213 break;
0214 case ACL_GROUP:
0215 pas->groups |= pa->e_perm;
0216 break;
0217 case ACL_OTHER:
0218 pas->other = pa->e_perm;
0219 break;
0220 case ACL_MASK:
0221 pas->mask = pa->e_perm;
0222 break;
0223 }
0224 }
0225
0226 pas->users &= pas->mask;
0227 pas->group &= pas->mask;
0228 pas->groups &= pas->mask;
0229 }
0230
0231
0232 static void
0233 _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
0234 unsigned int flags)
0235 {
0236 struct posix_acl_entry *pa, *group_owner_entry;
0237 struct nfs4_ace *ace;
0238 struct posix_acl_summary pas;
0239 unsigned short deny;
0240 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
0241 NFS4_INHERITANCE_FLAGS | NFS4_ACE_INHERIT_ONLY_ACE : 0);
0242
0243 BUG_ON(pacl->a_count < 3);
0244 summarize_posix_acl(pacl, &pas);
0245
0246 pa = pacl->a_entries;
0247 ace = acl->aces + acl->naces;
0248
0249
0250 deny = ~pas.owner;
0251
0252
0253
0254
0255 deny &= pas.users | pas.group | pas.groups | pas.other;
0256 if (deny) {
0257 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0258 ace->flag = eflag;
0259 ace->access_mask = deny_mask_from_posix(deny, flags);
0260 ace->whotype = NFS4_ACL_WHO_OWNER;
0261 ace++;
0262 acl->naces++;
0263 }
0264
0265 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0266 ace->flag = eflag;
0267 ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
0268 ace->whotype = NFS4_ACL_WHO_OWNER;
0269 ace++;
0270 acl->naces++;
0271 pa++;
0272
0273 while (pa->e_tag == ACL_USER) {
0274 deny = ~(pa->e_perm & pas.mask);
0275 deny &= pas.groups | pas.group | pas.other;
0276 if (deny) {
0277 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0278 ace->flag = eflag;
0279 ace->access_mask = deny_mask_from_posix(deny, flags);
0280 ace->whotype = NFS4_ACL_WHO_NAMED;
0281 ace->who_uid = pa->e_uid;
0282 ace++;
0283 acl->naces++;
0284 }
0285 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0286 ace->flag = eflag;
0287 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
0288 flags);
0289 ace->whotype = NFS4_ACL_WHO_NAMED;
0290 ace->who_uid = pa->e_uid;
0291 ace++;
0292 acl->naces++;
0293 pa++;
0294 }
0295
0296
0297
0298
0299
0300
0301 group_owner_entry = pa;
0302
0303 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0304 ace->flag = eflag;
0305 ace->access_mask = mask_from_posix(pas.group, flags);
0306 ace->whotype = NFS4_ACL_WHO_GROUP;
0307 ace++;
0308 acl->naces++;
0309 pa++;
0310
0311 while (pa->e_tag == ACL_GROUP) {
0312 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0313 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
0314 ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
0315 flags);
0316 ace->whotype = NFS4_ACL_WHO_NAMED;
0317 ace->who_gid = pa->e_gid;
0318 ace++;
0319 acl->naces++;
0320 pa++;
0321 }
0322
0323
0324
0325 pa = group_owner_entry;
0326
0327 deny = ~pas.group & pas.other;
0328 if (deny) {
0329 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0330 ace->flag = eflag;
0331 ace->access_mask = deny_mask_from_posix(deny, flags);
0332 ace->whotype = NFS4_ACL_WHO_GROUP;
0333 ace++;
0334 acl->naces++;
0335 }
0336 pa++;
0337
0338 while (pa->e_tag == ACL_GROUP) {
0339 deny = ~(pa->e_perm & pas.mask);
0340 deny &= pas.other;
0341 if (deny) {
0342 ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE;
0343 ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
0344 ace->access_mask = deny_mask_from_posix(deny, flags);
0345 ace->whotype = NFS4_ACL_WHO_NAMED;
0346 ace->who_gid = pa->e_gid;
0347 ace++;
0348 acl->naces++;
0349 }
0350 pa++;
0351 }
0352
0353 if (pa->e_tag == ACL_MASK)
0354 pa++;
0355 ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE;
0356 ace->flag = eflag;
0357 ace->access_mask = mask_from_posix(pa->e_perm, flags);
0358 ace->whotype = NFS4_ACL_WHO_EVERYONE;
0359 acl->naces++;
0360 }
0361
0362 static bool
0363 pace_gt(struct posix_acl_entry *pace1, struct posix_acl_entry *pace2)
0364 {
0365 if (pace1->e_tag != pace2->e_tag)
0366 return pace1->e_tag > pace2->e_tag;
0367 if (pace1->e_tag == ACL_USER)
0368 return uid_gt(pace1->e_uid, pace2->e_uid);
0369 if (pace1->e_tag == ACL_GROUP)
0370 return gid_gt(pace1->e_gid, pace2->e_gid);
0371 return false;
0372 }
0373
0374 static void
0375 sort_pacl_range(struct posix_acl *pacl, int start, int end) {
0376 int sorted = 0, i;
0377
0378
0379
0380 while (!sorted) {
0381 sorted = 1;
0382 for (i = start; i < end; i++) {
0383 if (pace_gt(&pacl->a_entries[i],
0384 &pacl->a_entries[i+1])) {
0385 sorted = 0;
0386 swap(pacl->a_entries[i],
0387 pacl->a_entries[i + 1]);
0388 }
0389 }
0390 }
0391 }
0392
0393 static void
0394 sort_pacl(struct posix_acl *pacl)
0395 {
0396
0397
0398 int i, j;
0399
0400
0401 if (!pacl || pacl->a_count <= 4)
0402 return;
0403
0404 i = 1;
0405 while (pacl->a_entries[i].e_tag == ACL_USER)
0406 i++;
0407 sort_pacl_range(pacl, 1, i-1);
0408
0409 BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
0410 j = ++i;
0411 while (pacl->a_entries[j].e_tag == ACL_GROUP)
0412 j++;
0413 sort_pacl_range(pacl, i, j-1);
0414 return;
0415 }
0416
0417
0418
0419
0420
0421 struct posix_ace_state {
0422 u32 allow;
0423 u32 deny;
0424 };
0425
0426 struct posix_user_ace_state {
0427 union {
0428 kuid_t uid;
0429 kgid_t gid;
0430 };
0431 struct posix_ace_state perms;
0432 };
0433
0434 struct posix_ace_state_array {
0435 int n;
0436 struct posix_user_ace_state aces[];
0437 };
0438
0439
0440
0441
0442
0443 struct posix_acl_state {
0444 int empty;
0445 struct posix_ace_state owner;
0446 struct posix_ace_state group;
0447 struct posix_ace_state other;
0448 struct posix_ace_state everyone;
0449 struct posix_ace_state mask;
0450 struct posix_ace_state_array *users;
0451 struct posix_ace_state_array *groups;
0452 };
0453
0454 static int
0455 init_state(struct posix_acl_state *state, int cnt)
0456 {
0457 int alloc;
0458
0459 memset(state, 0, sizeof(struct posix_acl_state));
0460 state->empty = 1;
0461
0462
0463
0464
0465
0466 alloc = sizeof(struct posix_ace_state_array)
0467 + cnt*sizeof(struct posix_user_ace_state);
0468 state->users = kzalloc(alloc, GFP_KERNEL);
0469 if (!state->users)
0470 return -ENOMEM;
0471 state->groups = kzalloc(alloc, GFP_KERNEL);
0472 if (!state->groups) {
0473 kfree(state->users);
0474 return -ENOMEM;
0475 }
0476 return 0;
0477 }
0478
0479 static void
0480 free_state(struct posix_acl_state *state) {
0481 kfree(state->users);
0482 kfree(state->groups);
0483 }
0484
0485 static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate)
0486 {
0487 state->mask.allow |= astate->allow;
0488 }
0489
0490 static struct posix_acl *
0491 posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
0492 {
0493 struct posix_acl_entry *pace;
0494 struct posix_acl *pacl;
0495 int nace;
0496 int i;
0497
0498
0499
0500
0501
0502
0503 if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT))
0504 return NULL;
0505
0506
0507
0508
0509
0510
0511 if (!state->users->n && !state->groups->n)
0512 nace = 3;
0513 else
0514 nace = 4 + state->users->n + state->groups->n;
0515 pacl = posix_acl_alloc(nace, GFP_KERNEL);
0516 if (!pacl)
0517 return ERR_PTR(-ENOMEM);
0518
0519 pace = pacl->a_entries;
0520 pace->e_tag = ACL_USER_OBJ;
0521 low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
0522
0523 for (i=0; i < state->users->n; i++) {
0524 pace++;
0525 pace->e_tag = ACL_USER;
0526 low_mode_from_nfs4(state->users->aces[i].perms.allow,
0527 &pace->e_perm, flags);
0528 pace->e_uid = state->users->aces[i].uid;
0529 add_to_mask(state, &state->users->aces[i].perms);
0530 }
0531
0532 pace++;
0533 pace->e_tag = ACL_GROUP_OBJ;
0534 low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
0535 add_to_mask(state, &state->group);
0536
0537 for (i=0; i < state->groups->n; i++) {
0538 pace++;
0539 pace->e_tag = ACL_GROUP;
0540 low_mode_from_nfs4(state->groups->aces[i].perms.allow,
0541 &pace->e_perm, flags);
0542 pace->e_gid = state->groups->aces[i].gid;
0543 add_to_mask(state, &state->groups->aces[i].perms);
0544 }
0545
0546 if (state->users->n || state->groups->n) {
0547 pace++;
0548 pace->e_tag = ACL_MASK;
0549 low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
0550 }
0551
0552 pace++;
0553 pace->e_tag = ACL_OTHER;
0554 low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
0555
0556 return pacl;
0557 }
0558
0559 static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
0560 {
0561
0562 astate->allow |= mask & ~astate->deny;
0563 }
0564
0565 static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
0566 {
0567
0568 astate->deny |= mask & ~astate->allow;
0569 }
0570
0571 static int find_uid(struct posix_acl_state *state, kuid_t uid)
0572 {
0573 struct posix_ace_state_array *a = state->users;
0574 int i;
0575
0576 for (i = 0; i < a->n; i++)
0577 if (uid_eq(a->aces[i].uid, uid))
0578 return i;
0579
0580 a->n++;
0581 a->aces[i].uid = uid;
0582 a->aces[i].perms.allow = state->everyone.allow;
0583 a->aces[i].perms.deny = state->everyone.deny;
0584
0585 return i;
0586 }
0587
0588 static int find_gid(struct posix_acl_state *state, kgid_t gid)
0589 {
0590 struct posix_ace_state_array *a = state->groups;
0591 int i;
0592
0593 for (i = 0; i < a->n; i++)
0594 if (gid_eq(a->aces[i].gid, gid))
0595 return i;
0596
0597 a->n++;
0598 a->aces[i].gid = gid;
0599 a->aces[i].perms.allow = state->everyone.allow;
0600 a->aces[i].perms.deny = state->everyone.deny;
0601
0602 return i;
0603 }
0604
0605 static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
0606 {
0607 int i;
0608
0609 for (i=0; i < a->n; i++)
0610 deny_bits(&a->aces[i].perms, mask);
0611 }
0612
0613 static void allow_bits_array(struct posix_ace_state_array *a, u32 mask)
0614 {
0615 int i;
0616
0617 for (i=0; i < a->n; i++)
0618 allow_bits(&a->aces[i].perms, mask);
0619 }
0620
0621 static void process_one_v4_ace(struct posix_acl_state *state,
0622 struct nfs4_ace *ace)
0623 {
0624 u32 mask = ace->access_mask;
0625 int i;
0626
0627 state->empty = 0;
0628
0629 switch (ace2type(ace)) {
0630 case ACL_USER_OBJ:
0631 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0632 allow_bits(&state->owner, mask);
0633 } else {
0634 deny_bits(&state->owner, mask);
0635 }
0636 break;
0637 case ACL_USER:
0638 i = find_uid(state, ace->who_uid);
0639 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0640 allow_bits(&state->users->aces[i].perms, mask);
0641 } else {
0642 deny_bits(&state->users->aces[i].perms, mask);
0643 mask = state->users->aces[i].perms.deny;
0644 deny_bits(&state->owner, mask);
0645 }
0646 break;
0647 case ACL_GROUP_OBJ:
0648 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0649 allow_bits(&state->group, mask);
0650 } else {
0651 deny_bits(&state->group, mask);
0652 mask = state->group.deny;
0653 deny_bits(&state->owner, mask);
0654 deny_bits(&state->everyone, mask);
0655 deny_bits_array(state->users, mask);
0656 deny_bits_array(state->groups, mask);
0657 }
0658 break;
0659 case ACL_GROUP:
0660 i = find_gid(state, ace->who_gid);
0661 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0662 allow_bits(&state->groups->aces[i].perms, mask);
0663 } else {
0664 deny_bits(&state->groups->aces[i].perms, mask);
0665 mask = state->groups->aces[i].perms.deny;
0666 deny_bits(&state->owner, mask);
0667 deny_bits(&state->group, mask);
0668 deny_bits(&state->everyone, mask);
0669 deny_bits_array(state->users, mask);
0670 deny_bits_array(state->groups, mask);
0671 }
0672 break;
0673 case ACL_OTHER:
0674 if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
0675 allow_bits(&state->owner, mask);
0676 allow_bits(&state->group, mask);
0677 allow_bits(&state->other, mask);
0678 allow_bits(&state->everyone, mask);
0679 allow_bits_array(state->users, mask);
0680 allow_bits_array(state->groups, mask);
0681 } else {
0682 deny_bits(&state->owner, mask);
0683 deny_bits(&state->group, mask);
0684 deny_bits(&state->other, mask);
0685 deny_bits(&state->everyone, mask);
0686 deny_bits_array(state->users, mask);
0687 deny_bits_array(state->groups, mask);
0688 }
0689 }
0690 }
0691
0692 static int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl,
0693 struct posix_acl **pacl, struct posix_acl **dpacl,
0694 unsigned int flags)
0695 {
0696 struct posix_acl_state effective_acl_state, default_acl_state;
0697 struct nfs4_ace *ace;
0698 int ret;
0699
0700 ret = init_state(&effective_acl_state, acl->naces);
0701 if (ret)
0702 return ret;
0703 ret = init_state(&default_acl_state, acl->naces);
0704 if (ret)
0705 goto out_estate;
0706 ret = -EINVAL;
0707 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
0708 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
0709 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
0710 goto out_dstate;
0711 if (ace->flag & ~NFS4_SUPPORTED_FLAGS)
0712 goto out_dstate;
0713 if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) {
0714 process_one_v4_ace(&effective_acl_state, ace);
0715 continue;
0716 }
0717 if (!(flags & NFS4_ACL_DIR))
0718 goto out_dstate;
0719
0720
0721
0722
0723
0724 process_one_v4_ace(&default_acl_state, ace);
0725
0726 if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE))
0727 process_one_v4_ace(&effective_acl_state, ace);
0728 }
0729 *pacl = posix_state_to_acl(&effective_acl_state, flags);
0730 if (IS_ERR(*pacl)) {
0731 ret = PTR_ERR(*pacl);
0732 *pacl = NULL;
0733 goto out_dstate;
0734 }
0735 *dpacl = posix_state_to_acl(&default_acl_state,
0736 flags | NFS4_ACL_TYPE_DEFAULT);
0737 if (IS_ERR(*dpacl)) {
0738 ret = PTR_ERR(*dpacl);
0739 *dpacl = NULL;
0740 posix_acl_release(*pacl);
0741 *pacl = NULL;
0742 goto out_dstate;
0743 }
0744 sort_pacl(*pacl);
0745 sort_pacl(*dpacl);
0746 ret = 0;
0747 out_dstate:
0748 free_state(&default_acl_state);
0749 out_estate:
0750 free_state(&effective_acl_state);
0751 return ret;
0752 }
0753
0754 __be32 nfsd4_acl_to_attr(enum nfs_ftype4 type, struct nfs4_acl *acl,
0755 struct nfsd_attrs *attr)
0756 {
0757 int host_error;
0758 unsigned int flags = 0;
0759
0760 if (!acl)
0761 return nfs_ok;
0762
0763 if (type == NF4DIR)
0764 flags = NFS4_ACL_DIR;
0765
0766 host_error = nfs4_acl_nfsv4_to_posix(acl, &attr->na_pacl,
0767 &attr->na_dpacl, flags);
0768 if (host_error == -EINVAL)
0769 return nfserr_attrnotsupp;
0770 else
0771 return nfserrno(host_error);
0772 }
0773
0774 static short
0775 ace2type(struct nfs4_ace *ace)
0776 {
0777 switch (ace->whotype) {
0778 case NFS4_ACL_WHO_NAMED:
0779 return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
0780 ACL_GROUP : ACL_USER);
0781 case NFS4_ACL_WHO_OWNER:
0782 return ACL_USER_OBJ;
0783 case NFS4_ACL_WHO_GROUP:
0784 return ACL_GROUP_OBJ;
0785 case NFS4_ACL_WHO_EVERYONE:
0786 return ACL_OTHER;
0787 }
0788 BUG();
0789 return -1;
0790 }
0791
0792
0793
0794
0795
0796 int nfs4_acl_bytes(int entries)
0797 {
0798 return sizeof(struct nfs4_acl) + entries * sizeof(struct nfs4_ace);
0799 }
0800
0801 static struct {
0802 char *string;
0803 int stringlen;
0804 int type;
0805 } s2t_map[] = {
0806 {
0807 .string = "OWNER@",
0808 .stringlen = sizeof("OWNER@") - 1,
0809 .type = NFS4_ACL_WHO_OWNER,
0810 },
0811 {
0812 .string = "GROUP@",
0813 .stringlen = sizeof("GROUP@") - 1,
0814 .type = NFS4_ACL_WHO_GROUP,
0815 },
0816 {
0817 .string = "EVERYONE@",
0818 .stringlen = sizeof("EVERYONE@") - 1,
0819 .type = NFS4_ACL_WHO_EVERYONE,
0820 },
0821 };
0822
0823 int
0824 nfs4_acl_get_whotype(char *p, u32 len)
0825 {
0826 int i;
0827
0828 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
0829 if (s2t_map[i].stringlen == len &&
0830 0 == memcmp(s2t_map[i].string, p, len))
0831 return s2t_map[i].type;
0832 }
0833 return NFS4_ACL_WHO_NAMED;
0834 }
0835
0836 __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who)
0837 {
0838 __be32 *p;
0839 int i;
0840
0841 for (i = 0; i < ARRAY_SIZE(s2t_map); i++) {
0842 if (s2t_map[i].type != who)
0843 continue;
0844 p = xdr_reserve_space(xdr, s2t_map[i].stringlen + 4);
0845 if (!p)
0846 return nfserr_resource;
0847 p = xdr_encode_opaque(p, s2t_map[i].string,
0848 s2t_map[i].stringlen);
0849 return 0;
0850 }
0851 WARN_ON_ONCE(1);
0852 return nfserr_serverfault;
0853 }