1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include "xfs.h"
34
35#include "xfs_inum.h"
36#include "xfs_dir.h"
37#include "xfs_dir2.h"
38#include "xfs_alloc_btree.h"
39#include "xfs_bmap_btree.h"
40#include "xfs_ialloc_btree.h"
41#include "xfs_btree.h"
42#include "xfs_attr_sf.h"
43#include "xfs_dir_sf.h"
44#include "xfs_dir2_sf.h"
45#include "xfs_dinode.h"
46#include "xfs_inode.h"
47#include "xfs_acl.h"
48#include "xfs_mac.h"
49#include "xfs_attr.h"
50
51#include <linux/posix_acl_xattr.h>
52
53STATIC int xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *);
54STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *);
55STATIC void xfs_acl_get_endian(xfs_acl_t *);
56STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
57STATIC int xfs_acl_invalid(xfs_acl_t *);
58STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *);
59STATIC void xfs_acl_get_attr(vnode_t *, xfs_acl_t *, int, int, int *);
60STATIC void xfs_acl_set_attr(vnode_t *, xfs_acl_t *, int, int *);
61STATIC int xfs_acl_allow_set(vnode_t *, int);
62
63kmem_zone_t *xfs_acl_zone;
64
65
66
67
68
69int
70xfs_acl_vhasacl_access(
71 vnode_t *vp)
72{
73 int error;
74
75 xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error);
76 return (error == 0);
77}
78
79
80
81
82int
83xfs_acl_vhasacl_default(
84 vnode_t *vp)
85{
86 int error;
87
88 if (vp->v_type != VDIR)
89 return 0;
90 xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
91 return (error == 0);
92}
93
94
95
96
97STATIC int
98posix_acl_xattr_to_xfs(
99 posix_acl_xattr_header *src,
100 size_t size,
101 xfs_acl_t *dest)
102{
103 posix_acl_xattr_entry *src_entry;
104 xfs_acl_entry_t *dest_entry;
105 int n;
106
107 if (!src || !dest)
108 return EINVAL;
109
110 if (size < sizeof(posix_acl_xattr_header))
111 return EINVAL;
112
113 if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
114 return EOPNOTSUPP;
115
116 memset(dest, 0, sizeof(xfs_acl_t));
117 dest->acl_cnt = posix_acl_xattr_count(size);
118 if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES)
119 return EINVAL;
120
121
122
123
124
125 if (!dest->acl_cnt)
126 return 0;
127
128 src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src));
129 dest_entry = &dest->acl_entry[0];
130
131 for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) {
132 dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm);
133 if (_ACL_PERM_INVALID(dest_entry->ae_perm))
134 return EINVAL;
135 dest_entry->ae_tag = le16_to_cpu(src_entry->e_tag);
136 switch(dest_entry->ae_tag) {
137 case ACL_USER:
138 case ACL_GROUP:
139 dest_entry->ae_id = le32_to_cpu(src_entry->e_id);
140 break;
141 case ACL_USER_OBJ:
142 case ACL_GROUP_OBJ:
143 case ACL_MASK:
144 case ACL_OTHER:
145 dest_entry->ae_id = ACL_UNDEFINED_ID;
146 break;
147 default:
148 return EINVAL;
149 }
150 }
151 if (xfs_acl_invalid(dest))
152 return EINVAL;
153
154 return 0;
155}
156
157
158
159
160
161STATIC int
162xfs_acl_entry_compare(
163 const void *va,
164 const void *vb)
165{
166 xfs_acl_entry_t *a = (xfs_acl_entry_t *)va,
167 *b = (xfs_acl_entry_t *)vb;
168
169 if (a->ae_tag == b->ae_tag)
170 return (a->ae_id - b->ae_id);
171 return (a->ae_tag - b->ae_tag);
172}
173
174
175
176
177STATIC int
178posix_acl_xfs_to_xattr(
179 xfs_acl_t *src,
180 posix_acl_xattr_header *dest,
181 size_t size)
182{
183 int n;
184 size_t new_size = posix_acl_xattr_size(src->acl_cnt);
185 posix_acl_xattr_entry *dest_entry;
186 xfs_acl_entry_t *src_entry;
187
188 if (size < new_size)
189 return -ERANGE;
190
191
192 qsort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
193 xfs_acl_entry_compare);
194
195 dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
196 dest_entry = &dest->a_entries[0];
197 src_entry = &src->acl_entry[0];
198 for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
199 dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
200 if (_ACL_PERM_INVALID(src_entry->ae_perm))
201 return -EINVAL;
202 dest_entry->e_tag = cpu_to_le16(src_entry->ae_tag);
203 switch (src_entry->ae_tag) {
204 case ACL_USER:
205 case ACL_GROUP:
206 dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
207 break;
208 case ACL_USER_OBJ:
209 case ACL_GROUP_OBJ:
210 case ACL_MASK:
211 case ACL_OTHER:
212 dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
213 break;
214 default:
215 return -EINVAL;
216 }
217 }
218 return new_size;
219}
220
221int
222xfs_acl_vget(
223 vnode_t *vp,
224 void *acl,
225 size_t size,
226 int kind)
227{
228 int error;
229 xfs_acl_t *xfs_acl = NULL;
230 posix_acl_xattr_header *ext_acl = acl;
231 int flags = 0;
232
233 VN_HOLD(vp);
234 if(size) {
235 if (!(_ACL_ALLOC(xfs_acl))) {
236 error = ENOMEM;
237 goto out;
238 }
239 memset(xfs_acl, 0, sizeof(xfs_acl_t));
240 } else
241 flags = ATTR_KERNOVAL;
242
243 xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
244 if (error)
245 goto out;
246
247 if (!size) {
248 error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
249 } else {
250 if (xfs_acl_invalid(xfs_acl)) {
251 error = EINVAL;
252 goto out;
253 }
254 if (kind == _ACL_TYPE_ACCESS) {
255 vattr_t va;
256
257 va.va_mask = XFS_AT_MODE;
258 VOP_GETATTR(vp, &va, 0, sys_cred, error);
259 if (error)
260 goto out;
261 xfs_acl_sync_mode(va.va_mode, xfs_acl);
262 }
263 error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
264 }
265out:
266 VN_RELE(vp);
267 if(xfs_acl)
268 _ACL_FREE(xfs_acl);
269 return -error;
270}
271
272int
273xfs_acl_vremove(
274 vnode_t *vp,
275 int kind)
276{
277 int error;
278
279 VN_HOLD(vp);
280 error = xfs_acl_allow_set(vp, kind);
281 if (!error) {
282 VOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT?
283 SGI_ACL_DEFAULT: SGI_ACL_FILE,
284 ATTR_ROOT, sys_cred, error);
285 if (error == ENOATTR)
286 error = 0;
287 }
288 VN_RELE(vp);
289 return -error;
290}
291
292int
293xfs_acl_vset(
294 vnode_t *vp,
295 void *acl,
296 size_t size,
297 int kind)
298{
299 posix_acl_xattr_header *ext_acl = acl;
300 xfs_acl_t *xfs_acl;
301 int error;
302 int basicperms = 0;
303
304 if (!acl)
305 return -EINVAL;
306
307 if (!(_ACL_ALLOC(xfs_acl)))
308 return -ENOMEM;
309
310 error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl);
311 if (error) {
312 _ACL_FREE(xfs_acl);
313 return -error;
314 }
315 if (!xfs_acl->acl_cnt) {
316 _ACL_FREE(xfs_acl);
317 return 0;
318 }
319
320 VN_HOLD(vp);
321 error = xfs_acl_allow_set(vp, kind);
322 if (error)
323 goto out;
324
325
326 if (kind == _ACL_TYPE_ACCESS)
327 xfs_acl_setmode(vp, xfs_acl, &basicperms);
328
329
330
331
332
333
334
335 if (!basicperms) {
336 xfs_acl_set_attr(vp, xfs_acl, kind, &error);
337 } else {
338 xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
339 }
340
341out:
342 VN_RELE(vp);
343 _ACL_FREE(xfs_acl);
344 return -error;
345}
346
347int
348xfs_acl_iaccess(
349 xfs_inode_t *ip,
350 mode_t mode,
351 cred_t *cr)
352{
353 xfs_acl_t *acl;
354 int rval;
355
356 if (!(_ACL_ALLOC(acl)))
357 return -1;
358
359
360 rval = sizeof(xfs_acl_t);
361 if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
362 (char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
363 _ACL_FREE(acl);
364 return -1;
365 }
366 xfs_acl_get_endian(acl);
367
368
369 if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) {
370 _ACL_FREE(acl);
371 return -1;
372 }
373
374
375 xfs_acl_sync_mode(ip->i_d.di_mode, acl);
376
377 rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);
378 _ACL_FREE(acl);
379 return rval;
380}
381
382STATIC int
383xfs_acl_allow_set(
384 vnode_t *vp,
385 int kind)
386{
387 vattr_t va;
388 int error;
389
390 if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
391 return EPERM;
392 if (kind == _ACL_TYPE_DEFAULT && vp->v_type != VDIR)
393 return ENOTDIR;
394 if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
395 return EROFS;
396 va.va_mask = XFS_AT_UID;
397 VOP_GETATTR(vp, &va, 0, NULL, error);
398 if (error)
399 return error;
400 if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
401 return EPERM;
402 return error;
403}
404
405
406
407
408
409
410
411STATIC int
412xfs_acl_find_any_exec(
413 xfs_acl_t *fap)
414{
415 int i;
416 int masked_aces = 0;
417 int mask = 0;
418
419 for (i = 0; i < fap->acl_cnt; i++) {
420 if (fap->acl_entry[i].ae_perm & ACL_EXECUTE) {
421 if (fap->acl_entry[i].ae_tag & (ACL_USER_OBJ|ACL_OTHER))
422 return 1;
423
424 if (fap->acl_entry[i].ae_tag == ACL_MASK)
425 mask = fap->acl_entry[i].ae_perm;
426 else
427 masked_aces |= fap->acl_entry[i].ae_perm;
428
429 if ((mask & masked_aces) & ACL_EXECUTE)
430 return 1;
431 }
432 }
433
434 return 0;
435}
436
437
438
439
440
441
442
443
444
445
446
447
448
449STATIC int
450xfs_acl_capability_check(
451 mode_t mode,
452 cred_t *cr,
453 xfs_acl_t *fap)
454{
455 if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
456 return EACCES;
457 if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
458 return EACCES;
459 if ((mode & ACL_EXECUTE) &&
460 (!capable_cred(cr, CAP_DAC_OVERRIDE) ||
461 !xfs_acl_find_any_exec(fap))) {
462 return EACCES;
463 }
464
465 return 0;
466}
467
468
469
470
471
472
473
474STATIC int
475xfs_acl_access(
476 uid_t fuid,
477 gid_t fgid,
478 xfs_acl_t *fap,
479 mode_t md,
480 cred_t *cr)
481{
482 xfs_acl_entry_t matched;
483 int i, allows;
484 int maskallows = -1;
485 int seen_userobj = 0;
486
487 matched.ae_tag = 0;
488 md >>= 6;
489
490 for (i = 0; i < fap->acl_cnt; i++) {
491
492
493
494
495 if (matched.ae_tag == ACL_USER_OBJ)
496 break;
497 if (matched.ae_tag == ACL_USER) {
498 if (maskallows != -1 && seen_userobj)
499 break;
500 if (fap->acl_entry[i].ae_tag != ACL_MASK &&
501 fap->acl_entry[i].ae_tag != ACL_USER_OBJ)
502 continue;
503 }
504
505 allows = ((fap->acl_entry[i].ae_perm & md) == md);
506
507 switch (fap->acl_entry[i].ae_tag) {
508 case ACL_USER_OBJ:
509 seen_userobj = 1;
510 if (fuid != current->fsuid)
511 continue;
512 matched.ae_tag = ACL_USER_OBJ;
513 matched.ae_perm = allows;
514 break;
515 case ACL_USER:
516 if (fap->acl_entry[i].ae_id != current->fsuid)
517 continue;
518 matched.ae_tag = ACL_USER;
519 matched.ae_perm = allows;
520 break;
521 case ACL_GROUP_OBJ:
522 if ((matched.ae_tag == ACL_GROUP_OBJ ||
523 matched.ae_tag == ACL_GROUP) && !allows)
524 continue;
525 if (!in_group_p(fgid))
526 continue;
527 matched.ae_tag = ACL_GROUP_OBJ;
528 matched.ae_perm = allows;
529 break;
530 case ACL_GROUP:
531 if ((matched.ae_tag == ACL_GROUP_OBJ ||
532 matched.ae_tag == ACL_GROUP) && !allows)
533 continue;
534 if (!in_group_p(fap->acl_entry[i].ae_id))
535 continue;
536 matched.ae_tag = ACL_GROUP;
537 matched.ae_perm = allows;
538 break;
539 case ACL_MASK:
540 maskallows = allows;
541 break;
542 case ACL_OTHER:
543 if (matched.ae_tag != 0)
544 continue;
545 matched.ae_tag = ACL_OTHER;
546 matched.ae_perm = allows;
547 break;
548 }
549 }
550
551
552
553
554 switch (matched.ae_tag) {
555 case ACL_OTHER:
556 case ACL_USER_OBJ:
557 if (matched.ae_perm)
558 return 0;
559 break;
560 case ACL_USER:
561 case ACL_GROUP_OBJ:
562 case ACL_GROUP:
563 if (maskallows && matched.ae_perm)
564 return 0;
565 break;
566 case 0:
567 break;
568 }
569
570 return xfs_acl_capability_check(md, cr, fap);
571}
572
573
574
575
576
577STATIC int
578xfs_acl_invalid(
579 xfs_acl_t *aclp)
580{
581 xfs_acl_entry_t *entry, *e;
582 int user = 0, group = 0, other = 0, mask = 0;
583 int mask_required = 0;
584 int i, j;
585
586 if (!aclp)
587 goto acl_invalid;
588
589 if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES)
590 goto acl_invalid;
591
592 for (i = 0; i < aclp->acl_cnt; i++) {
593 entry = &aclp->acl_entry[i];
594 switch (entry->ae_tag) {
595 case ACL_USER_OBJ:
596 if (user++)
597 goto acl_invalid;
598 break;
599 case ACL_GROUP_OBJ:
600 if (group++)
601 goto acl_invalid;
602 break;
603 case ACL_OTHER:
604 if (other++)
605 goto acl_invalid;
606 break;
607 case ACL_USER:
608 case ACL_GROUP:
609 for (j = i + 1; j < aclp->acl_cnt; j++) {
610 e = &aclp->acl_entry[j];
611 if (e->ae_id == entry->ae_id &&
612 e->ae_tag == entry->ae_tag)
613 goto acl_invalid;
614 }
615 mask_required++;
616 break;
617 case ACL_MASK:
618 if (mask++)
619 goto acl_invalid;
620 break;
621 default:
622 goto acl_invalid;
623 }
624 }
625 if (!user || !group || !other || (mask_required && !mask))
626 goto acl_invalid;
627 else
628 return 0;
629acl_invalid:
630 return EINVAL;
631}
632
633
634
635
636STATIC void
637xfs_acl_get_endian(
638 xfs_acl_t *aclp)
639{
640 xfs_acl_entry_t *ace, *end;
641
642 INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
643 end = &aclp->acl_entry[0]+aclp->acl_cnt;
644 for (ace = &aclp->acl_entry[0]; ace < end; ace++) {
645 INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag);
646 INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id);
647 INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm);
648 }
649}
650
651
652
653
654STATIC void
655xfs_acl_get_attr(
656 vnode_t *vp,
657 xfs_acl_t *aclp,
658 int kind,
659 int flags,
660 int *error)
661{
662 int len = sizeof(xfs_acl_t);
663
664 ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
665 flags |= ATTR_ROOT;
666 VOP_ATTR_GET(vp,
667 kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT,
668 (char *)aclp, &len, flags, sys_cred, *error);
669 if (*error || (flags & ATTR_KERNOVAL))
670 return;
671 xfs_acl_get_endian(aclp);
672}
673
674
675
676
677STATIC void
678xfs_acl_set_attr(
679 vnode_t *vp,
680 xfs_acl_t *aclp,
681 int kind,
682 int *error)
683{
684 xfs_acl_entry_t *ace, *newace, *end;
685 xfs_acl_t *newacl;
686 int len;
687
688 if (!(_ACL_ALLOC(newacl))) {
689 *error = ENOMEM;
690 return;
691 }
692
693 len = sizeof(xfs_acl_t) -
694 (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt));
695 end = &aclp->acl_entry[0]+aclp->acl_cnt;
696 for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0];
697 ace < end;
698 ace++, newace++) {
699 INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
700 INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
701 INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
702 }
703 INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
704 VOP_ATTR_SET(vp,
705 kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT,
706 (char *)newacl, len, ATTR_ROOT, sys_cred, *error);
707 _ACL_FREE(newacl);
708}
709
710int
711xfs_acl_vtoacl(
712 vnode_t *vp,
713 xfs_acl_t *access_acl,
714 xfs_acl_t *default_acl)
715{
716 vattr_t va;
717 int error = 0;
718
719 if (access_acl) {
720
721
722
723
724 xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
725 if (!error) {
726
727 va.va_mask = XFS_AT_MODE;
728 VOP_GETATTR(vp, &va, 0, sys_cred, error);
729 }
730
731 if (error)
732 access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
733 else
734 xfs_acl_sync_mode(va.va_mode, access_acl);
735 }
736
737 if (default_acl) {
738 xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error);
739 if (error)
740 default_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
741 }
742 return error;
743}
744
745
746
747
748
749int
750xfs_acl_inherit(
751 vnode_t *vp,
752 vattr_t *vap,
753 xfs_acl_t *pdaclp)
754{
755 xfs_acl_t *cacl;
756 int error = 0;
757 int basicperms = 0;
758
759
760
761
762
763 if (!vp)
764 return 0;
765 if (!pdaclp || xfs_acl_invalid(pdaclp))
766 return 0;
767
768
769
770
771
772
773
774
775
776 if (!(_ACL_ALLOC(cacl)))
777 return ENOMEM;
778
779 memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
780 xfs_acl_filter_mode(vap->va_mode, cacl);
781 xfs_acl_setmode(vp, cacl, &basicperms);
782
783
784
785
786
787
788
789
790 if (vp->v_type == VDIR)
791 xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
792 if (!error && !basicperms)
793 xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
794 _ACL_FREE(cacl);
795 return error;
796}
797
798
799
800
801
802
803
804
805STATIC int
806xfs_acl_setmode(
807 vnode_t *vp,
808 xfs_acl_t *acl,
809 int *basicperms)
810{
811 vattr_t va;
812 xfs_acl_entry_t *ap;
813 xfs_acl_entry_t *gap = NULL;
814 int i, error, nomask = 1;
815
816 *basicperms = 1;
817
818 if (acl->acl_cnt == XFS_ACL_NOT_PRESENT)
819 return 0;
820
821
822
823
824
825 va.va_mask = XFS_AT_MODE;
826 VOP_GETATTR(vp, &va, 0, sys_cred, error);
827 if (error)
828 return error;
829
830 va.va_mask = XFS_AT_MODE;
831 va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
832 ap = acl->acl_entry;
833 for (i = 0; i < acl->acl_cnt; ++i) {
834 switch (ap->ae_tag) {
835 case ACL_USER_OBJ:
836 va.va_mode |= ap->ae_perm << 6;
837 break;
838 case ACL_GROUP_OBJ:
839 gap = ap;
840 break;
841 case ACL_MASK:
842 nomask = 0;
843 va.va_mode |= ap->ae_perm << 3;
844 *basicperms = 0;
845 break;
846 case ACL_OTHER:
847 va.va_mode |= ap->ae_perm;
848 break;
849 default:
850 *basicperms = 0;
851 break;
852 }
853 ap++;
854 }
855
856
857 if (gap && nomask)
858 va.va_mode |= gap->ae_perm << 3;
859
860 VOP_SETATTR(vp, &va, 0, sys_cred, error);
861 return error;
862}
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895STATIC void
896xfs_acl_sync_mode(
897 mode_t mode,
898 xfs_acl_t *acl)
899{
900 int i, nomask = 1;
901 xfs_acl_entry_t *ap;
902 xfs_acl_entry_t *gap = NULL;
903
904
905
906
907
908 for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
909 switch (ap->ae_tag) {
910 case ACL_USER_OBJ:
911 ap->ae_perm = (mode >> 6) & 0x7;
912 break;
913 case ACL_GROUP_OBJ:
914 gap = ap;
915 break;
916 case ACL_MASK:
917 nomask = 0;
918 ap->ae_perm = (mode >> 3) & 0x7;
919 break;
920 case ACL_OTHER:
921 ap->ae_perm = mode & 0x7;
922 break;
923 default:
924 break;
925 }
926 }
927
928 if (gap && nomask)
929 gap->ae_perm = (mode >> 3) & 0x7;
930}
931
932
933
934
935
936
937
938
939STATIC void
940xfs_acl_filter_mode(
941 mode_t mode,
942 xfs_acl_t *acl)
943{
944 int i, nomask = 1;
945 xfs_acl_entry_t *ap;
946 xfs_acl_entry_t *gap = NULL;
947
948
949
950
951
952 for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
953 switch (ap->ae_tag) {
954 case ACL_USER_OBJ:
955 ap->ae_perm &= (mode >> 6) & 0x7;
956 break;
957 case ACL_GROUP_OBJ:
958 gap = ap;
959 break;
960 case ACL_MASK:
961 nomask = 0;
962 ap->ae_perm &= (mode >> 3) & 0x7;
963 break;
964 case ACL_OTHER:
965 ap->ae_perm &= mode & 0x7;
966 break;
967 default:
968 break;
969 }
970 }
971
972 if (gap && nomask)
973 gap->ae_perm &= (mode >> 3) & 0x7;
974}
975