sec_null.c revision d7e09d0397e84eefbabfd9cb353221f3c6448d83
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) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 28 * Use is subject to license terms. 29 * 30 * Copyright (c) 2011, 2012, 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/ptlrpc/sec_null.c 37 * 38 * Author: Eric Mei <ericm@clusterfs.com> 39 */ 40 41#define DEBUG_SUBSYSTEM S_SEC 42 43 44#include <obd_support.h> 45#include <obd_cksum.h> 46#include <obd_class.h> 47#include <lustre_net.h> 48#include <lustre_sec.h> 49 50static struct ptlrpc_sec_policy null_policy; 51static struct ptlrpc_sec null_sec; 52static struct ptlrpc_cli_ctx null_cli_ctx; 53static struct ptlrpc_svc_ctx null_svc_ctx; 54 55/* 56 * we can temporarily use the topmost 8-bits of lm_secflvr to identify 57 * the source sec part. 58 */ 59static inline 60void null_encode_sec_part(struct lustre_msg *msg, enum lustre_sec_part sp) 61{ 62 msg->lm_secflvr |= (((__u32) sp) & 0xFF) << 24; 63} 64 65static inline 66enum lustre_sec_part null_decode_sec_part(struct lustre_msg *msg) 67{ 68 return (msg->lm_secflvr >> 24) & 0xFF; 69} 70 71static int null_ctx_refresh(struct ptlrpc_cli_ctx *ctx) 72{ 73 /* should never reach here */ 74 LBUG(); 75 return 0; 76} 77 78static 79int null_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) 80{ 81 req->rq_reqbuf->lm_secflvr = SPTLRPC_FLVR_NULL; 82 83 if (!req->rq_import->imp_dlm_fake) { 84 struct obd_device *obd = req->rq_import->imp_obd; 85 null_encode_sec_part(req->rq_reqbuf, 86 obd->u.cli.cl_sp_me); 87 } 88 req->rq_reqdata_len = req->rq_reqlen; 89 return 0; 90} 91 92static 93int null_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) 94{ 95 __u32 cksums, cksumc; 96 97 LASSERT(req->rq_repdata); 98 99 req->rq_repmsg = req->rq_repdata; 100 req->rq_replen = req->rq_repdata_len; 101 102 if (req->rq_early) { 103 cksums = lustre_msg_get_cksum(req->rq_repdata); 104#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 50, 0) 105 if (lustre_msghdr_get_flags(req->rq_reqmsg) & 106 MSGHDR_CKSUM_INCOMPAT18) 107 cksumc = lustre_msg_calc_cksum(req->rq_repmsg, 0); 108 else 109 cksumc = lustre_msg_calc_cksum(req->rq_repmsg, 1); 110#else 111# warning "remove checksum compatibility support for b1_8" 112 cksumc = lustre_msg_calc_cksum(req->rq_repmsg); 113#endif 114 if (cksumc != cksums) { 115 CDEBUG(D_SEC, 116 "early reply checksum mismatch: %08x != %08x\n", 117 cksumc, cksums); 118 return -EINVAL; 119 } 120 } 121 122 return 0; 123} 124 125static 126struct ptlrpc_sec *null_create_sec(struct obd_import *imp, 127 struct ptlrpc_svc_ctx *svc_ctx, 128 struct sptlrpc_flavor *sf) 129{ 130 LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_NULL); 131 132 /* general layer has take a module reference for us, because we never 133 * really destroy the sec, simply release the reference here. 134 */ 135 sptlrpc_policy_put(&null_policy); 136 return &null_sec; 137} 138 139static 140void null_destroy_sec(struct ptlrpc_sec *sec) 141{ 142 LASSERT(sec == &null_sec); 143} 144 145static 146struct ptlrpc_cli_ctx *null_lookup_ctx(struct ptlrpc_sec *sec, 147 struct vfs_cred *vcred, 148 int create, int remove_dead) 149{ 150 atomic_inc(&null_cli_ctx.cc_refcount); 151 return &null_cli_ctx; 152} 153 154static 155int null_flush_ctx_cache(struct ptlrpc_sec *sec, 156 uid_t uid, 157 int grace, int force) 158{ 159 return 0; 160} 161 162static 163int null_alloc_reqbuf(struct ptlrpc_sec *sec, 164 struct ptlrpc_request *req, 165 int msgsize) 166{ 167 if (!req->rq_reqbuf) { 168 int alloc_size = size_roundup_power2(msgsize); 169 170 LASSERT(!req->rq_pool); 171 OBD_ALLOC_LARGE(req->rq_reqbuf, alloc_size); 172 if (!req->rq_reqbuf) 173 return -ENOMEM; 174 175 req->rq_reqbuf_len = alloc_size; 176 } else { 177 LASSERT(req->rq_pool); 178 LASSERT(req->rq_reqbuf_len >= msgsize); 179 memset(req->rq_reqbuf, 0, msgsize); 180 } 181 182 req->rq_reqmsg = req->rq_reqbuf; 183 return 0; 184} 185 186static 187void null_free_reqbuf(struct ptlrpc_sec *sec, 188 struct ptlrpc_request *req) 189{ 190 if (!req->rq_pool) { 191 LASSERTF(req->rq_reqmsg == req->rq_reqbuf, 192 "req %p: reqmsg %p is not reqbuf %p in null sec\n", 193 req, req->rq_reqmsg, req->rq_reqbuf); 194 LASSERTF(req->rq_reqbuf_len >= req->rq_reqlen, 195 "req %p: reqlen %d should smaller than buflen %d\n", 196 req, req->rq_reqlen, req->rq_reqbuf_len); 197 198 OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); 199 req->rq_reqbuf = NULL; 200 req->rq_reqbuf_len = 0; 201 } 202} 203 204static 205int null_alloc_repbuf(struct ptlrpc_sec *sec, 206 struct ptlrpc_request *req, 207 int msgsize) 208{ 209 /* add space for early replied */ 210 msgsize += lustre_msg_early_size(); 211 212 msgsize = size_roundup_power2(msgsize); 213 214 OBD_ALLOC_LARGE(req->rq_repbuf, msgsize); 215 if (!req->rq_repbuf) 216 return -ENOMEM; 217 218 req->rq_repbuf_len = msgsize; 219 return 0; 220} 221 222static 223void null_free_repbuf(struct ptlrpc_sec *sec, 224 struct ptlrpc_request *req) 225{ 226 LASSERT(req->rq_repbuf); 227 228 OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len); 229 req->rq_repbuf = NULL; 230 req->rq_repbuf_len = 0; 231} 232 233static 234int null_enlarge_reqbuf(struct ptlrpc_sec *sec, 235 struct ptlrpc_request *req, 236 int segment, int newsize) 237{ 238 struct lustre_msg *newbuf; 239 struct lustre_msg *oldbuf = req->rq_reqmsg; 240 int oldsize, newmsg_size, alloc_size; 241 242 LASSERT(req->rq_reqbuf); 243 LASSERT(req->rq_reqbuf == req->rq_reqmsg); 244 LASSERT(req->rq_reqbuf_len >= req->rq_reqlen); 245 LASSERT(req->rq_reqlen == lustre_packed_msg_size(oldbuf)); 246 247 /* compute new message size */ 248 oldsize = req->rq_reqbuf->lm_buflens[segment]; 249 req->rq_reqbuf->lm_buflens[segment] = newsize; 250 newmsg_size = lustre_packed_msg_size(oldbuf); 251 req->rq_reqbuf->lm_buflens[segment] = oldsize; 252 253 /* request from pool should always have enough buffer */ 254 LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newmsg_size); 255 256 if (req->rq_reqbuf_len < newmsg_size) { 257 alloc_size = size_roundup_power2(newmsg_size); 258 259 OBD_ALLOC_LARGE(newbuf, alloc_size); 260 if (newbuf == NULL) 261 return -ENOMEM; 262 263 memcpy(newbuf, req->rq_reqbuf, req->rq_reqlen); 264 265 OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); 266 req->rq_reqbuf = req->rq_reqmsg = newbuf; 267 req->rq_reqbuf_len = alloc_size; 268 } 269 270 _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize); 271 req->rq_reqlen = newmsg_size; 272 273 return 0; 274} 275 276static struct ptlrpc_svc_ctx null_svc_ctx = { 277 .sc_refcount = ATOMIC_INIT(1), 278 .sc_policy = &null_policy, 279}; 280 281static 282int null_accept(struct ptlrpc_request *req) 283{ 284 LASSERT(SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) == 285 SPTLRPC_POLICY_NULL); 286 287 if (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_NULL) { 288 CERROR("Invalid rpc flavor 0x%x\n", req->rq_flvr.sf_rpc); 289 return SECSVC_DROP; 290 } 291 292 req->rq_sp_from = null_decode_sec_part(req->rq_reqbuf); 293 294 req->rq_reqmsg = req->rq_reqbuf; 295 req->rq_reqlen = req->rq_reqdata_len; 296 297 req->rq_svc_ctx = &null_svc_ctx; 298 atomic_inc(&req->rq_svc_ctx->sc_refcount); 299 300 return SECSVC_OK; 301} 302 303static 304int null_alloc_rs(struct ptlrpc_request *req, int msgsize) 305{ 306 struct ptlrpc_reply_state *rs; 307 int rs_size = sizeof(*rs) + msgsize; 308 309 LASSERT(msgsize % 8 == 0); 310 311 rs = req->rq_reply_state; 312 313 if (rs) { 314 /* pre-allocated */ 315 LASSERT(rs->rs_size >= rs_size); 316 } else { 317 OBD_ALLOC_LARGE(rs, rs_size); 318 if (rs == NULL) 319 return -ENOMEM; 320 321 rs->rs_size = rs_size; 322 } 323 324 rs->rs_svc_ctx = req->rq_svc_ctx; 325 atomic_inc(&req->rq_svc_ctx->sc_refcount); 326 327 rs->rs_repbuf = (struct lustre_msg *) (rs + 1); 328 rs->rs_repbuf_len = rs_size - sizeof(*rs); 329 rs->rs_msg = rs->rs_repbuf; 330 331 req->rq_reply_state = rs; 332 return 0; 333} 334 335static 336void null_free_rs(struct ptlrpc_reply_state *rs) 337{ 338 LASSERT_ATOMIC_GT(&rs->rs_svc_ctx->sc_refcount, 1); 339 atomic_dec(&rs->rs_svc_ctx->sc_refcount); 340 341 if (!rs->rs_prealloc) 342 OBD_FREE_LARGE(rs, rs->rs_size); 343} 344 345static 346int null_authorize(struct ptlrpc_request *req) 347{ 348 struct ptlrpc_reply_state *rs = req->rq_reply_state; 349 350 LASSERT(rs); 351 352 rs->rs_repbuf->lm_secflvr = SPTLRPC_FLVR_NULL; 353 rs->rs_repdata_len = req->rq_replen; 354 355 if (likely(req->rq_packed_final)) { 356 if (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT) 357 req->rq_reply_off = lustre_msg_early_size(); 358 else 359 req->rq_reply_off = 0; 360 } else { 361 __u32 cksum; 362 363#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 7, 50, 0) 364 if (lustre_msghdr_get_flags(req->rq_reqmsg) & 365 MSGHDR_CKSUM_INCOMPAT18) 366 cksum = lustre_msg_calc_cksum(rs->rs_repbuf, 0); 367 else 368 cksum = lustre_msg_calc_cksum(rs->rs_repbuf, 1); 369#else 370# warning "remove checksum compatibility support for b1_8" 371 cksum = lustre_msg_calc_cksum(rs->rs_repbuf); 372#endif 373 lustre_msg_set_cksum(rs->rs_repbuf, cksum); 374 req->rq_reply_off = 0; 375 } 376 377 return 0; 378} 379 380static struct ptlrpc_ctx_ops null_ctx_ops = { 381 .refresh = null_ctx_refresh, 382 .sign = null_ctx_sign, 383 .verify = null_ctx_verify, 384}; 385 386static struct ptlrpc_sec_cops null_sec_cops = { 387 .create_sec = null_create_sec, 388 .destroy_sec = null_destroy_sec, 389 .lookup_ctx = null_lookup_ctx, 390 .flush_ctx_cache = null_flush_ctx_cache, 391 .alloc_reqbuf = null_alloc_reqbuf, 392 .alloc_repbuf = null_alloc_repbuf, 393 .free_reqbuf = null_free_reqbuf, 394 .free_repbuf = null_free_repbuf, 395 .enlarge_reqbuf = null_enlarge_reqbuf, 396}; 397 398static struct ptlrpc_sec_sops null_sec_sops = { 399 .accept = null_accept, 400 .alloc_rs = null_alloc_rs, 401 .authorize = null_authorize, 402 .free_rs = null_free_rs, 403}; 404 405static struct ptlrpc_sec_policy null_policy = { 406 .sp_owner = THIS_MODULE, 407 .sp_name = "sec.null", 408 .sp_policy = SPTLRPC_POLICY_NULL, 409 .sp_cops = &null_sec_cops, 410 .sp_sops = &null_sec_sops, 411}; 412 413static void null_init_internal(void) 414{ 415 static HLIST_HEAD(__list); 416 417 null_sec.ps_policy = &null_policy; 418 atomic_set(&null_sec.ps_refcount, 1); /* always busy */ 419 null_sec.ps_id = -1; 420 null_sec.ps_import = NULL; 421 null_sec.ps_flvr.sf_rpc = SPTLRPC_FLVR_NULL; 422 null_sec.ps_flvr.sf_flags = 0; 423 null_sec.ps_part = LUSTRE_SP_ANY; 424 null_sec.ps_dying = 0; 425 spin_lock_init(&null_sec.ps_lock); 426 atomic_set(&null_sec.ps_nctx, 1); /* for "null_cli_ctx" */ 427 INIT_LIST_HEAD(&null_sec.ps_gc_list); 428 null_sec.ps_gc_interval = 0; 429 null_sec.ps_gc_next = 0; 430 431 hlist_add_head(&null_cli_ctx.cc_cache, &__list); 432 atomic_set(&null_cli_ctx.cc_refcount, 1); /* for hash */ 433 null_cli_ctx.cc_sec = &null_sec; 434 null_cli_ctx.cc_ops = &null_ctx_ops; 435 null_cli_ctx.cc_expire = 0; 436 null_cli_ctx.cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_ETERNAL | 437 PTLRPC_CTX_UPTODATE; 438 null_cli_ctx.cc_vcred.vc_uid = 0; 439 spin_lock_init(&null_cli_ctx.cc_lock); 440 INIT_LIST_HEAD(&null_cli_ctx.cc_req_list); 441 INIT_LIST_HEAD(&null_cli_ctx.cc_gc_chain); 442} 443 444int sptlrpc_null_init(void) 445{ 446 int rc; 447 448 null_init_internal(); 449 450 rc = sptlrpc_register_policy(&null_policy); 451 if (rc) 452 CERROR("failed to register %s: %d\n", null_policy.sp_name, rc); 453 454 return rc; 455} 456 457void sptlrpc_null_fini(void) 458{ 459 int rc; 460 461 rc = sptlrpc_unregister_policy(&null_policy); 462 if (rc) 463 CERROR("failed to unregister %s: %d\n", null_policy.sp_name,rc); 464} 465