1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2006 Cluster File Systems, Inc.
6 * This file is part of the Lustre file system, http://www.lustre.org
7 * Lustre is a trademark of Cluster File Systems, Inc.
9 * You may have signed or agreed to another license before downloading
10 * this software. If so, you are bound by the terms and conditions
11 * of that agreement, and the following does not apply to you. See the
12 * LICENSE file included with this distribution for more information.
14 * If you did not agree to a different license, then this copy of Lustre
15 * is open source software; you can redistribute it and/or modify it
16 * under the terms of version 2 of the GNU General Public License as
17 * published by the Free Software Foundation.
19 * In either case, Lustre is distributed in the hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * license text for more details.
27 # define EXPORT_SYMTAB
29 #define DEBUG_SUBSYSTEM S_SEC
31 #include <linux/init.h>
32 #include <linux/module.h>
33 #include <linux/slab.h>
34 #include <linux/dcache.h>
36 #include <linux/random.h>
39 #include <linux/sunrpc/rpc_pipe_fs.h>
41 #include <liblustre.h>
45 #include <obd_class.h>
46 #include <obd_support.h>
47 #include <lustre/lustre_idl.h>
48 #include <lustre_net.h>
49 #include <lustre_import.h>
50 #include <lustre_sec.h>
53 #include "gss_internal.h"
56 #define LUSTRE_PIPE_ROOT "/lustre"
57 #define LUSTRE_PIPE_KRB5 LUSTRE_PIPE_ROOT"/krb5"
59 struct gss_upcall_msg_data {
63 __u32 gum_svc; /* MDS/OSS... */
64 __u64 gum_nid; /* peer NID */
65 __u8 gum_obd[64]; /* client obd name */
68 struct gss_upcall_msg {
69 struct rpc_pipe_msg gum_base;
70 atomic_t gum_refcount;
71 struct list_head gum_list;
73 struct gss_sec *gum_gsec;
74 struct gss_cli_ctx *gum_gctx;
75 struct gss_upcall_msg_data gum_data;
78 static atomic_t upcall_seq = ATOMIC_INIT(0);
81 __u32 upcall_get_sequence(void)
83 return (__u32) atomic_inc_return(&upcall_seq);
92 __u32 mech_name2idx(const char *name)
94 LASSERT(!strcmp(name, "krb5"));
98 /* pipefs dentries for each mechanisms */
99 static struct dentry *de_pipes[MECH_MAX] = { NULL, };
100 /* all upcall messgaes linked here */
101 static struct list_head upcall_lists[MECH_MAX];
102 /* and protected by this */
103 static spinlock_t upcall_locks[MECH_MAX];
106 void upcall_list_lock(int idx)
108 spin_lock(&upcall_locks[idx]);
112 void upcall_list_unlock(int idx)
114 spin_unlock(&upcall_locks[idx]);
118 void upcall_msg_enlist(struct gss_upcall_msg *msg)
120 __u32 idx = msg->gum_mechidx;
122 upcall_list_lock(idx);
123 list_add(&msg->gum_list, &upcall_lists[idx]);
124 upcall_list_unlock(idx);
128 void upcall_msg_delist(struct gss_upcall_msg *msg)
130 __u32 idx = msg->gum_mechidx;
132 upcall_list_lock(idx);
133 list_del_init(&msg->gum_list);
134 upcall_list_unlock(idx);
137 /**********************************************
138 * rpc_pipe upcall helpers *
139 **********************************************/
141 void gss_release_msg(struct gss_upcall_msg *gmsg)
144 LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
146 if (!atomic_dec_and_test(&gmsg->gum_refcount)) {
151 if (gmsg->gum_gctx) {
152 sptlrpc_ctx_wakeup(&gmsg->gum_gctx->gc_base);
153 sptlrpc_ctx_put(&gmsg->gum_gctx->gc_base, 1);
154 gmsg->gum_gctx = NULL;
157 LASSERT(list_empty(&gmsg->gum_list));
158 LASSERT(list_empty(&gmsg->gum_base.list));
164 void gss_unhash_msg_nolock(struct gss_upcall_msg *gmsg)
166 __u32 idx = gmsg->gum_mechidx;
168 LASSERT(idx < MECH_MAX);
169 LASSERT_SPIN_LOCKED(&upcall_locks[idx]);
171 if (list_empty(&gmsg->gum_list))
174 list_del_init(&gmsg->gum_list);
175 LASSERT(atomic_read(&gmsg->gum_refcount) > 1);
176 atomic_dec(&gmsg->gum_refcount);
180 void gss_unhash_msg(struct gss_upcall_msg *gmsg)
182 __u32 idx = gmsg->gum_mechidx;
184 LASSERT(idx < MECH_MAX);
185 upcall_list_lock(idx);
186 gss_unhash_msg_nolock(gmsg);
187 upcall_list_unlock(idx);
191 void gss_msg_fail_ctx(struct gss_upcall_msg *gmsg)
193 if (gmsg->gum_gctx) {
194 struct ptlrpc_cli_ctx *ctx = &gmsg->gum_gctx->gc_base;
196 LASSERT(atomic_read(&ctx->cc_refcount) > 0);
197 sptlrpc_ctx_expire(ctx);
198 set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags);
203 struct gss_upcall_msg * gss_find_upcall(__u32 mechidx, __u32 seq)
205 struct gss_upcall_msg *gmsg;
207 upcall_list_lock(mechidx);
208 list_for_each_entry(gmsg, &upcall_lists[mechidx], gum_list) {
209 if (gmsg->gum_data.gum_seq != seq)
212 LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
213 LASSERT(gmsg->gum_mechidx == mechidx);
215 atomic_inc(&gmsg->gum_refcount);
216 upcall_list_unlock(mechidx);
219 upcall_list_unlock(mechidx);
224 int simple_get_bytes(char **buf, __u32 *buflen, void *res, __u32 reslen)
226 if (*buflen < reslen) {
227 CERROR("buflen %u < %u\n", *buflen, reslen);
231 memcpy(res, *buf, reslen);
237 /*******************************************
239 *******************************************/
241 ssize_t gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
242 char *dst, size_t buflen)
244 char *data = (char *)msg->data + msg->copied;
245 ssize_t mlen = msg->len;
251 left = copy_to_user(dst, data, mlen);
263 ssize_t gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
265 struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
266 struct gss_upcall_msg *gss_msg;
267 struct ptlrpc_cli_ctx *ctx;
268 struct gss_cli_ctx *gctx = NULL;
272 __u32 mechidx, seq, gss_err;
275 mechidx = (__u32) (long) rpci->private;
276 LASSERT(mechidx < MECH_MAX);
278 OBD_ALLOC(buf, mlen);
282 if (copy_from_user(buf, src, mlen)) {
283 CERROR("failed copy user space data\n");
284 GOTO(out_free, rc = -EFAULT);
289 /* data passed down format:
293 * - wire_ctx (rawobj)
294 * - mech_ctx (rawobj)
296 if (simple_get_bytes(&data, &datalen, &seq, sizeof(seq))) {
297 CERROR("fail to get seq\n");
298 GOTO(out_free, rc = -EFAULT);
301 gss_msg = gss_find_upcall(mechidx, seq);
303 CERROR("upcall %u has aborted earlier\n", seq);
304 GOTO(out_free, rc = -EINVAL);
307 gss_unhash_msg(gss_msg);
308 gctx = gss_msg->gum_gctx;
310 LASSERT(atomic_read(&gctx->gc_base.cc_refcount) > 0);
312 /* timeout is not in use for now */
313 if (simple_get_bytes(&data, &datalen, &timeout, sizeof(timeout)))
314 GOTO(out_msg, rc = -EFAULT);
316 /* lgssd signal an error by gc_win == 0 */
317 if (simple_get_bytes(&data, &datalen, &gctx->gc_win,
318 sizeof(gctx->gc_win)))
319 GOTO(out_msg, rc = -EFAULT);
321 if (gctx->gc_win == 0) {
326 if (simple_get_bytes(&data, &datalen, &rc, sizeof(rc)))
327 GOTO(out_msg, rc = -EFAULT);
328 if (simple_get_bytes(&data, &datalen, &gss_err,sizeof(gss_err)))
329 GOTO(out_msg, rc = -EFAULT);
331 if (rc == 0 && gss_err == GSS_S_COMPLETE) {
332 CWARN("both rpc & gss error code not set\n");
339 if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen))
340 GOTO(out_msg, rc = -EFAULT);
341 if (rawobj_dup(&gctx->gc_handle, &tmpobj))
342 GOTO(out_msg, rc = -ENOMEM);
345 if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen))
346 GOTO(out_msg, rc = -EFAULT);
347 gss_err = lgss_import_sec_context(&tmpobj,
348 gss_msg->gum_gsec->gs_mech,
353 if (likely(rc == 0 && gss_err == GSS_S_COMPLETE)) {
354 gss_cli_ctx_uptodate(gctx);
356 ctx = &gctx->gc_base;
357 sptlrpc_ctx_expire(ctx);
358 if (rc != -ERESTART || gss_err != GSS_S_COMPLETE)
359 set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags);
361 CERROR("refresh ctx %p(uid %d) failed: %d/0x%08x: %s\n",
362 ctx, ctx->cc_vcred.vc_uid, rc, gss_err,
363 test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags) ?
364 "fatal error" : "non-fatal");
370 gss_release_msg(gss_msg);
375 * hack pipefs: always return asked length unless all following
376 * downcalls might be messed up.
383 void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
385 struct gss_upcall_msg *gmsg;
386 struct gss_upcall_msg_data *gumd;
387 static cfs_time_t ratelimit = 0;
390 LASSERT(list_empty(&msg->list));
392 /* normally errno is >= 0 */
393 if (msg->errno >= 0) {
398 gmsg = container_of(msg, struct gss_upcall_msg, gum_base);
399 gumd = &gmsg->gum_data;
400 LASSERT(atomic_read(&gmsg->gum_refcount) > 0);
402 CERROR("failed msg %p (seq %u, uid %u, svc %u, nid "LPX64", obd %.*s): "
403 "errno %d\n", msg, gumd->gum_seq, gumd->gum_uid, gumd->gum_svc,
404 gumd->gum_nid, (int) sizeof(gumd->gum_obd),
405 gumd->gum_obd, msg->errno);
407 atomic_inc(&gmsg->gum_refcount);
408 gss_unhash_msg(gmsg);
409 if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) {
410 cfs_time_t now = cfs_time_current_sec();
412 if (cfs_time_after(now, ratelimit)) {
413 CWARN("upcall timed out, is lgssd running?\n");
414 ratelimit = now + 15;
417 gss_msg_fail_ctx(gmsg);
418 gss_release_msg(gmsg);
423 void gss_pipe_release(struct inode *inode)
425 struct rpc_inode *rpci = RPC_I(inode);
429 idx = (__u32) (long) rpci->private;
430 LASSERT(idx < MECH_MAX);
432 upcall_list_lock(idx);
433 while (!list_empty(&upcall_lists[idx])) {
434 struct gss_upcall_msg *gmsg;
435 struct gss_upcall_msg_data *gumd;
437 gmsg = list_entry(upcall_lists[idx].next,
438 struct gss_upcall_msg, gum_list);
439 gumd = &gmsg->gum_data;
440 LASSERT(list_empty(&gmsg->gum_base.list));
442 CERROR("failing remaining msg %p:seq %u, uid %u, svc %u, "
443 "nid "LPX64", obd %.*s\n", gmsg,
444 gumd->gum_seq, gumd->gum_uid, gumd->gum_svc,
445 gumd->gum_nid, (int) sizeof(gumd->gum_obd),
448 gmsg->gum_base.errno = -EPIPE;
449 atomic_inc(&gmsg->gum_refcount);
450 gss_unhash_msg_nolock(gmsg);
452 gss_msg_fail_ctx(gmsg);
454 upcall_list_unlock(idx);
455 gss_release_msg(gmsg);
456 upcall_list_lock(idx);
458 upcall_list_unlock(idx);
462 static struct rpc_pipe_ops gss_upcall_ops = {
463 .upcall = gss_pipe_upcall,
464 .downcall = gss_pipe_downcall,
465 .destroy_msg = gss_pipe_destroy_msg,
466 .release_pipe = gss_pipe_release,
470 /*******************************************
471 * upcall helper functions *
472 *******************************************/
475 __u32 import_to_gss_svc(struct obd_import *imp)
477 const char *name = imp->imp_obd->obd_type->typ_name;
478 if (!strcmp(name, LUSTRE_MDC_NAME))
479 return LUSTRE_GSS_TGT_MDS;
480 if (!strcmp(name, LUSTRE_OSC_NAME))
481 return LUSTRE_GSS_TGT_OSS;
486 int gss_ctx_refresh_pipefs(struct ptlrpc_cli_ctx *ctx)
488 struct obd_import *imp;
489 struct gss_sec *gsec;
490 struct gss_upcall_msg *gmsg;
496 LASSERT(ctx->cc_sec);
497 LASSERT(ctx->cc_sec->ps_import);
498 LASSERT(ctx->cc_sec->ps_import->imp_obd);
500 imp = ctx->cc_sec->ps_import;
501 if (!imp->imp_connection) {
502 CERROR("import has no connection set\n");
506 gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base);
512 /* initialize pipefs base msg */
513 INIT_LIST_HEAD(&gmsg->gum_base.list);
514 gmsg->gum_base.data = &gmsg->gum_data;
515 gmsg->gum_base.len = sizeof(gmsg->gum_data);
516 gmsg->gum_base.copied = 0;
517 gmsg->gum_base.errno = 0;
519 /* init upcall msg */
520 atomic_set(&gmsg->gum_refcount, 1);
521 gmsg->gum_mechidx = mech_name2idx(gsec->gs_mech->gm_name);
522 gmsg->gum_gsec = gsec;
523 gmsg->gum_gctx = container_of(sptlrpc_ctx_get(ctx),
524 struct gss_cli_ctx, gc_base);
525 gmsg->gum_data.gum_seq = upcall_get_sequence();
526 gmsg->gum_data.gum_uid = ctx->cc_vcred.vc_uid;
527 gmsg->gum_data.gum_gid = 0; /* not used for now */
528 gmsg->gum_data.gum_svc = import_to_gss_svc(imp);
529 gmsg->gum_data.gum_nid = imp->imp_connection->c_peer.nid;
530 strncpy(gmsg->gum_data.gum_obd, imp->imp_obd->obd_name,
531 sizeof(gmsg->gum_data.gum_obd));
533 /* This only could happen when sysadmin set it dead/expired
534 * using lctl by force.
537 if (ctx->cc_flags & PTLRPC_CTX_STATUS_MASK) {
538 CWARN("ctx %p(%u->%s) was set flags %lx unexpectedly\n",
539 ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
542 LASSERT(!(ctx->cc_flags & PTLRPC_CTX_UPTODATE));
543 ctx->cc_flags |= PTLRPC_CTX_DEAD | PTLRPC_CTX_ERROR;
549 upcall_msg_enlist(gmsg);
551 rc = rpc_queue_upcall(de_pipes[gmsg->gum_mechidx]->d_inode,
554 CERROR("rpc_queue_upcall failed: %d\n", rc);
556 upcall_msg_delist(gmsg);
566 int gss_sec_upcall_init(struct gss_sec *gsec)
571 void gss_sec_upcall_cleanup(struct gss_sec *gsec)
575 int gss_init_pipefs(void)
580 de = rpc_mkdir(LUSTRE_PIPE_ROOT, NULL);
581 if (IS_ERR(de) && PTR_ERR(de) != -EEXIST) {
582 CERROR("Failed to create gss pipe dir: %ld\n", PTR_ERR(de));
586 * hack pipefs: dput will sometimes cause oops during module unload
587 * and lgssd close the pipe fds.
592 de = rpc_mkpipe(LUSTRE_PIPE_KRB5, (void *) MECH_KRB5, &gss_upcall_ops,
593 RPC_PIPE_WAIT_FOR_OPEN);
594 if (!de || IS_ERR(de)) {
595 CERROR("failed to make rpc_pipe %s: %ld\n",
596 LUSTRE_PIPE_KRB5, PTR_ERR(de));
597 rpc_rmdir(LUSTRE_PIPE_ROOT);
601 de_pipes[MECH_KRB5] = de;
602 INIT_LIST_HEAD(&upcall_lists[MECH_KRB5]);
603 upcall_locks[MECH_KRB5] = SPIN_LOCK_UNLOCKED;
608 void gss_cleanup_pipefs(void)
612 for (i = 0; i < MECH_MAX; i++) {
613 LASSERT(list_empty(&upcall_lists[i]));
615 * hack pipefs, dput pipe dentry here might cause lgssd oops.
621 rpc_unlink(LUSTRE_PIPE_KRB5);
622 rpc_rmdir(LUSTRE_PIPE_ROOT);
625 /**********************************************
626 * gss context init/fini helper *
627 **********************************************/
630 int ctx_init_pack_request(struct obd_import *imp,
631 struct ptlrpc_request *req,
633 uid_t uid, gid_t gid,
637 struct lustre_msg *msg = req->rq_reqbuf;
638 struct gss_sec *gsec;
639 struct gss_header *ghdr;
640 struct ptlrpc_user_desc *pud;
641 __u32 *p, size, offset = 2;
644 LASSERT(msg->lm_bufcount <= 4);
647 ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
648 ghdr->gh_version = PTLRPC_GSS_VERSION;
650 ghdr->gh_proc = PTLRPC_GSS_PROC_INIT;
652 ghdr->gh_svc = PTLRPC_GSS_SVC_NONE;
653 ghdr->gh_handle.len = 0;
655 /* fix the user desc */
656 if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
657 pud = lustre_msg_buf(msg, offset, sizeof(*pud));
659 pud->pud_uid = pud->pud_fsuid = uid;
660 pud->pud_gid = pud->pud_fsgid = gid;
662 pud->pud_ngroups = 0;
666 /* security payload */
667 p = lustre_msg_buf(msg, offset, 0);
668 size = msg->lm_buflens[offset];
670 /* 1. lustre svc type */
672 *p++ = cpu_to_le32(lustre_srv);
676 obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1;
677 obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid;
678 if (rawobj_serialize(&obj, &p, &size))
681 /* 3. reverse context handle. actually only needed by root user,
682 * but we send it anyway.
684 gsec = container_of(imp->imp_sec, struct gss_sec, gs_base);
685 obj.len = sizeof(gsec->gs_rvs_hdl);
686 obj.data = (__u8 *) &gsec->gs_rvs_hdl;
687 if (rawobj_serialize(&obj, &p, &size))
690 /* 4. now the token */
691 LASSERT(size >= (sizeof(__u32) + token_size));
692 *p++ = cpu_to_le32(((__u32) token_size));
693 if (copy_from_user(p, token, token_size)) {
694 CERROR("can't copy token\n");
697 size -= sizeof(__u32) + size_round4(token_size);
699 req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset,
700 msg->lm_buflens[offset] - size, 0);
705 int ctx_init_parse_reply(struct lustre_msg *msg,
706 char __user *outbuf, long outlen)
708 struct gss_rep_header *ghdr;
709 __u32 obj_len, round_len;
710 __u32 status, effective = 0;
712 if (msg->lm_bufcount != 3) {
713 CERROR("unexpected bufcount %u\n", msg->lm_bufcount);
717 ghdr = (struct gss_rep_header *) gss_swab_header(msg, 0);
719 CERROR("unable to extract gss reply header\n");
723 if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
724 CERROR("invalid gss version %u\n", ghdr->gh_version);
728 if (outlen < (4 + 2) * 4 + size_round4(ghdr->gh_handle.len) +
729 size_round4(msg->lm_buflens[2])) {
730 CERROR("output buffer size %ld too small\n", outlen);
737 if (copy_to_user(outbuf, &status, 4))
740 if (copy_to_user(outbuf, &ghdr->gh_major, 4))
743 if (copy_to_user(outbuf, &ghdr->gh_minor, 4))
746 if (copy_to_user(outbuf, &ghdr->gh_seqwin, 4))
752 obj_len = ghdr->gh_handle.len;
753 round_len = (obj_len + 3) & ~ 3;
754 if (copy_to_user(outbuf, &obj_len, 4))
757 if (copy_to_user(outbuf, (char *) ghdr->gh_handle.data, round_len))
760 effective += 4 + round_len;
763 obj_len = msg->lm_buflens[2];
764 round_len = (obj_len + 3) & ~ 3;
765 if (copy_to_user(outbuf, &obj_len, 4))
768 if (copy_to_user(outbuf, lustre_msg_buf(msg, 2, 0), round_len))
771 effective += 4 + round_len;
776 /* XXX move to where lgssd could see */
777 struct lgssd_ioctl_param {
778 int version; /* in */
780 int lustre_svc; /* in */
783 long send_token_size;/* in */
784 char *send_token; /* in */
785 long reply_buf_size; /* in */
786 char *reply_buf; /* in */
787 long status; /* out */
788 long reply_length; /* out */
791 int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count)
793 struct obd_import *imp;
794 struct ptlrpc_request *req;
795 struct lgssd_ioctl_param param;
796 struct obd_device *obd;
799 int lmsg_size = sizeof(struct ptlrpc_body);
802 if (count != sizeof(param)) {
803 CERROR("ioctl size %lu, expect %lu, please check lgssd version\n",
804 count, (unsigned long) sizeof(param));
807 if (copy_from_user(¶m, buffer, sizeof(param))) {
808 CERROR("failed copy data from lgssd\n");
812 if (param.version != GSSD_INTERFACE_VERSION) {
813 CERROR("gssd interface version %d (expect %d)\n",
814 param.version, GSSD_INTERFACE_VERSION);
819 if (strncpy_from_user(obdname, param.uuid, sizeof(obdname)) <= 0) {
820 CERROR("Invalid obdname pointer\n");
824 obd = class_name2obd(obdname);
826 CERROR("no such obd %s\n", obdname);
830 imp = class_import_get(obd->u.cli.cl_import);
831 LASSERT(imp->imp_sec);
833 /* force this import to use v2 msg */
834 imp->imp_msg_magic = LUSTRE_MSG_MAGIC_V2;
836 req = ptlrpc_prep_req(imp, LUSTRE_OBD_VERSION, SEC_CTX_INIT,
837 1, &lmsg_size, NULL);
839 param.status = -ENOMEM;
844 rc = ctx_init_pack_request(imp, req,
846 param.uid, param.gid,
847 param.send_token_size,
854 req->rq_replen = lustre_msg_size_v2(1, &lmsg_size);
856 rc = ptlrpc_queue_wait(req);
858 /* If any _real_ denial be made, we expect server return
859 * -EACCES reply or return success but indicate gss error
860 * inside reply messsage. All other errors are treated as
861 * timeout, caller might try the negotiation repeatedly,
862 * leave recovery decisions to general ptlrpc layer.
864 * FIXME maybe some other error code shouldn't be treated
869 param.status = -ETIMEDOUT;
873 lsize = ctx_init_parse_reply(req->rq_repbuf,
874 param.reply_buf, param.reply_buf_size);
876 param.status = (int) lsize;
881 param.reply_length = lsize;
884 if (copy_to_user(buffer, ¶m, sizeof(param)))
889 class_import_put(imp);
890 ptlrpc_req_finished(req);
894 int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx)
896 struct ptlrpc_cli_ctx *ctx = &gctx->gc_base;
897 struct obd_import *imp = ctx->cc_sec->ps_import;
898 struct ptlrpc_request *req;
899 struct ptlrpc_user_desc *pud;
900 int buflens = sizeof(struct ptlrpc_body);
904 if (ctx->cc_sec->ps_flags & PTLRPC_SEC_FL_REVERSE) {
905 CWARN("ctx %p(%u) is reverse, don't send destroy rpc\n",
906 ctx, ctx->cc_vcred.vc_uid);
910 if (test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags) ||
911 !test_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags)) {
912 CWARN("ctx %p(%u->%s) already dead, don't send destroy rpc\n",
913 ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
919 CWARN("client destroy ctx %p(%u->%s)\n",
920 ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
922 /* context's refcount could be 0, steal one */
923 atomic_inc(&ctx->cc_refcount);
925 gctx->gc_proc = PTLRPC_GSS_PROC_DESTROY;
927 req = ptlrpc_prep_req_pool(imp, LUSTRE_OBD_VERSION, SEC_CTX_FINI,
928 1, &buflens, NULL, NULL, ctx);
930 CWARN("ctx %p(%u): fail to prepare rpc, destroy locally\n",
931 ctx, ctx->cc_vcred.vc_uid);
932 GOTO(out_ref, rc = -ENOMEM);
935 /* fix the user desc */
936 if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
937 /* we rely the fact that this request is in AUTH mode,
938 * and user_desc at offset 2.
940 pud = lustre_msg_buf(req->rq_reqbuf, 2, sizeof(*pud));
942 pud->pud_uid = pud->pud_fsuid = ctx->cc_vcred.vc_uid;
943 pud->pud_gid = pud->pud_fsgid = ctx->cc_vcred.vc_gid;
945 pud->pud_ngroups = 0;
948 req->rq_replen = lustre_msg_size_v2(1, &buflens);
950 rc = ptlrpc_queue_wait(req);
952 CWARN("ctx %p(%u): rpc error %d, destroy locally\n",
953 ctx, ctx->cc_vcred.vc_uid, rc);
956 ptlrpc_req_finished(req);
958 atomic_dec(&ctx->cc_refcount);
962 int __init gss_init_upcall(void)
966 rc = gss_svc_init_upcall();
970 rc = gss_init_pipefs();
972 gss_svc_exit_upcall();
977 void __exit gss_exit_upcall(void)
979 gss_svc_exit_upcall();
980 gss_cleanup_pipefs();