Whamcloud - gitweb
5b290c6411d9abf3f37f620c14eae2cd75b495d6
[fs/lustre-release.git] / lustre / obdclass / acl.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2013, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * lustre/obdclass/acl.c
33  *
34  * Lustre Access Control List.
35  *
36  * Author: Fan Yong <fanyong@clusterfs.com>
37  */
38
39 #define DEBUG_SUBSYSTEM S_SEC
40 #include <lu_object.h>
41 #include <lustre_acl.h>
42 #include <lustre_eacl.h>
43 #include <obd_support.h>
44 #ifdef HAVE_SERVER_SUPPORT
45 # include <lustre_idmap.h>
46 # include <md_object.h>
47 #endif /* HAVE_SERVER_SUPPORT */
48
49 #ifdef CONFIG_FS_POSIX_ACL
50
51 static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
52                                               posix_acl_xattr_entry *s)
53 {
54         d->e_tag        = le16_to_cpu(s->e_tag);
55         d->e_perm       = le16_to_cpu(s->e_perm);
56         d->e_id         = le32_to_cpu(s->e_id);
57 }
58
59 /*static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
60                                               posix_acl_xattr_entry *s)
61 {
62         d->e_tag        = cpu_to_le16(s->e_tag);
63         d->e_perm       = cpu_to_le16(s->e_perm);
64         d->e_id         = cpu_to_le32(s->e_id);
65 }*/
66
67 /*
68  * Check permission based on POSIX ACL.
69  */
70 int lustre_posix_acl_permission(struct lu_ucred *mu, const struct lu_attr *la,
71                                 int want, posix_acl_xattr_entry *entry,
72                                 int count)
73 {
74         posix_acl_xattr_entry *pa, *pe, *mask_obj;
75         posix_acl_xattr_entry ae, me;
76         int found = 0;
77
78         if (count <= 0)
79                 return -EACCES;
80
81         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
82                 lustre_posix_acl_le_to_cpu(&ae, pa);
83                 switch (ae.e_tag) {
84                 case ACL_USER_OBJ:
85                         /* (May have been checked already) */
86                         if (la->la_uid == mu->uc_fsuid)
87                                 goto check_perm;
88                         break;
89                 case ACL_USER:
90                         if (ae.e_id == mu->uc_fsuid)
91                                 goto mask;
92                         break;
93                 case ACL_GROUP_OBJ:
94                         if (lustre_in_group_p(mu, la->la_gid)) {
95                                 found = 1;
96                                 if ((ae.e_perm & want) == want)
97                                         goto mask;
98                         }
99                         break;
100                 case ACL_GROUP:
101                         if (lustre_in_group_p(mu, ae.e_id)) {
102                                 found = 1;
103                                 if ((ae.e_perm & want) == want)
104                                         goto mask;
105                         }
106                         break;
107                 case ACL_MASK:
108                         break;
109                 case ACL_OTHER:
110                         if (found)
111                                 return -EACCES;
112                         else
113                                 goto check_perm;
114                 default:
115                         return -EIO;
116                 }
117         }
118         return -EIO;
119
120 mask:
121         for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
122                 lustre_posix_acl_le_to_cpu(&me, mask_obj);
123                 if (me.e_tag == ACL_MASK) {
124                         if ((ae.e_perm & me.e_perm & want) == want)
125                                 return 0;
126
127                         return -EACCES;
128                 }
129         }
130
131 check_perm:
132         if ((ae.e_perm & want) == want)
133                 return 0;
134
135         return -EACCES;
136 }
137 EXPORT_SYMBOL(lustre_posix_acl_permission);
138
139 /*
140  * Modify the ACL for the chmod.
141  */
142 int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, __u32 mode,
143                                 int count)
144 {
145         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
146
147         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
148                 switch (le16_to_cpu(pa->e_tag)) {
149                 case ACL_USER_OBJ:
150                         pa->e_perm = cpu_to_le16((mode & S_IRWXU) >> 6);
151                         break;
152                 case ACL_USER:
153                 case ACL_GROUP:
154                         break;
155                 case ACL_GROUP_OBJ:
156                         group_obj = pa;
157                         break;
158                 case ACL_MASK:
159                         mask_obj = pa;
160                         break;
161                 case ACL_OTHER:
162                         pa->e_perm = cpu_to_le16(mode & S_IRWXO);
163                         break;
164                 default:
165                         return -EIO;
166                 }
167         }
168
169         if (mask_obj) {
170                 mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
171         } else {
172                 if (!group_obj)
173                         return -EIO;
174                 group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
175         }
176
177         return 0;
178 }
179 EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
180
181 /*
182  * Returns 0 if the acl can be exactly represented in the traditional
183  * file mode permission bits, or else 1. Returns -E... on error.
184  */
185 int
186 lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
187                             int count)
188 {
189         posix_acl_xattr_entry *pa, *pe;
190         mode_t                 mode = 0;
191         int                    not_equiv = 0;
192
193         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
194                 __u16 perm = le16_to_cpu(pa->e_perm);
195                 switch (le16_to_cpu(pa->e_tag)) {
196                         case ACL_USER_OBJ:
197                                 mode |= (perm & S_IRWXO) << 6;
198                                 break;
199                         case ACL_GROUP_OBJ:
200                                 mode |= (perm & S_IRWXO) << 3;
201                                 break;
202                         case ACL_OTHER:
203                                 mode |= perm & S_IRWXO;
204                                 break;
205                         case ACL_MASK:
206                                 mode = (mode & ~S_IRWXG) |
207                                         ((perm & S_IRWXO) << 3);
208                                 not_equiv = 1;
209                                 break;
210                         case ACL_USER:
211                         case ACL_GROUP:
212                                 not_equiv = 1;
213                                 break;
214                         default:
215                                 return -EINVAL;
216                 }
217         }
218         if (mode_p)
219                 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
220         return not_equiv;
221 }
222 EXPORT_SYMBOL(lustre_posix_acl_equiv_mode);
223
224 /*
225  * Modify acl when creating a new object.
226  */
227 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,
228                                  int count)
229 {
230         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
231         posix_acl_xattr_entry ae;
232         __u32 mode = *pmode;
233         int not_equiv = 0;
234
235         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
236                 lustre_posix_acl_le_to_cpu(&ae, pa);
237                 switch (ae.e_tag) {
238                 case ACL_USER_OBJ:
239                         ae.e_perm &= (mode >> 6) | ~S_IRWXO;
240                         pa->e_perm = cpu_to_le16(ae.e_perm);
241                         mode &= (ae.e_perm << 6) | ~S_IRWXU;
242                         break;
243                 case ACL_USER:
244                 case ACL_GROUP:
245                         not_equiv = 1;
246                         break;
247                 case ACL_GROUP_OBJ:
248                         group_obj = pa;
249                         break;
250                 case ACL_OTHER:
251                         ae.e_perm &= mode | ~S_IRWXO;
252                         pa->e_perm = cpu_to_le16(ae.e_perm);
253                         mode &= ae.e_perm | ~S_IRWXO;
254                         break;
255                 case ACL_MASK:
256                         mask_obj = pa;
257                         not_equiv = 1;
258                         break;
259                 default:
260                         return -EIO;
261                 }
262         }
263
264         if (mask_obj) {
265                 ae.e_perm = le16_to_cpu(mask_obj->e_perm) &
266                             ((mode >> 3) | ~S_IRWXO);
267                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
268                 mask_obj->e_perm = cpu_to_le16(ae.e_perm);
269         } else {
270                 if (!group_obj)
271                         return -EIO;
272                 ae.e_perm = le16_to_cpu(group_obj->e_perm) &
273                             ((mode >> 3) | ~S_IRWXO);
274                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
275                 group_obj->e_perm = cpu_to_le16(ae.e_perm);
276         }
277
278         *pmode = (*pmode & ~S_IRWXUGO) | mode;
279         return not_equiv;
280 }
281 EXPORT_SYMBOL(lustre_posix_acl_create_masq);
282 #endif