4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2012, 2013, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lustre/obdclass/acl.c
34 * Lustre Access Control List.
36 * Author: Fan Yong <fanyong@clusterfs.com>
39 #define DEBUG_SUBSYSTEM S_SEC
40 #include <lu_object.h>
41 #include <lustre_acl.h>
42 #include <obd_support.h>
43 #include <lustre_idmap.h>
44 #include <md_object.h>
45 #include "mdd_internal.h"
47 #ifdef CONFIG_LUSTRE_FS_POSIX_ACL
49 static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
50 posix_acl_xattr_entry *s)
52 d->e_tag = le16_to_cpu(s->e_tag);
53 d->e_perm = le16_to_cpu(s->e_perm);
54 d->e_id = le32_to_cpu(s->e_id);
58 static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
59 posix_acl_xattr_entry *s)
61 d->e_tag = cpu_to_le16(s->e_tag);
62 d->e_perm = cpu_to_le16(s->e_perm);
63 d->e_id = cpu_to_le32(s->e_id);
68 * Check permission based on POSIX ACL.
70 int lustre_posix_acl_permission(struct lu_ucred *mu, const struct lu_attr *la,
71 unsigned int may_mask,
72 posix_acl_xattr_entry *entry, int count)
74 posix_acl_xattr_entry *pa, *pe, *mask_obj;
75 posix_acl_xattr_entry ae, me;
82 /* There is implicit conversion between MAY_* modes and ACL_* modes.
83 * Don't bother explicitly converting them unless they actually change.
86 acl_want = (may_mask & MAY_READ ? ACL_READ : 0) |
87 (may_mask & MAY_WRITE ? ACL_WRITE : 0) |
88 (may_mask & MAY_EXEC ? ACL_EXECUTE : 0);
90 BUILD_BUG_ON(MAY_READ != ACL_READ);
91 BUILD_BUG_ON(MAY_WRITE != ACL_WRITE);
92 BUILD_BUG_ON(MAY_EXEC != ACL_EXECUTE);
97 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
98 lustre_posix_acl_le_to_cpu(&ae, pa);
101 /* (May have been checked already) */
102 if (la->la_uid == mu->uc_fsuid)
106 if (ae.e_id == mu->uc_fsuid)
110 if (lustre_in_group_p(mu, la->la_gid)) {
112 if ((ae.e_perm & acl_want) == acl_want)
117 if (lustre_in_group_p(mu, ae.e_id)) {
119 if ((ae.e_perm & acl_want) == acl_want)
136 for (mask_obj = pa + 1; mask_obj <= pe; mask_obj++) {
137 lustre_posix_acl_le_to_cpu(&me, mask_obj);
138 if (me.e_tag == ACL_MASK) {
139 if ((ae.e_perm & me.e_perm & acl_want) == acl_want)
147 if ((ae.e_perm & acl_want) == acl_want)
154 * Modify the ACL for the chmod.
156 int lustre_posix_acl_chmod_masq(posix_acl_xattr_entry *entry, u32 mode,
159 posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
161 /* There is implicit conversion between S_IRWX modes and ACL_* modes.
162 * Don't bother explicitly converting them unless they actually change.
164 BUILD_BUG_ON(S_IROTH != ACL_READ);
165 BUILD_BUG_ON(S_IWOTH != ACL_WRITE);
166 BUILD_BUG_ON(S_IXOTH != ACL_EXECUTE);
168 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
169 switch (le16_to_cpu(pa->e_tag)) {
171 pa->e_perm = cpu_to_le16((mode & S_IRWXU) >> 6);
183 pa->e_perm = cpu_to_le16(mode & S_IRWXO);
191 mask_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
195 group_obj->e_perm = cpu_to_le16((mode & S_IRWXG) >> 3);
202 * Returns 0 if the acl can be exactly represented in the traditional
203 * file mode permission bits, or else 1. Returns -E... on error.
206 lustre_posix_acl_equiv_mode(posix_acl_xattr_entry *entry, mode_t *mode_p,
209 posix_acl_xattr_entry *pa, *pe;
213 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
214 __u16 perm = le16_to_cpu(pa->e_perm);
215 switch (le16_to_cpu(pa->e_tag)) {
217 mode |= (perm & S_IRWXO) << 6;
220 mode |= (perm & S_IRWXO) << 3;
223 mode |= perm & S_IRWXO;
226 mode = (mode & ~S_IRWXG) |
227 ((perm & S_IRWXO) << 3);
239 *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
244 * Modify acl when creating a new object.
246 int lustre_posix_acl_create_masq(posix_acl_xattr_entry *entry, u32 *pmode,
249 posix_acl_xattr_entry *group_obj = NULL, *mask_obj = NULL, *pa, *pe;
250 posix_acl_xattr_entry ae;
254 for (pa = &entry[0], pe = &entry[count - 1]; pa <= pe; pa++) {
255 lustre_posix_acl_le_to_cpu(&ae, pa);
258 ae.e_perm &= (mode >> 6) | ~(0007);
259 pa->e_perm = cpu_to_le16(ae.e_perm);
260 mode &= (ae.e_perm << 6) | ~S_IRWXU;
270 ae.e_perm &= mode | ~(0007);
271 pa->e_perm = cpu_to_le16(ae.e_perm);
272 mode &= ae.e_perm | ~(0007);
284 ae.e_perm = le16_to_cpu(mask_obj->e_perm) &
285 ((mode >> 3) | ~(0007));
286 mode &= (ae.e_perm << 3) | ~S_IRWXG;
287 mask_obj->e_perm = cpu_to_le16(ae.e_perm);
291 ae.e_perm = le16_to_cpu(group_obj->e_perm) &
292 ((mode >> 3) | ~(0007));
293 mode &= (ae.e_perm << 3) | ~S_IRWXG;
294 group_obj->e_perm = cpu_to_le16(ae.e_perm);
297 *pmode = (*pmode & ~S_IRWXUGO) | mode;