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.sun.com/software/products/lustre/docs/GPLv2.pdf
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
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/llite/remote_perm.c
38 * Lustre Permission Cache for Remote Client
40 * Author: Lai Siyao <lsy@clusterfs.com>
41 * Author: Fan Yong <fanyong@clusterfs.com>
44 #define DEBUG_SUBSYSTEM S_LLITE
46 #include <linux/module.h>
47 #include <linux/types.h>
49 #include "../include/lustre_lite.h"
50 #include "../include/lustre_ha.h"
51 #include "../include/lustre_dlm.h"
52 #include "../include/lprocfs_status.h"
53 #include "../include/lustre_disk.h"
54 #include "../include/lustre_param.h"
55 #include "llite_internal.h"
57 struct kmem_cache
*ll_remote_perm_cachep
= NULL
;
58 struct kmem_cache
*ll_rmtperm_hash_cachep
= NULL
;
60 static inline struct ll_remote_perm
*alloc_ll_remote_perm(void)
62 struct ll_remote_perm
*lrp
;
64 OBD_SLAB_ALLOC_PTR_GFP(lrp
, ll_remote_perm_cachep
, GFP_KERNEL
);
66 INIT_HLIST_NODE(&lrp
->lrp_list
);
70 static inline void free_ll_remote_perm(struct ll_remote_perm
*lrp
)
75 if (!hlist_unhashed(&lrp
->lrp_list
))
76 hlist_del(&lrp
->lrp_list
);
77 OBD_SLAB_FREE(lrp
, ll_remote_perm_cachep
, sizeof(*lrp
));
80 static struct hlist_head
*alloc_rmtperm_hash(void)
82 struct hlist_head
*hash
;
85 OBD_SLAB_ALLOC_GFP(hash
, ll_rmtperm_hash_cachep
,
86 REMOTE_PERM_HASHSIZE
* sizeof(*hash
),
91 for (i
= 0; i
< REMOTE_PERM_HASHSIZE
; i
++)
92 INIT_HLIST_HEAD(hash
+ i
);
97 void free_rmtperm_hash(struct hlist_head
*hash
)
100 struct ll_remote_perm
*lrp
;
101 struct hlist_node
*next
;
106 for (i
= 0; i
< REMOTE_PERM_HASHSIZE
; i
++)
107 hlist_for_each_entry_safe(lrp
, next
, hash
+ i
,
109 free_ll_remote_perm(lrp
);
110 OBD_SLAB_FREE(hash
, ll_rmtperm_hash_cachep
,
111 REMOTE_PERM_HASHSIZE
* sizeof(*hash
));
114 static inline int remote_perm_hashfunc(uid_t uid
)
116 return uid
& (REMOTE_PERM_HASHSIZE
- 1);
119 /* NB: setxid permission is not checked here, instead it's done on
120 * MDT when client get remote permission. */
121 static int do_check_remote_perm(struct ll_inode_info
*lli
, int mask
)
123 struct hlist_head
*head
;
124 struct ll_remote_perm
*lrp
;
127 if (!lli
->lli_remote_perms
)
130 head
= lli
->lli_remote_perms
+
131 remote_perm_hashfunc(from_kuid(&init_user_ns
, current_uid()));
133 spin_lock(&lli
->lli_lock
);
134 hlist_for_each_entry(lrp
, head
, lrp_list
) {
135 if (lrp
->lrp_uid
!= from_kuid(&init_user_ns
, current_uid()))
137 if (lrp
->lrp_gid
!= from_kgid(&init_user_ns
, current_gid()))
139 if (lrp
->lrp_fsuid
!= from_kuid(&init_user_ns
, current_fsuid()))
141 if (lrp
->lrp_fsgid
!= from_kgid(&init_user_ns
, current_fsgid()))
148 GOTO(out
, rc
= -ENOENT
);
150 CDEBUG(D_SEC
, "found remote perm: %u/%u/%u/%u - %#x\n",
151 lrp
->lrp_uid
, lrp
->lrp_gid
, lrp
->lrp_fsuid
, lrp
->lrp_fsgid
,
152 lrp
->lrp_access_perm
);
153 rc
= ((lrp
->lrp_access_perm
& mask
) == mask
) ? 0 : -EACCES
;
156 spin_unlock(&lli
->lli_lock
);
160 int ll_update_remote_perm(struct inode
*inode
, struct mdt_remote_perm
*perm
)
162 struct ll_inode_info
*lli
= ll_i2info(inode
);
163 struct ll_remote_perm
*lrp
= NULL
, *tmp
= NULL
;
164 struct hlist_head
*head
, *perm_hash
= NULL
;
166 LASSERT(ll_i2sbi(inode
)->ll_flags
& LL_SBI_RMT_CLIENT
);
169 if (perm
->rp_uid
!= current
->uid
||
170 perm
->rp_gid
!= current
->gid
||
171 perm
->rp_fsuid
!= current
->fsuid
||
172 perm
->rp_fsgid
!= current
->fsgid
) {
173 /* user might setxid in this small period */
175 "remote perm user %u/%u/%u/%u != current %u/%u/%u/%u\n",
176 perm
->rp_uid
, perm
->rp_gid
, perm
->rp_fsuid
,
177 perm
->rp_fsgid
, current
->uid
, current
->gid
,
178 current
->fsuid
, current
->fsgid
);
183 if (!lli
->lli_remote_perms
) {
184 perm_hash
= alloc_rmtperm_hash();
185 if (perm_hash
== NULL
) {
186 CERROR("alloc lli_remote_perms failed!\n");
191 spin_lock(&lli
->lli_lock
);
193 if (!lli
->lli_remote_perms
)
194 lli
->lli_remote_perms
= perm_hash
;
196 free_rmtperm_hash(perm_hash
);
198 head
= lli
->lli_remote_perms
+ remote_perm_hashfunc(perm
->rp_uid
);
201 hlist_for_each_entry(tmp
, head
, lrp_list
) {
202 if (tmp
->lrp_uid
!= perm
->rp_uid
)
204 if (tmp
->lrp_gid
!= perm
->rp_gid
)
206 if (tmp
->lrp_fsuid
!= perm
->rp_fsuid
)
208 if (tmp
->lrp_fsgid
!= perm
->rp_fsgid
)
211 free_ll_remote_perm(lrp
);
217 spin_unlock(&lli
->lli_lock
);
218 lrp
= alloc_ll_remote_perm();
220 CERROR("alloc memory for ll_remote_perm failed!\n");
223 spin_lock(&lli
->lli_lock
);
227 lrp
->lrp_access_perm
= perm
->rp_access_perm
;
229 lrp
->lrp_uid
= perm
->rp_uid
;
230 lrp
->lrp_gid
= perm
->rp_gid
;
231 lrp
->lrp_fsuid
= perm
->rp_fsuid
;
232 lrp
->lrp_fsgid
= perm
->rp_fsgid
;
233 hlist_add_head(&lrp
->lrp_list
, head
);
235 lli
->lli_rmtperm_time
= cfs_time_current();
236 spin_unlock(&lli
->lli_lock
);
238 CDEBUG(D_SEC
, "new remote perm@%p: %u/%u/%u/%u - %#x\n",
239 lrp
, lrp
->lrp_uid
, lrp
->lrp_gid
, lrp
->lrp_fsuid
, lrp
->lrp_fsgid
,
240 lrp
->lrp_access_perm
);
245 int lustre_check_remote_perm(struct inode
*inode
, int mask
)
247 struct ll_inode_info
*lli
= ll_i2info(inode
);
248 struct ll_sb_info
*sbi
= ll_i2sbi(inode
);
249 struct ptlrpc_request
*req
= NULL
;
250 struct mdt_remote_perm
*perm
;
256 save
= lli
->lli_rmtperm_time
;
257 rc
= do_check_remote_perm(lli
, mask
);
258 if (!rc
|| (rc
!= -ENOENT
&& i
))
263 mutex_lock(&lli
->lli_rmtperm_mutex
);
265 if (save
!= lli
->lli_rmtperm_time
) {
266 rc
= do_check_remote_perm(lli
, mask
);
267 if (!rc
|| (rc
!= -ENOENT
&& i
)) {
268 mutex_unlock(&lli
->lli_rmtperm_mutex
);
274 CERROR("check remote perm falls in dead loop!\n");
278 oc
= ll_mdscapa_get(inode
);
279 rc
= md_get_remote_perm(sbi
->ll_md_exp
, ll_inode2fid(inode
), oc
,
280 ll_i2suppgid(inode
), &req
);
283 mutex_unlock(&lli
->lli_rmtperm_mutex
);
287 perm
= req_capsule_server_swab_get(&req
->rq_pill
, &RMF_ACL
,
288 lustre_swab_mdt_remote_perm
);
289 if (unlikely(perm
== NULL
)) {
290 mutex_unlock(&lli
->lli_rmtperm_mutex
);
295 rc
= ll_update_remote_perm(inode
, perm
);
296 mutex_unlock(&lli
->lli_rmtperm_mutex
);
300 ptlrpc_req_finished(req
);
303 ptlrpc_req_finished(req
);
307 #if 0 /* NB: remote perms can't be freed in ll_mdc_blocking_ast of UPDATE lock,
308 * because it will fail sanity test 48.
310 void ll_free_remote_perms(struct inode
*inode
)
312 struct ll_inode_info
*lli
= ll_i2info(inode
);
313 struct hlist_head
*hash
= lli
->lli_remote_perms
;
314 struct ll_remote_perm
*lrp
;
315 struct hlist_node
*node
, *next
;
320 spin_lock(&lli
->lli_lock
);
322 for (i
= 0; i
< REMOTE_PERM_HASHSIZE
; i
++) {
323 hlist_for_each_entry_safe(lrp
, node
, next
, hash
+ i
,
325 free_ll_remote_perm(lrp
);
328 spin_unlock(&lli
->lli_lock
);