Whamcloud - gitweb
LU-6142 tests: Fix style issues for chownmany.c
[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_LUSTRE_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 #if 0
60 static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
61                                               posix_acl_xattr_entry *s)
62 {
63         d->e_tag = cpu_to_le16(s->e_tag);
64         d->e_perm = cpu_to_le16(s->e_perm);
65         d->e_id = cpu_to_le32(s->e_id);
66 }
67 #endif
68
69 /*
70  * Check permission based on POSIX ACL.
71  */
72 int lustre_posix_acl_permission(struct lu_ucred *mu, const struct lu_attr *la,
73                                 int want, posix_acl_xattr_entry *entry,
74                                 int count)
75 {
76         posix_acl_xattr_entry *pa, *pe, *mask_obj;
77         posix_acl_xattr_entry ae, me;
78         int found = 0;
79
80         if (count <= 0)
81                 return -EACCES;
82
83         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
84                 lustre_posix_acl_le_to_cpu(&ae, pa);
85                 switch (ae.e_tag) {
86                 case ACL_USER_OBJ:
87                         /* (May have been checked already) */
88                         if (la->la_uid == mu->uc_fsuid)
89                                 goto check_perm;
90                         break;
91                 case ACL_USER:
92                         if (ae.e_id == mu->uc_fsuid)
93                                 goto mask;
94                         break;
95                 case ACL_GROUP_OBJ:
96                         if (lustre_in_group_p(mu, la->la_gid)) {
97                                 found = 1;
98                                 if ((ae.e_perm & want) == want)
99                                         goto mask;
100                         }
101                         break;
102                 case ACL_GROUP:
103                         if (lustre_in_group_p(mu, ae.e_id)) {
104                                 found = 1;
105                                 if ((ae.e_perm & want) == want)
106                                         goto mask;
107                         }
108                         break;
109                 case ACL_MASK:
110                         break;
111                 case ACL_OTHER:
112                         if (found)
113                                 return -EACCES;
114                         goto check_perm;
115                 default:
116                         return -EIO;
117 }
118         }
119         return -EIO;
120
121 mask:
122         for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
123                 lustre_posix_acl_le_to_cpu(&me, mask_obj);
124                 if (me.e_tag == ACL_MASK) {
125                         if ((ae.e_perm & me.e_perm & want) == want)
126                                 return 0;
127
128                         return -EACCES;
129                 }
130         }
131
132 check_perm:
133         if ((ae.e_perm & want) == want)
134                 return 0;
135
136         return -EACCES;
137 }
138 EXPORT_SYMBOL(lustre_posix_acl_permission);
139
140 /*
141  * Modify the ACL for the chmod.
142  */
143 int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, u32 mode,
144                                 int count)
145 {
146         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
147
148         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
149                 switch (le16_to_cpu(pa->e_tag)) {
150                 case ACL_USER_OBJ:
151                         pa->e_perm = cpu_to_le16((mode & S_IRWXU) >> 6);
152                         break;
153                 case ACL_USER:
154                 case ACL_GROUP:
155                         break;
156                 case ACL_GROUP_OBJ:
157                         group_obj = pa;
158                         break;
159                 case ACL_MASK:
160                         mask_obj = pa;
161                         break;
162                 case ACL_OTHER:
163                         pa->e_perm = cpu_to_le16(mode & S_IRWXO);
164                         break;
165                 default:
166                         return -EIO;
167                 }
168         }
169
170         if (mask_obj) {
171                 mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
172         } else {
173                 if (!group_obj)
174                         return -EIO;
175                 group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
176         }
177
178         return 0;
179 }
180 EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
181
182 /*
183  * Returns 0 if the acl can be exactly represented in the traditional
184  * file mode permission bits, or else 1. Returns -E... on error.
185  */
186 int
187 lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
188                             int count)
189 {
190         posix_acl_xattr_entry *pa, *pe;
191         mode_t mode = 0;
192         int not_equiv = 0;
193
194         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
195                 __u16 perm = le16_to_cpu(pa->e_perm);
196                 switch (le16_to_cpu(pa->e_tag)) {
197                         case ACL_USER_OBJ:
198                                 mode |= (perm & S_IRWXO) << 6;
199                                 break;
200                         case ACL_GROUP_OBJ:
201                                 mode |= (perm & S_IRWXO) << 3;
202                                 break;
203                         case ACL_OTHER:
204                                 mode |= perm & S_IRWXO;
205                                 break;
206                         case ACL_MASK:
207                                 mode = (mode & ~S_IRWXG) |
208                                         ((perm & S_IRWXO) << 3);
209                                 not_equiv = 1;
210                                 break;
211                         case ACL_USER:
212                         case ACL_GROUP:
213                                 not_equiv = 1;
214                                 break;
215                         default:
216                                 return -EINVAL;
217                 }
218         }
219         if (mode_p)
220                 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
221         return not_equiv;
222 }
223 EXPORT_SYMBOL(lustre_posix_acl_equiv_mode);
224
225 /*
226  * Modify acl when creating a new object.
227  */
228 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, u32 *pmode,
229                                  int count)
230 {
231         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
232         posix_acl_xattr_entry ae;
233         u32 mode = *pmode;
234         int not_equiv = 0;
235
236         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
237                 lustre_posix_acl_le_to_cpu(&ae, pa);
238                 switch (ae.e_tag) {
239                 case ACL_USER_OBJ:
240                         ae.e_perm &= (mode >> 6) | ~(0007);
241                         pa->e_perm = cpu_to_le16(ae.e_perm);
242                         mode &= (ae.e_perm << 6) | ~S_IRWXU;
243                         break;
244                 case ACL_USER:
245                 case ACL_GROUP:
246                         not_equiv = 1;
247                         break;
248                 case ACL_GROUP_OBJ:
249                         group_obj = pa;
250                         break;
251                 case ACL_OTHER:
252                         ae.e_perm &= mode | ~(0007);
253                         pa->e_perm = cpu_to_le16(ae.e_perm);
254                         mode &= ae.e_perm | ~(0007);
255                         break;
256                 case ACL_MASK:
257                         mask_obj = pa;
258                         not_equiv = 1;
259                         break;
260                 default:
261                         return -EIO;
262                 }
263         }
264
265         if (mask_obj) {
266                 ae.e_perm = le16_to_cpu(mask_obj->e_perm) &
267                                         ((mode >> 3) | ~(0007));
268                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
269                 mask_obj->e_perm = cpu_to_le16(ae.e_perm);
270         } else {
271                 if (!group_obj)
272                         return -EIO;
273                 ae.e_perm = le16_to_cpu(group_obj->e_perm) &
274                                         ((mode >> 3) | ~(0007));
275                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
276                 group_obj->e_perm = cpu_to_le16(ae.e_perm);
277         }
278
279         *pmode = (*pmode & ~S_IRWXUGO) | mode;
280         return not_equiv;
281 }
282 EXPORT_SYMBOL(lustre_posix_acl_create_masq);
283 #endif