1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004, 2005 Cluster File Systems, Inc.
6 * Author: Lai Siyao <lsy@clusterfs.com>
8 * This file is part of Lustre, http://www.lustre.org.
10 * Lustre is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
14 * Lustre is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Lustre; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DEBUG_SUBSYSTEM S_FILTER
27 #include <linux/version.h>
28 #include <asm/uaccess.h>
29 #include <linux/file.h>
30 #include <linux/kmod.h>
32 #include <linux/lustre_fsfilt.h>
33 #include <linux/lustre_sec.h>
35 #include "filter_internal.h"
39 * keep this as simple as possible. we suppose the blacklist usually
40 * be empry or very short (<5), since long term blacklist should be
41 * done on MDS side. A more sophisticated blacklist will be implemented
44 * note blacklist didn't take effect when OSS capability disabled. this
45 * looks reasonable to me.
47 #define BLACKLIST_MAX (32)
48 static int nblacklist = 0;
49 static uid_t blacklist[BLACKLIST_MAX];
50 static spinlock_t blacklist_lock = SPIN_LOCK_UNLOCKED;
52 int blacklist_display(char *buf, int bufsize)
59 spin_lock(&blacklist_lock);
60 for (i = 0; i < nblacklist; i++) {
61 snprintf(one, 16, "%u\n", blacklist[i]);
62 strncat(buf, one, bufsize);
64 spin_unlock(&blacklist_lock);
65 return strnlen(buf, bufsize);
68 void blacklist_add(uid_t uid)
72 spin_lock(&blacklist_lock);
73 if (nblacklist == BLACKLIST_MAX) {
74 CERROR("can't add more in blacklist\n");
75 spin_unlock(&blacklist_lock);
79 for (i = 0; i < nblacklist; i++) {
80 if (blacklist[i] == uid) {
81 spin_unlock(&blacklist_lock);
86 blacklist[nblacklist++] = uid;
87 spin_unlock(&blacklist_lock);
90 void blacklist_del(uid_t uid)
94 spin_lock(&blacklist_lock);
95 for (i = 0; i < nblacklist; i++) {
96 if (blacklist[i] == uid) {
98 while (i < nblacklist) {
99 blacklist[i] = blacklist[i+1];
102 spin_unlock(&blacklist_lock);
106 spin_unlock(&blacklist_lock);
109 int blacklist_check(uid_t uid)
113 spin_lock(&blacklist_lock);
114 for (i = 0; i < nblacklist; i++) {
115 if (blacklist[i] == uid) {
120 spin_unlock(&blacklist_lock);
125 void filter_free_capa_keys(struct filter_obd *filter)
127 struct filter_capa_key *key, *n;
129 spin_lock(&filter->fo_capa_lock);
130 list_for_each_entry_safe(key, n, &filter->fo_capa_keys, k_list) {
131 list_del_init(&key->k_list);
132 OBD_FREE(key, sizeof(*key));
134 spin_unlock(&filter->fo_capa_lock);
137 int filter_update_capa_key(struct obd_device *obd, struct lustre_capa_key *key)
139 struct filter_obd *filter = &obd->u.filter;
140 struct filter_capa_key *tmp = NULL, *rkey = NULL, *bkey = NULL;
144 spin_lock(&filter->fo_capa_lock);
145 list_for_each_entry(tmp, &filter->fo_capa_keys, k_list) {
146 if (tmp->k_key.lk_mdsid != le32_to_cpu(key->lk_mdsid))
154 spin_unlock(&filter->fo_capa_lock);
156 if (rkey && bkey && capa_key_cmp(&rkey->k_key, &bkey->k_key) < 0) {
165 DEBUG_CAPA_KEY(D_INFO, &tmp->k_key, "filter update");
167 OBD_ALLOC(tmp, sizeof(*tmp));
169 GOTO(out, rc = -ENOMEM);
171 DEBUG_CAPA_KEY(D_INFO, &tmp->k_key, "filter new");
174 /* fields in lustre_capa_key are in cpu order */
175 spin_lock(&filter->fo_capa_lock);
176 tmp->k_key.lk_mdsid = le32_to_cpu(key->lk_mdsid);
177 tmp->k_key.lk_keyid = le32_to_cpu(key->lk_keyid);
178 tmp->k_key.lk_expiry = le64_to_cpu(key->lk_expiry);
179 memcpy(&tmp->k_key.lk_key, key->lk_key, sizeof(key->lk_key));
182 list_add_tail(&tmp->k_list, &filter->fo_capa_keys);
183 spin_unlock(&filter->fo_capa_lock);
188 int filter_verify_fid(struct obd_export *exp, struct inode *inode,
189 struct lustre_capa *capa)
191 struct lustre_id fid;
198 rc = fsfilt_get_md(exp->exp_obd, inode, &fid, sizeof(fid), EA_SID);
200 CERROR("get fid from object failed! rc:%d\n", rc);
203 if (capa->lc_mdsid != id_group(&fid) ||
204 capa->lc_ino != id_ino(&fid))
212 filter_verify_capa(int cmd, struct obd_export *exp, struct lustre_capa *capa)
214 struct obd_device *obd = exp->exp_obd;
215 struct filter_obd *filter = &obd->u.filter;
216 struct obd_capa *ocapa;
217 struct lustre_capa tcapa;
218 struct filter_capa_key *rkey = NULL, *bkey = NULL, *tmp;
219 __u8 hmac_key[CAPA_KEY_LEN];
222 /* capability is disabled */
223 if (filter->fo_capa_stat == 0)
230 if (blacklist_check(capa->lc_uid))
233 if (cmd == OBD_BRW_WRITE && !(capa->lc_op & (CAPA_WRITE | CAPA_TRUNC)))
235 if (cmd == OBD_BRW_READ && !(capa->lc_op & (CAPA_WRITE | CAPA_READ)))
238 if (OBD_FAIL_CHECK(OBD_FAIL_FILTER_VERIFY_CAPA))
241 if (capa_expired(capa)) {
242 DEBUG_CAPA(D_INFO, capa, "expired");
246 ocapa = capa_get(capa->lc_uid, capa->lc_op, capa->lc_mdsid,
247 capa->lc_ino, FILTER_CAPA);
250 /* fo_capa_lock protects capa too */
251 spin_lock(&filter->fo_capa_lock);
252 if (capa->lc_keyid == ocapa->c_capa.lc_keyid) {
253 rc = memcmp(capa, &ocapa->c_capa, sizeof(*capa));
254 } else if (ocapa->c_bvalid &&
255 capa->lc_keyid == ocapa->c_bkeyid) {
256 rc = memcmp(capa->lc_hmac, ocapa->c_bhmac,
257 sizeof(capa->lc_hmac));
259 /* ocapa is obsolete too */
264 if (rc && __capa_is_to_expire(ocapa)) {
265 /* client should use new expiry now */
269 spin_unlock(&filter->fo_capa_lock);
272 RETURN(rc ? -EACCES : 0);
275 spin_lock(&filter->fo_capa_lock);
277 list_for_each_entry(tmp, &filter->fo_capa_keys, k_list) {
278 if (tmp->k_key.lk_mdsid == capa->lc_mdsid) {
286 if (rkey && bkey && capa_key_cmp(&rkey->k_key, &bkey->k_key) < 0) {
292 if ((!rkey || rkey->k_key.lk_keyid != capa->lc_keyid) &&
293 (!bkey || bkey->k_key.lk_keyid != capa->lc_keyid)) {
294 spin_unlock(&filter->fo_capa_lock);
295 GOTO(out, rc = -ESTALE);
300 memcpy(&tcapa, capa, sizeof(tcapa));
301 tcapa.lc_keyid = rkey->k_key.lk_keyid;
302 memcpy(hmac_key, rkey->k_key.lk_key, sizeof(hmac_key));
303 spin_unlock(&filter->fo_capa_lock);
305 capa_hmac(filter->fo_capa_hmac, hmac_key, &tcapa);
307 /* store in capa cache */
308 ocapa = capa_renew(capa, FILTER_CAPA);
310 GOTO(out, rc = -ENOMEM);
313 spin_lock(&filter->fo_capa_lock);
314 tcapa.lc_keyid = bkey->k_key.lk_keyid;
315 memcpy(hmac_key, bkey->k_key.lk_key, sizeof(hmac_key));
316 ocapa->c_bkeyid = bkey->k_key.lk_keyid;
317 spin_unlock(&filter->fo_capa_lock);
319 capa_hmac(filter->fo_capa_hmac, bkey->k_key.lk_key, &tcapa);
321 spin_lock(&filter->fo_capa_lock);
322 memcpy(ocapa->c_bhmac, tcapa.lc_hmac, sizeof(ocapa->c_bhmac));
324 spin_unlock(&filter->fo_capa_lock);