b2f639a1416f0ecd1c0b91e4958584de823c3a46
[linux-2.6.git] / fs / xfs / xfs_acl.c
1 /*
2  * Copyright (c) 2001-2002,2005 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_inum.h"
23 #include "xfs_ag.h"
24 #include "xfs_dir2.h"
25 #include "xfs_bmap_btree.h"
26 #include "xfs_alloc_btree.h"
27 #include "xfs_ialloc_btree.h"
28 #include "xfs_dir2_sf.h"
29 #include "xfs_attr_sf.h"
30 #include "xfs_dinode.h"
31 #include "xfs_inode.h"
32 #include "xfs_btree.h"
33 #include "xfs_acl.h"
34 #include "xfs_attr.h"
35 #include "xfs_vnodeops.h"
36
37 #include <linux/capability.h>
38 #include <linux/posix_acl_xattr.h>
39
40 STATIC int      xfs_acl_setmode(struct inode *, xfs_acl_t *, int *);
41 STATIC void     xfs_acl_filter_mode(mode_t, xfs_acl_t *);
42 STATIC void     xfs_acl_get_endian(xfs_acl_t *);
43 STATIC int      xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
44 STATIC int      xfs_acl_invalid(xfs_acl_t *);
45 STATIC void     xfs_acl_sync_mode(mode_t, xfs_acl_t *);
46 STATIC void     xfs_acl_get_attr(struct inode *, xfs_acl_t *, int, int, int *);
47 STATIC void     xfs_acl_set_attr(struct inode *, xfs_acl_t *, int, int *);
48 STATIC int      xfs_acl_allow_set(struct inode *, int);
49
50 kmem_zone_t *xfs_acl_zone;
51
52
53 /*
54  * Test for existence of access ACL attribute as efficiently as possible.
55  */
56 int
57 xfs_acl_vhasacl_access(
58         struct inode    *vp)
59 {
60         int             error;
61
62         xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error);
63         return (error == 0);
64 }
65
66 /*
67  * Test for existence of default ACL attribute as efficiently as possible.
68  */
69 int
70 xfs_acl_vhasacl_default(
71         struct inode    *vp)
72 {
73         int             error;
74
75         if (!S_ISDIR(vp->i_mode))
76                 return 0;
77         xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
78         return (error == 0);
79 }
80
81 /*
82  * Convert from extended attribute representation to in-memory for XFS.
83  */
84 STATIC int
85 posix_acl_xattr_to_xfs(
86         posix_acl_xattr_header  *src,
87         size_t                  size,
88         xfs_acl_t               *dest)
89 {
90         posix_acl_xattr_entry   *src_entry;
91         xfs_acl_entry_t         *dest_entry;
92         int                     n;
93
94         if (!src || !dest)
95                 return EINVAL;
96
97         if (size < sizeof(posix_acl_xattr_header))
98                 return EINVAL;
99
100         if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
101                 return EOPNOTSUPP;
102
103         memset(dest, 0, sizeof(xfs_acl_t));
104         dest->acl_cnt = posix_acl_xattr_count(size);
105         if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES)
106                 return EINVAL;
107
108         /*
109          * acl_set_file(3) may request that we set default ACLs with
110          * zero length -- defend (gracefully) against that here.
111          */
112         if (!dest->acl_cnt)
113                 return 0;
114
115         src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src));
116         dest_entry = &dest->acl_entry[0];
117
118         for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) {
119                 dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm);
120                 if (_ACL_PERM_INVALID(dest_entry->ae_perm))
121                         return EINVAL;
122                 dest_entry->ae_tag  = le16_to_cpu(src_entry->e_tag);
123                 switch(dest_entry->ae_tag) {
124                 case ACL_USER:
125                 case ACL_GROUP:
126                         dest_entry->ae_id = le32_to_cpu(src_entry->e_id);
127                         break;
128                 case ACL_USER_OBJ:
129                 case ACL_GROUP_OBJ:
130                 case ACL_MASK:
131                 case ACL_OTHER:
132                         dest_entry->ae_id = ACL_UNDEFINED_ID;
133                         break;
134                 default:
135                         return EINVAL;
136                 }
137         }
138         if (xfs_acl_invalid(dest))
139                 return EINVAL;
140
141         return 0;
142 }
143
144 /*
145  * Comparison function called from xfs_sort().
146  * Primary key is ae_tag, secondary key is ae_id.
147  */
148 STATIC int
149 xfs_acl_entry_compare(
150         const void      *va,
151         const void      *vb)
152 {
153         xfs_acl_entry_t *a = (xfs_acl_entry_t *)va,
154                         *b = (xfs_acl_entry_t *)vb;
155
156         if (a->ae_tag == b->ae_tag)
157                 return (a->ae_id - b->ae_id);
158         return (a->ae_tag - b->ae_tag);
159 }
160
161 /*
162  * Convert from in-memory XFS to extended attribute representation.
163  */
164 STATIC int
165 posix_acl_xfs_to_xattr(
166         xfs_acl_t               *src,
167         posix_acl_xattr_header  *dest,
168         size_t                  size)
169 {
170         int                     n;
171         size_t                  new_size = posix_acl_xattr_size(src->acl_cnt);
172         posix_acl_xattr_entry   *dest_entry;
173         xfs_acl_entry_t         *src_entry;
174
175         if (size < new_size)
176                 return -ERANGE;
177
178         /* Need to sort src XFS ACL by <ae_tag,ae_id> */
179         xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
180                  xfs_acl_entry_compare);
181
182         dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
183         dest_entry = &dest->a_entries[0];
184         src_entry = &src->acl_entry[0];
185         for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
186                 dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
187                 if (_ACL_PERM_INVALID(src_entry->ae_perm))
188                         return -EINVAL;
189                 dest_entry->e_tag  = cpu_to_le16(src_entry->ae_tag);
190                 switch (src_entry->ae_tag) {
191                 case ACL_USER:
192                 case ACL_GROUP:
193                         dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
194                                 break;
195                 case ACL_USER_OBJ:
196                 case ACL_GROUP_OBJ:
197                 case ACL_MASK:
198                 case ACL_OTHER:
199                         dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
200                         break;
201                 default:
202                         return -EINVAL;
203                 }
204         }
205         return new_size;
206 }
207
208 int
209 xfs_acl_vget(
210         struct inode    *vp,
211         void            *acl,
212         size_t          size,
213         int             kind)
214 {
215         int                     error;
216         xfs_acl_t               *xfs_acl = NULL;
217         posix_acl_xattr_header  *ext_acl = acl;
218         int                     flags = 0;
219
220         if(size) {
221                 if (!(_ACL_ALLOC(xfs_acl))) {
222                         error = ENOMEM;
223                         goto out;
224                 }
225                 memset(xfs_acl, 0, sizeof(xfs_acl_t));
226         } else
227                 flags = ATTR_KERNOVAL;
228
229         xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
230         if (error)
231                 goto out;
232
233         if (!size) {
234                 error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
235         } else {
236                 if (xfs_acl_invalid(xfs_acl)) {
237                         error = EINVAL;
238                         goto out;
239                 }
240                 if (kind == _ACL_TYPE_ACCESS)
241                         xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, xfs_acl);
242                 error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
243         }
244 out:
245         if(xfs_acl)
246                 _ACL_FREE(xfs_acl);
247         return -error;
248 }
249
250 int
251 xfs_acl_vremove(
252         struct inode    *vp,
253         int             kind)
254 {
255         int             error;
256
257         error = xfs_acl_allow_set(vp, kind);
258         if (!error) {
259                 error = xfs_attr_remove(XFS_I(vp),
260                                                 kind == _ACL_TYPE_DEFAULT?
261                                                 SGI_ACL_DEFAULT: SGI_ACL_FILE,
262                                                 ATTR_ROOT);
263                 if (error == ENOATTR)
264                         error = 0;      /* 'scool */
265         }
266         return -error;
267 }
268
269 int
270 xfs_acl_vset(
271         struct inode            *vp,
272         void                    *acl,
273         size_t                  size,
274         int                     kind)
275 {
276         posix_acl_xattr_header  *ext_acl = acl;
277         xfs_acl_t               *xfs_acl;
278         int                     error;
279         int                     basicperms = 0; /* more than std unix perms? */
280
281         if (!acl)
282                 return -EINVAL;
283
284         if (!(_ACL_ALLOC(xfs_acl)))
285                 return -ENOMEM;
286
287         error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl);
288         if (error) {
289                 _ACL_FREE(xfs_acl);
290                 return -error;
291         }
292         if (!xfs_acl->acl_cnt) {
293                 _ACL_FREE(xfs_acl);
294                 return 0;
295         }
296
297         error = xfs_acl_allow_set(vp, kind);
298
299         /* Incoming ACL exists, set file mode based on its value */
300         if (!error && kind == _ACL_TYPE_ACCESS)
301                 error = xfs_acl_setmode(vp, xfs_acl, &basicperms);
302
303         if (error)
304                 goto out;
305
306         /*
307          * If we have more than std unix permissions, set up the actual attr.
308          * Otherwise, delete any existing attr.  This prevents us from
309          * having actual attrs for permissions that can be stored in the
310          * standard permission bits.
311          */
312         if (!basicperms) {
313                 xfs_acl_set_attr(vp, xfs_acl, kind, &error);
314         } else {
315                 error = -xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
316         }
317
318 out:
319         _ACL_FREE(xfs_acl);
320         return -error;
321 }
322
323 int
324 xfs_acl_iaccess(
325         xfs_inode_t     *ip,
326         mode_t          mode,
327         cred_t          *cr)
328 {
329         xfs_acl_t       *acl;
330         int             rval;
331         struct xfs_name acl_name = {SGI_ACL_FILE, SGI_ACL_FILE_SIZE};
332
333         if (!(_ACL_ALLOC(acl)))
334                 return -1;
335
336         /* If the file has no ACL return -1. */
337         rval = sizeof(xfs_acl_t);
338         if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval, ATTR_ROOT)) {
339                 _ACL_FREE(acl);
340                 return -1;
341         }
342         xfs_acl_get_endian(acl);
343
344         /* If the file has an empty ACL return -1. */
345         if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) {
346                 _ACL_FREE(acl);
347                 return -1;
348         }
349
350         /* Synchronize ACL with mode bits */
351         xfs_acl_sync_mode(ip->i_d.di_mode, acl);
352
353         rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);
354         _ACL_FREE(acl);
355         return rval;
356 }
357
358 STATIC int
359 xfs_acl_allow_set(
360         struct inode    *vp,
361         int             kind)
362 {
363         if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
364                 return EPERM;
365         if (kind == _ACL_TYPE_DEFAULT && !S_ISDIR(vp->i_mode))
366                 return ENOTDIR;
367         if (vp->i_sb->s_flags & MS_RDONLY)
368                 return EROFS;
369         if (XFS_I(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
370                 return EPERM;
371         return 0;
372 }
373
374 /*
375  * Note: cr is only used here for the capability check if the ACL test fails.
376  *       It is not used to find out the credentials uid or groups etc, as was
377  *       done in IRIX. It is assumed that the uid and groups for the current
378  *       thread are taken from "current" instead of the cr parameter.
379  */
380 STATIC int
381 xfs_acl_access(
382         uid_t           fuid,
383         gid_t           fgid,
384         xfs_acl_t       *fap,
385         mode_t          md,
386         cred_t          *cr)
387 {
388         xfs_acl_entry_t matched;
389         int             i, allows;
390         int             maskallows = -1;        /* true, but not 1, either */
391         int             seen_userobj = 0;
392
393         matched.ae_tag = 0;     /* Invalid type */
394         matched.ae_perm = 0;
395
396         for (i = 0; i < fap->acl_cnt; i++) {
397                 /*
398                  * Break out if we've got a user_obj entry or
399                  * a user entry and the mask (and have processed USER_OBJ)
400                  */
401                 if (matched.ae_tag == ACL_USER_OBJ)
402                         break;
403                 if (matched.ae_tag == ACL_USER) {
404                         if (maskallows != -1 && seen_userobj)
405                                 break;
406                         if (fap->acl_entry[i].ae_tag != ACL_MASK &&
407                             fap->acl_entry[i].ae_tag != ACL_USER_OBJ)
408                                 continue;
409                 }
410                 /* True if this entry allows the requested access */
411                 allows = ((fap->acl_entry[i].ae_perm & md) == md);
412
413                 switch (fap->acl_entry[i].ae_tag) {
414                 case ACL_USER_OBJ:
415                         seen_userobj = 1;
416                         if (fuid != current->fsuid)
417                                 continue;
418                         matched.ae_tag = ACL_USER_OBJ;
419                         matched.ae_perm = allows;
420                         break;
421                 case ACL_USER:
422                         if (fap->acl_entry[i].ae_id != current->fsuid)
423                                 continue;
424                         matched.ae_tag = ACL_USER;
425                         matched.ae_perm = allows;
426                         break;
427                 case ACL_GROUP_OBJ:
428                         if ((matched.ae_tag == ACL_GROUP_OBJ ||
429                             matched.ae_tag == ACL_GROUP) && !allows)
430                                 continue;
431                         if (!in_group_p(fgid))
432                                 continue;
433                         matched.ae_tag = ACL_GROUP_OBJ;
434                         matched.ae_perm = allows;
435                         break;
436                 case ACL_GROUP:
437                         if ((matched.ae_tag == ACL_GROUP_OBJ ||
438                             matched.ae_tag == ACL_GROUP) && !allows)
439                                 continue;
440                         if (!in_group_p(fap->acl_entry[i].ae_id))
441                                 continue;
442                         matched.ae_tag = ACL_GROUP;
443                         matched.ae_perm = allows;
444                         break;
445                 case ACL_MASK:
446                         maskallows = allows;
447                         break;
448                 case ACL_OTHER:
449                         if (matched.ae_tag != 0)
450                                 continue;
451                         matched.ae_tag = ACL_OTHER;
452                         matched.ae_perm = allows;
453                         break;
454                 }
455         }
456         /*
457          * First possibility is that no matched entry allows access.
458          * The capability to override DAC may exist, so check for it.
459          */
460         switch (matched.ae_tag) {
461         case ACL_OTHER:
462         case ACL_USER_OBJ:
463                 if (matched.ae_perm)
464                         return 0;
465                 break;
466         case ACL_USER:
467         case ACL_GROUP_OBJ:
468         case ACL_GROUP:
469                 if (maskallows && matched.ae_perm)
470                         return 0;
471                 break;
472         case 0:
473                 break;
474         }
475
476         /* EACCES tells generic_permission to check for capability overrides */
477         return EACCES;
478 }
479
480 /*
481  * ACL validity checker.
482  *   This acl validation routine checks each ACL entry read in makes sense.
483  */
484 STATIC int
485 xfs_acl_invalid(
486         xfs_acl_t       *aclp)
487 {
488         xfs_acl_entry_t *entry, *e;
489         int             user = 0, group = 0, other = 0, mask = 0;
490         int             mask_required = 0;
491         int             i, j;
492
493         if (!aclp)
494                 goto acl_invalid;
495
496         if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES)
497                 goto acl_invalid;
498
499         for (i = 0; i < aclp->acl_cnt; i++) {
500                 entry = &aclp->acl_entry[i];
501                 switch (entry->ae_tag) {
502                 case ACL_USER_OBJ:
503                         if (user++)
504                                 goto acl_invalid;
505                         break;
506                 case ACL_GROUP_OBJ:
507                         if (group++)
508                                 goto acl_invalid;
509                         break;
510                 case ACL_OTHER:
511                         if (other++)
512                                 goto acl_invalid;
513                         break;
514                 case ACL_USER:
515                 case ACL_GROUP:
516                         for (j = i + 1; j < aclp->acl_cnt; j++) {
517                                 e = &aclp->acl_entry[j];
518                                 if (e->ae_id == entry->ae_id &&
519                                     e->ae_tag == entry->ae_tag)
520                                         goto acl_invalid;
521                         }
522                         mask_required++;
523                         break;
524                 case ACL_MASK:
525                         if (mask++)
526                                 goto acl_invalid;
527                         break;
528                 default:
529                         goto acl_invalid;
530                 }
531         }
532         if (!user || !group || !other || (mask_required && !mask))
533                 goto acl_invalid;
534         else
535                 return 0;
536 acl_invalid:
537         return EINVAL;
538 }
539
540 /*
541  * Do ACL endian conversion.
542  */
543 STATIC void
544 xfs_acl_get_endian(
545         xfs_acl_t       *aclp)
546 {
547         xfs_acl_entry_t *ace, *end;
548
549         INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
550         end = &aclp->acl_entry[0]+aclp->acl_cnt;
551         for (ace = &aclp->acl_entry[0]; ace < end; ace++) {
552                 INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag);
553                 INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id);
554                 INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm);
555         }
556 }
557
558 /*
559  * Get the ACL from the EA and do endian conversion.
560  */
561 STATIC void
562 xfs_acl_get_attr(
563         struct inode    *vp,
564         xfs_acl_t       *aclp,
565         int             kind,
566         int             flags,
567         int             *error)
568 {
569         int             len = sizeof(xfs_acl_t);
570
571         ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
572         flags |= ATTR_ROOT;
573         *error = xfs_attr_get(XFS_I(vp),
574                                         kind == _ACL_TYPE_ACCESS ?
575                                         SGI_ACL_FILE : SGI_ACL_DEFAULT,
576                                         (char *)aclp, &len, flags);
577         if (*error || (flags & ATTR_KERNOVAL))
578                 return;
579         xfs_acl_get_endian(aclp);
580 }
581
582 /*
583  * Set the EA with the ACL and do endian conversion.
584  */
585 STATIC void
586 xfs_acl_set_attr(
587         struct inode    *vp,
588         xfs_acl_t       *aclp,
589         int             kind,
590         int             *error)
591 {
592         xfs_acl_entry_t *ace, *newace, *end;
593         xfs_acl_t       *newacl;
594         int             len;
595
596         if (!(_ACL_ALLOC(newacl))) {
597                 *error = ENOMEM;
598                 return;
599         }
600
601         len = sizeof(xfs_acl_t) -
602               (sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt));
603         end = &aclp->acl_entry[0]+aclp->acl_cnt;
604         for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0];
605              ace < end;
606              ace++, newace++) {
607                 INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
608                 INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
609                 INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
610         }
611         INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
612         *error = xfs_attr_set(XFS_I(vp),
613                                 kind == _ACL_TYPE_ACCESS ?
614                                 SGI_ACL_FILE: SGI_ACL_DEFAULT,
615                                 (char *)newacl, len, ATTR_ROOT);
616         _ACL_FREE(newacl);
617 }
618
619 int
620 xfs_acl_vtoacl(
621         struct inode    *vp,
622         xfs_acl_t       *access_acl,
623         xfs_acl_t       *default_acl)
624 {
625         int             error = 0;
626
627         if (access_acl) {
628                 /*
629                  * Get the Access ACL and the mode.  If either cannot
630                  * be obtained for some reason, invalidate the access ACL.
631                  */
632                 xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
633                 if (error)
634                         access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
635                 else /* We have a good ACL and the file mode, synchronize. */
636                         xfs_acl_sync_mode(XFS_I(vp)->i_d.di_mode, access_acl);
637         }
638
639         if (default_acl) {
640                 xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error);
641                 if (error)
642                         default_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
643         }
644         return error;
645 }
646
647 /*
648  * This function retrieves the parent directory's acl, processes it
649  * and lets the child inherit the acl(s) that it should.
650  */
651 int
652 xfs_acl_inherit(
653         struct inode    *vp,
654         mode_t          mode,
655         xfs_acl_t       *pdaclp)
656 {
657         xfs_acl_t       *cacl;
658         int             error = 0;
659         int             basicperms = 0;
660
661         /*
662          * If the parent does not have a default ACL, or it's an
663          * invalid ACL, we're done.
664          */
665         if (!vp)
666                 return 0;
667         if (!pdaclp || xfs_acl_invalid(pdaclp))
668                 return 0;
669
670         /*
671          * Copy the default ACL of the containing directory to
672          * the access ACL of the new file and use the mode that
673          * was passed in to set up the correct initial values for
674          * the u::,g::[m::], and o:: entries.  This is what makes
675          * umask() "work" with ACL's.
676          */
677
678         if (!(_ACL_ALLOC(cacl)))
679                 return ENOMEM;
680
681         memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
682         xfs_acl_filter_mode(mode, cacl);
683         error = xfs_acl_setmode(vp, cacl, &basicperms);
684         if (error)
685                 goto out_error;
686
687         /*
688          * Set the Default and Access ACL on the file.  The mode is already
689          * set on the file, so we don't need to worry about that.
690          *
691          * If the new file is a directory, its default ACL is a copy of
692          * the containing directory's default ACL.
693          */
694         if (S_ISDIR(vp->i_mode))
695                 xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
696         if (!error && !basicperms)
697                 xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
698 out_error:
699         _ACL_FREE(cacl);
700         return error;
701 }
702
703 /*
704  * Set up the correct mode on the file based on the supplied ACL.  This
705  * makes sure that the mode on the file reflects the state of the
706  * u::,g::[m::], and o:: entries in the ACL.  Since the mode is where
707  * the ACL is going to get the permissions for these entries, we must
708  * synchronize the mode whenever we set the ACL on a file.
709  */
710 STATIC int
711 xfs_acl_setmode(
712         struct inode    *vp,
713         xfs_acl_t       *acl,
714         int             *basicperms)
715 {
716         struct iattr    iattr;
717         xfs_acl_entry_t *ap;
718         xfs_acl_entry_t *gap = NULL;
719         int             i, nomask = 1;
720
721         *basicperms = 1;
722
723         if (acl->acl_cnt == XFS_ACL_NOT_PRESENT)
724                 return 0;
725
726         /*
727          * Copy the u::, g::, o::, and m:: bits from the ACL into the
728          * mode.  The m:: bits take precedence over the g:: bits.
729          */
730         iattr.ia_valid = ATTR_MODE;
731         iattr.ia_mode = XFS_I(vp)->i_d.di_mode;
732         iattr.ia_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
733         ap = acl->acl_entry;
734         for (i = 0; i < acl->acl_cnt; ++i) {
735                 switch (ap->ae_tag) {
736                 case ACL_USER_OBJ:
737                         iattr.ia_mode |= ap->ae_perm << 6;
738                         break;
739                 case ACL_GROUP_OBJ:
740                         gap = ap;
741                         break;
742                 case ACL_MASK:  /* more than just standard modes */
743                         nomask = 0;
744                         iattr.ia_mode |= ap->ae_perm << 3;
745                         *basicperms = 0;
746                         break;
747                 case ACL_OTHER:
748                         iattr.ia_mode |= ap->ae_perm;
749                         break;
750                 default:        /* more than just standard modes */
751                         *basicperms = 0;
752                         break;
753                 }
754                 ap++;
755         }
756
757         /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */
758         if (gap && nomask)
759                 iattr.ia_mode |= gap->ae_perm << 3;
760
761         return xfs_setattr(XFS_I(vp), &iattr, 0, sys_cred);
762 }
763
764 /*
765  * The permissions for the special ACL entries (u::, g::[m::], o::) are
766  * actually stored in the file mode (if there is both a group and a mask,
767  * the group is stored in the ACL entry and the mask is stored on the file).
768  * This allows the mode to remain automatically in sync with the ACL without
769  * the need for a call-back to the ACL system at every point where the mode
770  * could change.  This function takes the permissions from the specified mode
771  * and places it in the supplied ACL.
772  *
773  * This implementation draws its validity from the fact that, when the ACL
774  * was assigned, the mode was copied from the ACL.
775  * If the mode did not change, therefore, the mode remains exactly what was
776  * taken from the special ACL entries at assignment.
777  * If a subsequent chmod() was done, the POSIX spec says that the change in
778  * mode must cause an update to the ACL seen at user level and used for
779  * access checks.  Before and after a mode change, therefore, the file mode
780  * most accurately reflects what the special ACL entries should permit/deny.
781  *
782  * CAVEAT: If someone sets the SGI_ACL_FILE attribute directly,
783  *         the existing mode bits will override whatever is in the
784  *         ACL. Similarly, if there is a pre-existing ACL that was
785  *         never in sync with its mode (owing to a bug in 6.5 and
786  *         before), it will now magically (or mystically) be
787  *         synchronized.  This could cause slight astonishment, but
788  *         it is better than inconsistent permissions.
789  *
790  * The supplied ACL is a template that may contain any combination
791  * of special entries.  These are treated as place holders when we fill
792  * out the ACL.  This routine does not add or remove special entries, it
793  * simply unites each special entry with its associated set of permissions.
794  */
795 STATIC void
796 xfs_acl_sync_mode(
797         mode_t          mode,
798         xfs_acl_t       *acl)
799 {
800         int             i, nomask = 1;
801         xfs_acl_entry_t *ap;
802         xfs_acl_entry_t *gap = NULL;
803
804         /*
805          * Set ACL entries. POSIX1003.1eD16 requires that the MASK
806          * be set instead of the GROUP entry, if there is a MASK.
807          */
808         for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
809                 switch (ap->ae_tag) {
810                 case ACL_USER_OBJ:
811                         ap->ae_perm = (mode >> 6) & 0x7;
812                         break;
813                 case ACL_GROUP_OBJ:
814                         gap = ap;
815                         break;
816                 case ACL_MASK:
817                         nomask = 0;
818                         ap->ae_perm = (mode >> 3) & 0x7;
819                         break;
820                 case ACL_OTHER:
821                         ap->ae_perm = mode & 0x7;
822                         break;
823                 default:
824                         break;
825                 }
826         }
827         /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
828         if (gap && nomask)
829                 gap->ae_perm = (mode >> 3) & 0x7;
830 }
831
832 /*
833  * When inheriting an Access ACL from a directory Default ACL,
834  * the ACL bits are set to the intersection of the ACL default
835  * permission bits and the file permission bits in mode. If there
836  * are no permission bits on the file then we must not give them
837  * the ACL. This is what what makes umask() work with ACLs.
838  */
839 STATIC void
840 xfs_acl_filter_mode(
841         mode_t          mode,
842         xfs_acl_t       *acl)
843 {
844         int             i, nomask = 1;
845         xfs_acl_entry_t *ap;
846         xfs_acl_entry_t *gap = NULL;
847
848         /*
849          * Set ACL entries. POSIX1003.1eD16 requires that the MASK
850          * be merged with GROUP entry, if there is a MASK.
851          */
852         for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
853                 switch (ap->ae_tag) {
854                 case ACL_USER_OBJ:
855                         ap->ae_perm &= (mode >> 6) & 0x7;
856                         break;
857                 case ACL_GROUP_OBJ:
858                         gap = ap;
859                         break;
860                 case ACL_MASK:
861                         nomask = 0;
862                         ap->ae_perm &= (mode >> 3) & 0x7;
863                         break;
864                 case ACL_OTHER:
865                         ap->ae_perm &= mode & 0x7;
866                         break;
867                 default:
868                         break;
869                 }
870         }
871         /* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
872         if (gap && nomask)
873                 gap->ae_perm &= (mode >> 3) & 0x7;
874 }