Whamcloud - gitweb
LU-6971 cleanup: not support remote client anymore
[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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, 2013, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/obdclass/acl.c
37  *
38  * Lustre Access Control List.
39  *
40  * Author: Fan Yong <fanyong@clusterfs.com>
41  */
42
43 #define DEBUG_SUBSYSTEM S_SEC
44 #include <lu_object.h>
45 #include <lustre_acl.h>
46 #include <lustre_eacl.h>
47 #include <obd_support.h>
48 #ifdef HAVE_SERVER_SUPPORT
49 # include <lustre_idmap.h>
50 # include <md_object.h>
51 #endif /* HAVE_SERVER_SUPPORT */
52
53 #ifdef CONFIG_FS_POSIX_ACL
54
55 static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
56                                               posix_acl_xattr_entry *s)
57 {
58         d->e_tag        = le16_to_cpu(s->e_tag);
59         d->e_perm       = le16_to_cpu(s->e_perm);
60         d->e_id         = le32_to_cpu(s->e_id);
61 }
62
63 /*static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
64                                               posix_acl_xattr_entry *s)
65 {
66         d->e_tag        = cpu_to_le16(s->e_tag);
67         d->e_perm       = cpu_to_le16(s->e_perm);
68         d->e_id         = cpu_to_le32(s->e_id);
69 }*/
70
71 /*
72  * Check permission based on POSIX ACL.
73  */
74 int lustre_posix_acl_permission(struct lu_ucred *mu, const struct lu_attr *la,
75                                 int want, posix_acl_xattr_entry *entry,
76                                 int count)
77 {
78         posix_acl_xattr_entry *pa, *pe, *mask_obj;
79         posix_acl_xattr_entry ae, me;
80         int found = 0;
81
82         if (count <= 0)
83                 return -EACCES;
84
85         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
86                 lustre_posix_acl_le_to_cpu(&ae, pa);
87                 switch (ae.e_tag) {
88                 case ACL_USER_OBJ:
89                         /* (May have been checked already) */
90                         if (la->la_uid == mu->uc_fsuid)
91                                 goto check_perm;
92                         break;
93                 case ACL_USER:
94                         if (ae.e_id == mu->uc_fsuid)
95                                 goto mask;
96                         break;
97                 case ACL_GROUP_OBJ:
98                         if (lustre_in_group_p(mu, la->la_gid)) {
99                                 found = 1;
100                                 if ((ae.e_perm & want) == want)
101                                         goto mask;
102                         }
103                         break;
104                 case ACL_GROUP:
105                         if (lustre_in_group_p(mu, ae.e_id)) {
106                                 found = 1;
107                                 if ((ae.e_perm & want) == want)
108                                         goto mask;
109                         }
110                         break;
111                 case ACL_MASK:
112                         break;
113                 case ACL_OTHER:
114                         if (found)
115                                 return -EACCES;
116                         else
117                                 goto check_perm;
118                 default:
119                         return -EIO;
120                 }
121         }
122         return -EIO;
123
124 mask:
125         for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
126                 lustre_posix_acl_le_to_cpu(&me, mask_obj);
127                 if (me.e_tag == ACL_MASK) {
128                         if ((ae.e_perm & me.e_perm & want) == want)
129                                 return 0;
130
131                         return -EACCES;
132                 }
133         }
134
135 check_perm:
136         if ((ae.e_perm & want) == want)
137                 return 0;
138
139         return -EACCES;
140 }
141 EXPORT_SYMBOL(lustre_posix_acl_permission);
142
143 /*
144  * Modify the ACL for the chmod.
145  */
146 int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, __u32 mode,
147                                 int count)
148 {
149         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
150
151         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
152                 switch (le16_to_cpu(pa->e_tag)) {
153                 case ACL_USER_OBJ:
154                         pa->e_perm = cpu_to_le16((mode & S_IRWXU) >> 6);
155                         break;
156                 case ACL_USER:
157                 case ACL_GROUP:
158                         break;
159                 case ACL_GROUP_OBJ:
160                         group_obj = pa;
161                         break;
162                 case ACL_MASK:
163                         mask_obj = pa;
164                         break;
165                 case ACL_OTHER:
166                         pa->e_perm = cpu_to_le16(mode & S_IRWXO);
167                         break;
168                 default:
169                         return -EIO;
170                 }
171         }
172
173         if (mask_obj) {
174                 mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
175         } else {
176                 if (!group_obj)
177                         return -EIO;
178                 group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
179         }
180
181         return 0;
182 }
183 EXPORT_SYMBOL(lustre_posix_acl_chmod_masq);
184
185 /*
186  * Returns 0 if the acl can be exactly represented in the traditional
187  * file mode permission bits, or else 1. Returns -E... on error.
188  */
189 int
190 lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
191                             int count)
192 {
193         posix_acl_xattr_entry *pa, *pe;
194         mode_t                 mode = 0;
195         int                    not_equiv = 0;
196
197         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
198                 __u16 perm = le16_to_cpu(pa->e_perm);
199                 switch (le16_to_cpu(pa->e_tag)) {
200                         case ACL_USER_OBJ:
201                                 mode |= (perm & S_IRWXO) << 6;
202                                 break;
203                         case ACL_GROUP_OBJ:
204                                 mode |= (perm & S_IRWXO) << 3;
205                                 break;
206                         case ACL_OTHER:
207                                 mode |= perm & S_IRWXO;
208                                 break;
209                         case ACL_MASK:
210                                 mode = (mode & ~S_IRWXG) |
211                                         ((perm & S_IRWXO) << 3);
212                                 not_equiv = 1;
213                                 break;
214                         case ACL_USER:
215                         case ACL_GROUP:
216                                 not_equiv = 1;
217                                 break;
218                         default:
219                                 return -EINVAL;
220                 }
221         }
222         if (mode_p)
223                 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
224         return not_equiv;
225 }
226 EXPORT_SYMBOL(lustre_posix_acl_equiv_mode);
227
228 /*
229  * Modify acl when creating a new object.
230  */
231 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, __u32 *pmode,
232                                  int count)
233 {
234         posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
235         posix_acl_xattr_entry ae;
236         __u32 mode = *pmode;
237         int not_equiv = 0;
238
239         for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
240                 lustre_posix_acl_le_to_cpu(&ae, pa);
241                 switch (ae.e_tag) {
242                 case ACL_USER_OBJ:
243                         ae.e_perm &= (mode >> 6) | ~S_IRWXO;
244                         pa->e_perm = cpu_to_le16(ae.e_perm);
245                         mode &= (ae.e_perm << 6) | ~S_IRWXU;
246                         break;
247                 case ACL_USER:
248                 case ACL_GROUP:
249                         not_equiv = 1;
250                         break;
251                 case ACL_GROUP_OBJ:
252                         group_obj = pa;
253                         break;
254                 case ACL_OTHER:
255                         ae.e_perm &= mode | ~S_IRWXO;
256                         pa->e_perm = cpu_to_le16(ae.e_perm);
257                         mode &= ae.e_perm | ~S_IRWXO;
258                         break;
259                 case ACL_MASK:
260                         mask_obj = pa;
261                         not_equiv = 1;
262                         break;
263                 default:
264                         return -EIO;
265                 }
266         }
267
268         if (mask_obj) {
269                 ae.e_perm = le16_to_cpu(mask_obj->e_perm) &
270                             ((mode >> 3) | ~S_IRWXO);
271                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
272                 mask_obj->e_perm = cpu_to_le16(ae.e_perm);
273         } else {
274                 if (!group_obj)
275                         return -EIO;
276                 ae.e_perm = le16_to_cpu(group_obj->e_perm) &
277                             ((mode >> 3) | ~S_IRWXO);
278                 mode &= (ae.e_perm << 3) | ~S_IRWXG;
279                 group_obj->e_perm = cpu_to_le16(ae.e_perm);
280         }
281
282         *pmode = (*pmode & ~S_IRWXUGO) | mode;
283         return not_equiv;
284 }
285 EXPORT_SYMBOL(lustre_posix_acl_create_masq);
286 #endif