diff options
Diffstat (limited to 'drivers/staging/lustre/lustre/ptlrpc')
46 files changed, 415 insertions, 11984 deletions
diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile index 1c338aaf18a6..fb50cd4c65b6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/Makefile +++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile @@ -18,8 +18,3 @@ ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs) ptlrpc-$(CONFIG_PROC_FS) += sec_lproc.o ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.o - -obj-$(CONFIG_PTLRPC_GSS) += gss/ - - -ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 7246e8ce9c19..4146e8b29a6d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -38,12 +38,12 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_lib.h> -#include <lustre_ha.h> -#include <lustre_import.h> -#include <lustre_req_layout.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_lib.h" +#include "../include/lustre_ha.h" +#include "../include/lustre_import.h" +#include "../include/lustre_req_layout.h" #include "ptlrpc_internal.h" @@ -283,7 +283,7 @@ static void ptlrpc_at_adj_net_latency(struct ptlrpc_request *req, { unsigned int nl, oldnl; struct imp_at *at; - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); LASSERT(req->rq_import); at = &req->rq_import->imp_at; @@ -367,13 +367,13 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) olddl = req->rq_deadline; /* server assumes it now has rq_timeout from when it sent the * early reply, so client should give it at least that long. */ - req->rq_deadline = cfs_time_current_sec() + req->rq_timeout + + req->rq_deadline = get_seconds() + req->rq_timeout + ptlrpc_at_get_net_latency(req); DEBUG_REQ(D_ADAPTTO, req, "Early reply #%d, new deadline in "CFS_DURATION_T"s " "("CFS_DURATION_T"s)", req->rq_early_count, - cfs_time_sub(req->rq_deadline, cfs_time_current_sec()), + cfs_time_sub(req->rq_deadline, get_seconds()), cfs_time_sub(req->rq_deadline, olddl)); return rc; @@ -1181,7 +1181,7 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req) LASSERT(versions); lustre_msg_set_versions(reqmsg, versions); - CDEBUG(D_INFO, "Client save versions ["LPX64"/"LPX64"]\n", + CDEBUG(D_INFO, "Client save versions [%#llx/%#llx]\n", versions[0], versions[1]); } @@ -1202,7 +1202,7 @@ static int after_reply(struct ptlrpc_request *req) LASSERT(obd != NULL); /* repbuf must be unlinked */ - LASSERT(!req->rq_receiving_reply && !req->rq_must_unlink); + LASSERT(!req->rq_receiving_reply && !req->rq_reply_unlink); if (req->rq_reply_truncate) { if (ptlrpc_no_resend(req)) { @@ -1248,7 +1248,7 @@ static int after_reply(struct ptlrpc_request *req) /* retry indefinitely on EINPROGRESS */ if (lustre_msg_get_status(req->rq_repmsg) == -EINPROGRESS && ptlrpc_no_resend(req) == 0 && !req->rq_no_retry_einprogress) { - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); DEBUG_REQ(D_RPCTRACE, req, "Resending request on EINPROGRESS"); req->rq_resend = 1; @@ -1395,7 +1395,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) int rc; LASSERT(req->rq_phase == RQ_PHASE_NEW); - if (req->rq_sent && (req->rq_sent > cfs_time_current_sec()) && + if (req->rq_sent && (req->rq_sent > get_seconds()) && (!req->rq_generation_set || req->rq_import_generation == imp->imp_generation)) return 0; @@ -1451,7 +1451,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) } CDEBUG(D_RPCTRACE, "Sending RPC pname:cluuid:pid:xid:nid:opc" - " %s:%s:%d:"LPU64":%s:%d\n", current_comm(), + " %s:%s:%d:%llu:%s:%d\n", current_comm(), imp->imp_obd->obd_uuid.uuid, lustre_msg_get_status(req->rq_reqmsg), req->rq_xid, libcfs_nid2str(imp->imp_connection->c_peer.nid), @@ -1496,6 +1496,8 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set) * and no more replies are expected. * (it is possible to get less replies than requests sent e.g. due to timed out * requests or requests that we had trouble to send out) + * + * NOTE: This function contains a potential schedule point (cond_resched()). */ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) { @@ -1513,6 +1515,14 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) int unregistered = 0; int rc = 0; + /* This schedule point is mainly for the ptlrpcd caller of this + * function. Most ptlrpc sets are not long-lived and unbounded + * in length, but at the least the set used by the ptlrpcd is. + * Since the processing time is unbounded, we need to insert an + * explicit schedule point to make the thread well-behaved. + */ + cond_resched(); + if (req->rq_phase == RQ_PHASE_NEW && ptlrpc_send_new_req(req)) { force_timer_recalc = 1; @@ -1524,7 +1534,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) /* delayed resend - skip */ if (req->rq_phase == RQ_PHASE_RPC && req->rq_resend && - req->rq_sent > cfs_time_current_sec()) + req->rq_sent > get_seconds()) continue; if (!(req->rq_phase == RQ_PHASE_RPC || @@ -1688,9 +1698,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) /* ensure previous bulk fails */ old_xid = req->rq_xid; req->rq_xid = ptlrpc_next_xid(); - CDEBUG(D_HA, "resend bulk " - "old x"LPU64 - " new x"LPU64"\n", + CDEBUG(D_HA, "resend bulk old x%llu new x%llu\n", old_xid, req->rq_xid); } } @@ -1821,7 +1829,7 @@ interpret: CDEBUG(req->rq_reqmsg != NULL ? D_RPCTRACE : 0, "Completed RPC pname:cluuid:pid:xid:nid:" - "opc %s:%s:%d:"LPU64":%s:%d\n", + "opc %s:%s:%d:%llu:%s:%d\n", current_comm(), imp->imp_obd->obd_uuid.uuid, lustre_msg_get_status(req->rq_reqmsg), req->rq_xid, libcfs_nid2str(imp->imp_connection->c_peer.nid), @@ -1884,7 +1892,7 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) "/real "CFS_DURATION_T"]", req->rq_net_err ? "failed due to network error" : ((req->rq_real_sent == 0 || - cfs_time_before(req->rq_real_sent, req->rq_sent) || + time_before((unsigned long)req->rq_real_sent, (unsigned long)req->rq_sent) || cfs_time_aftereq(req->rq_real_sent, req->rq_deadline)) ? "timed out for sent delay" : "timed out for slow reply"), req->rq_sent, req->rq_real_sent); @@ -1945,7 +1953,7 @@ int ptlrpc_expired_set(void *data) { struct ptlrpc_request_set *set = data; struct list_head *tmp; - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); LASSERT(set != NULL); @@ -2028,7 +2036,7 @@ EXPORT_SYMBOL(ptlrpc_interrupted_set); int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set) { struct list_head *tmp; - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); int timeout = 0; struct ptlrpc_request *req; int deadline; @@ -2346,7 +2354,7 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) */ if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_REPL_UNLINK) && async && request->rq_reply_deadline == 0) - request->rq_reply_deadline = cfs_time_current_sec()+LONG_UNLINK; + request->rq_reply_deadline = get_seconds()+LONG_UNLINK; /* * Nothing left to do. @@ -2396,9 +2404,10 @@ int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) } LASSERT(rc == -ETIMEDOUT); - DEBUG_REQ(D_WARNING, request, "Unexpectedly long timeout " - "rvcng=%d unlnk=%d", request->rq_receiving_reply, - request->rq_must_unlink); + DEBUG_REQ(D_WARNING, request, + "Unexpectedly long timeout rvcng=%d unlnk=%d/%d", + request->rq_receiving_reply, + request->rq_req_unlink, request->rq_reply_unlink); } return 0; } @@ -2456,11 +2465,11 @@ void ptlrpc_free_committed(struct obd_import *imp) if (imp->imp_peer_committed_transno == imp->imp_last_transno_checked && imp->imp_generation == imp->imp_last_generation_checked) { - CDEBUG(D_INFO, "%s: skip recheck: last_committed "LPU64"\n", + CDEBUG(D_INFO, "%s: skip recheck: last_committed %llu\n", imp->imp_obd->obd_name, imp->imp_peer_committed_transno); return; } - CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n", + CDEBUG(D_RPCTRACE, "%s: committing for last_committed %llu gen %d\n", imp->imp_obd->obd_name, imp->imp_peer_committed_transno, imp->imp_generation); @@ -2498,7 +2507,7 @@ void ptlrpc_free_committed(struct obd_import *imp) continue; } - DEBUG_REQ(D_INFO, req, "commit (last_committed "LPU64")", + DEBUG_REQ(D_INFO, req, "commit (last_committed %llu)", imp->imp_peer_committed_transno); free_req: ptlrpc_free_request(req); @@ -2530,10 +2539,19 @@ EXPORT_SYMBOL(ptlrpc_cleanup_client); void ptlrpc_resend_req(struct ptlrpc_request *req) { DEBUG_REQ(D_HA, req, "going to resend"); + spin_lock(&req->rq_lock); + + /* Request got reply but linked to the import list still. + Let ptlrpc_check_set() to process it. */ + if (ptlrpc_client_replied(req)) { + spin_unlock(&req->rq_lock); + DEBUG_REQ(D_HA, req, "it has reply, so skip it"); + return; + } + lustre_msg_set_handle(req->rq_reqmsg, &(struct lustre_handle){ 0 }); req->rq_status = -EAGAIN; - spin_lock(&req->rq_lock); req->rq_resend = 1; req->rq_net_err = 0; req->rq_timedout = 0; @@ -2542,7 +2560,7 @@ void ptlrpc_resend_req(struct ptlrpc_request *req) /* ensure previous bulk fails */ req->rq_xid = ptlrpc_next_xid(); - CDEBUG(D_HA, "resend bulk old x"LPU64" new x"LPU64"\n", + CDEBUG(D_HA, "resend bulk old x%llu new x%llu\n", old_xid, req->rq_xid); } ptlrpc_client_wake_req(req); @@ -2705,7 +2723,7 @@ static int ptlrpc_replay_interpret(const struct lu_env *env, LASSERTF(lustre_msg_get_transno(req->rq_reqmsg) == lustre_msg_get_transno(req->rq_repmsg) || lustre_msg_get_transno(req->rq_repmsg) == 0, - LPX64"/"LPX64"\n", + "%#llx/%#llx\n", lustre_msg_get_transno(req->rq_reqmsg), lustre_msg_get_transno(req->rq_repmsg)); } @@ -2721,8 +2739,8 @@ static int ptlrpc_replay_interpret(const struct lu_env *env, /* transaction number shouldn't be bigger than the latest replayed */ if (req->rq_transno > lustre_msg_get_transno(req->rq_reqmsg)) { DEBUG_REQ(D_ERROR, req, - "Reported transno "LPU64" is bigger than the " - "replayed one: "LPU64, req->rq_transno, + "Reported transno %llu is bigger than the replayed one: %llu", + req->rq_transno, lustre_msg_get_transno(req->rq_reqmsg)); GOTO(out, rc = -EINVAL); } @@ -2907,7 +2925,7 @@ static spinlock_t ptlrpc_last_xid_lock; #define YEAR_2004 (1ULL << 30) void ptlrpc_init_xid(void) { - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); spin_lock_init(&ptlrpc_last_xid_lock); if (now < YEAR_2004) { @@ -2996,7 +3014,7 @@ static void ptlrpcd_add_work_req(struct ptlrpc_request *req) { /* re-initialize the req */ req->rq_timeout = obd_timeout; - req->rq_sent = cfs_time_current_sec(); + req->rq_sent = get_seconds(); req->rq_deadline = req->rq_sent + req->rq_timeout; req->rq_reply_deadline = req->rq_deadline; req->rq_phase = RQ_PHASE_INTERPRET; @@ -3062,7 +3080,7 @@ void *ptlrpcd_alloc_work(struct obd_import *imp, req->rq_interpret_reply = work_interpreter; /* don't want reply */ req->rq_receiving_reply = 0; - req->rq_must_unlink = 0; + req->rq_req_unlink = req->rq_reply_unlink = 0; req->rq_no_delay = req->rq_no_resend = 1; req->rq_pill.rc_fmt = (void *)&worker_format; diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c index 6756356faac1..adff1ab4f5a4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/connection.c +++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c @@ -35,9 +35,9 @@ */ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" #include "ptlrpc_internal.h" diff --git a/drivers/staging/lustre/lustre/ptlrpc/errno.c b/drivers/staging/lustre/lustre/ptlrpc/errno.c index 1c1006333960..73f8374f190e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/errno.c +++ b/drivers/staging/lustre/lustre/ptlrpc/errno.c @@ -25,8 +25,8 @@ * Copyright (c) 2013, Intel Corporation. */ -#include <linux/libcfs/libcfs.h> -#include <lustre/lustre_errno.h> +#include "../../include/linux/libcfs/libcfs.h" +#include "../include/lustre/lustre_errno.h" /* * The two translation tables below must define a one-to-one mapping between diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index aa85239f6cd5..c3ec21d5d29f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -36,14 +36,14 @@ #define DEBUG_SUBSYSTEM S_RPC -# include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" # ifdef __mips64__ # include <linux/kernel.h> # endif -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_sec.h> +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_sec.h" #include "ptlrpc_internal.h" lnet_handle_eq_t ptlrpc_eq_h; @@ -63,19 +63,20 @@ void request_out_callback(lnet_event_t *ev) DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status); sptlrpc_request_out_callback(req); - req->rq_real_sent = cfs_time_current_sec(); + spin_lock(&req->rq_lock); + req->rq_real_sent = get_seconds(); + if (ev->unlinked) + req->rq_req_unlink = 0; if (ev->type == LNET_EVENT_UNLINK || ev->status != 0) { /* Failed send: make it seem like the reply timed out, just * like failing sends in client.c does currently... */ - spin_lock(&req->rq_lock); req->rq_net_err = 1; - spin_unlock(&req->rq_lock); - ptlrpc_client_wake_req(req); } + spin_unlock(&req->rq_lock); ptlrpc_req_finished(req); } @@ -102,7 +103,7 @@ void reply_in_callback(lnet_event_t *ev) req->rq_receiving_reply = 0; req->rq_early = 0; if (ev->unlinked) - req->rq_must_unlink = 0; + req->rq_reply_unlink = 0; if (ev->status) goto out_wake; @@ -145,6 +146,8 @@ void reply_in_callback(lnet_event_t *ev) /* Real reply */ req->rq_rep_swab_mask = 0; req->rq_replied = 1; + /* Got reply, no resend required */ + req->rq_resend = 0; req->rq_reply_off = ev->offset; req->rq_nob_received = ev->mlength; /* LNetMDUnlink can't be called under the LNET_LOCK, @@ -155,7 +158,7 @@ void reply_in_callback(lnet_event_t *ev) ev->mlength, ev->offset, req->rq_replen); } - req->rq_import->imp_last_reply_time = cfs_time_current_sec(); + req->rq_import->imp_last_reply_time = get_seconds(); out_wake: /* NB don't unlock till after wakeup; req can disappear under us @@ -307,7 +310,7 @@ void request_in_callback(lnet_event_t *ev) /* We moaned above already... */ return; } - req = ptlrpc_request_cache_alloc(ALLOC_ATOMIC_TRY); + req = ptlrpc_request_cache_alloc(GFP_ATOMIC); if (req == NULL) { CERROR("Can't allocate incoming request descriptor: " "Dropping %s RPC from %s\n", @@ -334,7 +337,7 @@ void request_in_callback(lnet_event_t *ev) INIT_LIST_HEAD(&req->rq_exp_list); atomic_set(&req->rq_refcount, 1); if (ev->type == LNET_EVENT_PUT) - CDEBUG(D_INFO, "incoming req@%p x"LPU64" msgsize %u\n", + CDEBUG(D_INFO, "incoming req@%p x%llu msgsize %u\n", req, req->rq_xid, ev->mlength); CDEBUG(D_RPCTRACE, "peer: %s\n", libcfs_id2str(req->rq_peer)); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile b/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile deleted file mode 100644 index 8cdfbeed64e6..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-$(CONFIG_LUSTRE_FS) := ptlrpc_gss.o - -ptlrpc_gss-y := sec_gss.o gss_bulk.o gss_cli_upcall.o gss_svc_upcall.o \ - gss_rawobj.o lproc_gss.o gss_generic_token.o \ - gss_mech_switch.o gss_krb5_mech.o - - -ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h deleted file mode 100644 index 0e9f6c472a37..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_api.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * Somewhat simplified version of the gss api. - * - * Dug Song <dugsong@monkey.org> - * Andy Adamson <andros@umich.edu> - * Bruce Fields <bfields@umich.edu> - * Copyright (c) 2000 The Regents of the University of Michigan - * - */ - -#ifndef __PTLRPC_GSS_GSS_API_H_ -#define __PTLRPC_GSS_GSS_API_H_ - -struct gss_api_mech; - -/* The mechanism-independent gss-api context: */ -struct gss_ctx { - struct gss_api_mech *mech_type; - void *internal_ctx_id; -}; - -#define GSS_C_NO_BUFFER ((rawobj_t) 0) -#define GSS_C_NO_CONTEXT ((struct gss_ctx *) 0) -#define GSS_C_NULL_OID ((rawobj_t) 0) - -/* - * gss-api prototypes; note that these are somewhat simplified versions of - * the prototypes specified in RFC 2744. - */ -__u32 lgss_import_sec_context( - rawobj_t *input_token, - struct gss_api_mech *mech, - struct gss_ctx **ctx); -__u32 lgss_copy_reverse_context( - struct gss_ctx *ctx, - struct gss_ctx **ctx_new); -__u32 lgss_inquire_context( - struct gss_ctx *ctx, - unsigned long *endtime); -__u32 lgss_get_mic( - struct gss_ctx *ctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token); -__u32 lgss_verify_mic( - struct gss_ctx *ctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token); -__u32 lgss_wrap( - struct gss_ctx *ctx, - rawobj_t *gsshdr, - rawobj_t *msg, - int msg_buflen, - rawobj_t *out_token); -__u32 lgss_unwrap( - struct gss_ctx *ctx, - rawobj_t *gsshdr, - rawobj_t *token, - rawobj_t *out_msg); -__u32 lgss_prep_bulk( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc); -__u32 lgss_wrap_bulk( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob); -__u32 lgss_unwrap_bulk( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob); -__u32 lgss_delete_sec_context( - struct gss_ctx **ctx); -int lgss_display( - struct gss_ctx *ctx, - char *buf, - int bufsize); - -struct subflavor_desc { - __u32 sf_subflavor; - __u32 sf_qop; - __u32 sf_service; - char *sf_name; -}; - -/* Each mechanism is described by the following struct: */ -struct gss_api_mech { - struct list_head gm_list; - struct module *gm_owner; - char *gm_name; - rawobj_t gm_oid; - atomic_t gm_count; - struct gss_api_ops *gm_ops; - int gm_sf_num; - struct subflavor_desc *gm_sfs; -}; - -/* and must provide the following operations: */ -struct gss_api_ops { - __u32 (*gss_import_sec_context)( - rawobj_t *input_token, - struct gss_ctx *ctx); - __u32 (*gss_copy_reverse_context)( - struct gss_ctx *ctx, - struct gss_ctx *ctx_new); - __u32 (*gss_inquire_context)( - struct gss_ctx *ctx, - unsigned long *endtime); - __u32 (*gss_get_mic)( - struct gss_ctx *ctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token); - __u32 (*gss_verify_mic)( - struct gss_ctx *ctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token); - __u32 (*gss_wrap)( - struct gss_ctx *ctx, - rawobj_t *gsshdr, - rawobj_t *msg, - int msg_buflen, - rawobj_t *out_token); - __u32 (*gss_unwrap)( - struct gss_ctx *ctx, - rawobj_t *gsshdr, - rawobj_t *token, - rawobj_t *out_msg); - __u32 (*gss_prep_bulk)( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc); - __u32 (*gss_wrap_bulk)( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob); - __u32 (*gss_unwrap_bulk)( - struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob); - void (*gss_delete_sec_context)( - void *ctx); - int (*gss_display)( - struct gss_ctx *ctx, - char *buf, - int bufsize); -}; - -int lgss_mech_register(struct gss_api_mech *mech); -void lgss_mech_unregister(struct gss_api_mech *mech); - -struct gss_api_mech * lgss_OID_to_mech(rawobj_t *oid); -struct gss_api_mech * lgss_name_to_mech(char *name); -struct gss_api_mech * lgss_subflavor_to_mech(__u32 subflavor); - -struct gss_api_mech * lgss_mech_get(struct gss_api_mech *mech); -void lgss_mech_put(struct gss_api_mech *mech); - -#endif /* __PTLRPC_GSS_GSS_API_H_ */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h deleted file mode 100644 index bdfd83880422..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_asn1.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * minimal asn1 for generic encoding/decoding of gss tokens - * - * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, - * lib/gssapi/krb5/gssapiP_krb5.h, and others - * - * Copyright (c) 2000 The Regents of the University of Michigan. - * All rights reserved. - * - * Andy Adamson <andros@umich.edu> - */ - -/* - * Copyright 1995 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - */ - -#define SIZEOF_INT 4 - -/* from gssapi_err_generic.h */ -#define G_BAD_SERVICE_NAME (-2045022976L) -#define G_BAD_STRING_UID (-2045022975L) -#define G_NOUSER (-2045022974L) -#define G_VALIDATE_FAILED (-2045022973L) -#define G_BUFFER_ALLOC (-2045022972L) -#define G_BAD_MSG_CTX (-2045022971L) -#define G_WRONG_SIZE (-2045022970L) -#define G_BAD_USAGE (-2045022969L) -#define G_UNKNOWN_QOP (-2045022968L) -#define G_NO_HOSTNAME (-2045022967L) -#define G_BAD_HOSTNAME (-2045022966L) -#define G_WRONG_MECH (-2045022965L) -#define G_BAD_TOK_HEADER (-2045022964L) -#define G_BAD_DIRECTION (-2045022963L) -#define G_TOK_TRUNC (-2045022962L) -#define G_REFLECT (-2045022961L) -#define G_WRONG_TOKID (-2045022960L) - -#define g_OID_equal(o1, o2) \ - (((o1)->len == (o2)->len) && \ - (memcmp((o1)->data, (o2)->data, (int) (o1)->len) == 0)) - -__u32 g_verify_token_header(rawobj_t *mech, - int *body_size, - unsigned char **buf_in, - int toksize); - -__u32 g_get_mech_oid(rawobj_t *mech, - rawobj_t *in_buf); - -int g_token_size(rawobj_t *mech, - unsigned int body_size); - -void g_make_token_header(rawobj_t *mech, - int body_size, - unsigned char **buf); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c deleted file mode 100644 index 93794bd928cb..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/ptlrpc/gss/gss_bulk.c - * - * Author: Eric Mei <eric.mei@sun.com> - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/mutex.h> -#include <linux/crypto.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - struct gss_cli_ctx *gctx; - struct lustre_msg *msg; - struct ptlrpc_bulk_sec_desc *bsd; - rawobj_t token; - __u32 maj; - int offset; - int rc; - - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_read || req->rq_bulk_write); - - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - LASSERT(gctx->gc_mechctx); - - switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) { - case SPTLRPC_SVC_NULL: - LASSERT(req->rq_reqbuf->lm_bufcount >= 3); - msg = req->rq_reqbuf; - offset = msg->lm_bufcount - 1; - break; - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - LASSERT(req->rq_reqbuf->lm_bufcount >= 4); - msg = req->rq_reqbuf; - offset = msg->lm_bufcount - 2; - break; - case SPTLRPC_SVC_PRIV: - LASSERT(req->rq_clrbuf->lm_bufcount >= 2); - msg = req->rq_clrbuf; - offset = msg->lm_bufcount - 1; - break; - default: - LBUG(); - } - - bsd = lustre_msg_buf(msg, offset, sizeof(*bsd)); - bsd->bsd_version = 0; - bsd->bsd_flags = 0; - bsd->bsd_type = SPTLRPC_BULK_DEFAULT; - bsd->bsd_svc = SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc); - - if (bsd->bsd_svc == SPTLRPC_BULK_SVC_NULL) - return 0; - - LASSERT(bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG || - bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV); - - if (req->rq_bulk_read) { - /* - * bulk read: prepare receiving pages only for privacy mode. - */ - if (bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV) - return gss_cli_prep_bulk(req, desc); - } else { - /* - * bulk write: sign or encrypt bulk pages. - */ - bsd->bsd_nob = desc->bd_nob; - - if (bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG) { - /* integrity mode */ - token.data = bsd->bsd_data; - token.len = lustre_msg_buflen(msg, offset) - - sizeof(*bsd); - - maj = lgss_get_mic(gctx->gc_mechctx, 0, NULL, - desc->bd_iov_count, desc->bd_iov, - &token); - if (maj != GSS_S_COMPLETE) { - CWARN("failed to sign bulk data: %x\n", maj); - return -EACCES; - } - } else { - /* privacy mode */ - if (desc->bd_iov_count == 0) - return 0; - - rc = sptlrpc_enc_pool_get_pages(desc); - if (rc) { - CERROR("bulk write: failed to allocate " - "encryption pages: %d\n", rc); - return rc; - } - - token.data = bsd->bsd_data; - token.len = lustre_msg_buflen(msg, offset) - - sizeof(*bsd); - - maj = lgss_wrap_bulk(gctx->gc_mechctx, desc, &token, 0); - if (maj != GSS_S_COMPLETE) { - CWARN("fail to encrypt bulk data: %x\n", maj); - return -EACCES; - } - } - } - - return 0; -} - -int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - struct gss_cli_ctx *gctx; - struct lustre_msg *rmsg, *vmsg; - struct ptlrpc_bulk_sec_desc *bsdr, *bsdv; - rawobj_t token; - __u32 maj; - int roff, voff; - - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_read || req->rq_bulk_write); - - switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) { - case SPTLRPC_SVC_NULL: - vmsg = req->rq_repdata; - LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 3); - voff = vmsg->lm_bufcount - 1; - - rmsg = req->rq_reqbuf; - LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 3); - roff = rmsg->lm_bufcount - 1; /* last segment */ - break; - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - vmsg = req->rq_repdata; - LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 4); - voff = vmsg->lm_bufcount - 2; - - rmsg = req->rq_reqbuf; - LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 4); - roff = rmsg->lm_bufcount - 2; /* second last segment */ - break; - case SPTLRPC_SVC_PRIV: - vmsg = req->rq_repdata; - LASSERT(vmsg != NULL && vmsg->lm_bufcount >= 2); - voff = vmsg->lm_bufcount - 1; - - rmsg = req->rq_clrbuf; - LASSERT(rmsg != NULL && rmsg->lm_bufcount >= 2); - roff = rmsg->lm_bufcount - 1; /* last segment */ - break; - default: - LBUG(); - } - - bsdr = lustre_msg_buf(rmsg, roff, sizeof(*bsdr)); - bsdv = lustre_msg_buf(vmsg, voff, sizeof(*bsdv)); - LASSERT(bsdr && bsdv); - - if (bsdr->bsd_version != bsdv->bsd_version || - bsdr->bsd_type != bsdv->bsd_type || - bsdr->bsd_svc != bsdv->bsd_svc) { - CERROR("bulk security descriptor mismatch: " - "(%u,%u,%u) != (%u,%u,%u)\n", - bsdr->bsd_version, bsdr->bsd_type, bsdr->bsd_svc, - bsdv->bsd_version, bsdv->bsd_type, bsdv->bsd_svc); - return -EPROTO; - } - - LASSERT(bsdv->bsd_svc == SPTLRPC_BULK_SVC_NULL || - bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG || - bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV); - - /* - * in privacy mode if return success, make sure bd_nob_transferred - * is the actual size of the clear text, otherwise upper layer - * may be surprised. - */ - if (req->rq_bulk_write) { - if (bsdv->bsd_flags & BSD_FL_ERR) { - CERROR("server reported bulk i/o failure\n"); - return -EIO; - } - - if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV) - desc->bd_nob_transferred = desc->bd_nob; - } else { - /* - * bulk read, upon return success, bd_nob_transferred is - * the size of plain text actually received. - */ - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - LASSERT(gctx->gc_mechctx); - - if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG) { - int i, nob; - - /* fix the actual data size */ - for (i = 0, nob = 0; i < desc->bd_iov_count; i++) { - if (desc->bd_iov[i].kiov_len + nob > - desc->bd_nob_transferred) { - desc->bd_iov[i].kiov_len = - desc->bd_nob_transferred - nob; - } - nob += desc->bd_iov[i].kiov_len; - } - - token.data = bsdv->bsd_data; - token.len = lustre_msg_buflen(vmsg, voff) - - sizeof(*bsdv); - - maj = lgss_verify_mic(gctx->gc_mechctx, 0, NULL, - desc->bd_iov_count, desc->bd_iov, - &token); - if (maj != GSS_S_COMPLETE) { - CERROR("failed to verify bulk read: %x\n", maj); - return -EACCES; - } - } else if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV) { - desc->bd_nob = bsdv->bsd_nob; - if (desc->bd_nob == 0) - return 0; - - token.data = bsdv->bsd_data; - token.len = lustre_msg_buflen(vmsg, voff) - - sizeof(*bsdr); - - maj = lgss_unwrap_bulk(gctx->gc_mechctx, desc, - &token, 1); - if (maj != GSS_S_COMPLETE) { - CERROR("failed to decrypt bulk read: %x\n", - maj); - return -EACCES; - } - - desc->bd_nob_transferred = desc->bd_nob; - } - } - - return 0; -} - -static int gss_prep_bulk(struct ptlrpc_bulk_desc *desc, - struct gss_ctx *mechctx) -{ - int rc; - - if (desc->bd_iov_count == 0) - return 0; - - rc = sptlrpc_enc_pool_get_pages(desc); - if (rc) - return rc; - - if (lgss_prep_bulk(mechctx, desc) != GSS_S_COMPLETE) - return -EACCES; - - return 0; -} - -int gss_cli_prep_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - int rc; - - LASSERT(req->rq_cli_ctx); - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_read); - - if (SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_BULK_SVC_PRIV) - return 0; - - rc = gss_prep_bulk(desc, ctx2gctx(req->rq_cli_ctx)->gc_mechctx); - if (rc) - CERROR("bulk read: failed to prepare encryption " - "pages: %d\n", rc); - - return rc; -} - -int gss_svc_prep_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - struct gss_svc_reqctx *grctx; - struct ptlrpc_bulk_sec_desc *bsd; - int rc; - - LASSERT(req->rq_svc_ctx); - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_write); - - grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - LASSERT(grctx->src_reqbsd); - LASSERT(grctx->src_repbsd); - LASSERT(grctx->src_ctx); - LASSERT(grctx->src_ctx->gsc_mechctx); - - bsd = grctx->src_reqbsd; - if (bsd->bsd_svc != SPTLRPC_BULK_SVC_PRIV) - return 0; - - rc = gss_prep_bulk(desc, grctx->src_ctx->gsc_mechctx); - if (rc) - CERROR("bulk write: failed to prepare encryption " - "pages: %d\n", rc); - - return rc; -} - -int gss_svc_unwrap_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - struct gss_svc_reqctx *grctx; - struct ptlrpc_bulk_sec_desc *bsdr, *bsdv; - rawobj_t token; - __u32 maj; - - LASSERT(req->rq_svc_ctx); - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_write); - - grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - - LASSERT(grctx->src_reqbsd); - LASSERT(grctx->src_repbsd); - LASSERT(grctx->src_ctx); - LASSERT(grctx->src_ctx->gsc_mechctx); - - bsdr = grctx->src_reqbsd; - bsdv = grctx->src_repbsd; - - /* bsdr has been sanity checked during unpacking */ - bsdv->bsd_version = 0; - bsdv->bsd_type = SPTLRPC_BULK_DEFAULT; - bsdv->bsd_svc = bsdr->bsd_svc; - bsdv->bsd_flags = 0; - - switch (bsdv->bsd_svc) { - case SPTLRPC_BULK_SVC_INTG: - token.data = bsdr->bsd_data; - token.len = grctx->src_reqbsd_size - sizeof(*bsdr); - - maj = lgss_verify_mic(grctx->src_ctx->gsc_mechctx, 0, NULL, - desc->bd_iov_count, desc->bd_iov, &token); - if (maj != GSS_S_COMPLETE) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("failed to verify bulk signature: %x\n", maj); - return -EACCES; - } - break; - case SPTLRPC_BULK_SVC_PRIV: - if (bsdr->bsd_nob != desc->bd_nob) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("prepared nob %d doesn't match the actual " - "nob %d\n", desc->bd_nob, bsdr->bsd_nob); - return -EPROTO; - } - - if (desc->bd_iov_count == 0) { - LASSERT(desc->bd_nob == 0); - break; - } - - token.data = bsdr->bsd_data; - token.len = grctx->src_reqbsd_size - sizeof(*bsdr); - - maj = lgss_unwrap_bulk(grctx->src_ctx->gsc_mechctx, - desc, &token, 0); - if (maj != GSS_S_COMPLETE) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("failed decrypt bulk data: %x\n", maj); - return -EACCES; - } - break; - } - - return 0; -} - -int gss_svc_wrap_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc) -{ - struct gss_svc_reqctx *grctx; - struct ptlrpc_bulk_sec_desc *bsdr, *bsdv; - rawobj_t token; - __u32 maj; - int rc; - - LASSERT(req->rq_svc_ctx); - LASSERT(req->rq_pack_bulk); - LASSERT(req->rq_bulk_read); - - grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - - LASSERT(grctx->src_reqbsd); - LASSERT(grctx->src_repbsd); - LASSERT(grctx->src_ctx); - LASSERT(grctx->src_ctx->gsc_mechctx); - - bsdr = grctx->src_reqbsd; - bsdv = grctx->src_repbsd; - - /* bsdr has been sanity checked during unpacking */ - bsdv->bsd_version = 0; - bsdv->bsd_type = SPTLRPC_BULK_DEFAULT; - bsdv->bsd_svc = bsdr->bsd_svc; - bsdv->bsd_flags = 0; - - switch (bsdv->bsd_svc) { - case SPTLRPC_BULK_SVC_INTG: - token.data = bsdv->bsd_data; - token.len = grctx->src_repbsd_size - sizeof(*bsdv); - - maj = lgss_get_mic(grctx->src_ctx->gsc_mechctx, 0, NULL, - desc->bd_iov_count, desc->bd_iov, &token); - if (maj != GSS_S_COMPLETE) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("failed to sign bulk data: %x\n", maj); - return -EACCES; - } - break; - case SPTLRPC_BULK_SVC_PRIV: - bsdv->bsd_nob = desc->bd_nob; - - if (desc->bd_iov_count == 0) { - LASSERT(desc->bd_nob == 0); - break; - } - - rc = sptlrpc_enc_pool_get_pages(desc); - if (rc) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("bulk read: failed to allocate encryption " - "pages: %d\n", rc); - return rc; - } - - token.data = bsdv->bsd_data; - token.len = grctx->src_repbsd_size - sizeof(*bsdv); - - maj = lgss_wrap_bulk(grctx->src_ctx->gsc_mechctx, - desc, &token, 1); - if (maj != GSS_S_COMPLETE) { - bsdv->bsd_flags |= BSD_FL_ERR; - CERROR("failed to encrypt bulk data: %x\n", maj); - return -EACCES; - } - break; - } - - return 0; -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c deleted file mode 100644 index c279edf5b2a5..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/ptlrpc/gss/gss_cli_upcall.c - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -/********************************************** - * gss context init/fini helper * - **********************************************/ - -static -int ctx_init_pack_request(struct obd_import *imp, - struct ptlrpc_request *req, - int lustre_srv, - uid_t uid, gid_t gid, - long token_size, - char __user *token) -{ - struct lustre_msg *msg = req->rq_reqbuf; - struct gss_sec *gsec; - struct gss_header *ghdr; - struct ptlrpc_user_desc *pud; - __u32 *p, size, offset = 2; - rawobj_t obj; - - LASSERT(msg->lm_bufcount <= 4); - LASSERT(req->rq_cli_ctx); - LASSERT(req->rq_cli_ctx->cc_sec); - - /* gss hdr */ - ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr)); - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_sp = (__u8) imp->imp_sec->ps_part; - ghdr->gh_flags = 0; - ghdr->gh_proc = PTLRPC_GSS_PROC_INIT; - ghdr->gh_seq = 0; - ghdr->gh_svc = SPTLRPC_SVC_NULL; - ghdr->gh_handle.len = 0; - - /* fix the user desc */ - if (req->rq_pack_udesc) { - ghdr->gh_flags |= LUSTRE_GSS_PACK_USER; - - pud = lustre_msg_buf(msg, offset, sizeof(*pud)); - LASSERT(pud); - pud->pud_uid = pud->pud_fsuid = uid; - pud->pud_gid = pud->pud_fsgid = gid; - pud->pud_cap = 0; - pud->pud_ngroups = 0; - offset++; - } - - /* security payload */ - p = lustre_msg_buf(msg, offset, 0); - size = msg->lm_buflens[offset]; - LASSERT(p); - - /* 1. lustre svc type */ - LASSERT(size > 4); - *p++ = cpu_to_le32(lustre_srv); - size -= 4; - - /* 2. target uuid */ - obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1; - obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid; - if (rawobj_serialize(&obj, &p, &size)) - LBUG(); - - /* 3. reverse context handle. actually only needed by root user, - * but we send it anyway. */ - gsec = sec2gsec(req->rq_cli_ctx->cc_sec); - obj.len = sizeof(gsec->gs_rvs_hdl); - obj.data = (__u8 *) &gsec->gs_rvs_hdl; - if (rawobj_serialize(&obj, &p, &size)) - LBUG(); - - /* 4. now the token */ - LASSERT(size >= (sizeof(__u32) + token_size)); - *p++ = cpu_to_le32(((__u32) token_size)); - if (copy_from_user(p, token, token_size)) { - CERROR("can't copy token\n"); - return -EFAULT; - } - size -= sizeof(__u32) + cfs_size_round4(token_size); - - req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset, - msg->lm_buflens[offset] - size, 0); - return 0; -} - -static -int ctx_init_parse_reply(struct lustre_msg *msg, int swabbed, - char __user *outbuf, long outlen) -{ - struct gss_rep_header *ghdr; - __u32 obj_len, round_len; - __u32 status, effective = 0; - - if (msg->lm_bufcount != 3) { - CERROR("unexpected bufcount %u\n", msg->lm_bufcount); - return -EPROTO; - } - - ghdr = (struct gss_rep_header *) gss_swab_header(msg, 0, swabbed); - if (ghdr == NULL) { - CERROR("unable to extract gss reply header\n"); - return -EPROTO; - } - - if (ghdr->gh_version != PTLRPC_GSS_VERSION) { - CERROR("invalid gss version %u\n", ghdr->gh_version); - return -EPROTO; - } - - if (outlen < (4 + 2) * 4 + cfs_size_round4(ghdr->gh_handle.len) + - cfs_size_round4(msg->lm_buflens[2])) { - CERROR("output buffer size %ld too small\n", outlen); - return -EFAULT; - } - - status = 0; - effective = 0; - - if (copy_to_user(outbuf, &status, 4)) - return -EFAULT; - outbuf += 4; - if (copy_to_user(outbuf, &ghdr->gh_major, 4)) - return -EFAULT; - outbuf += 4; - if (copy_to_user(outbuf, &ghdr->gh_minor, 4)) - return -EFAULT; - outbuf += 4; - if (copy_to_user(outbuf, &ghdr->gh_seqwin, 4)) - return -EFAULT; - outbuf += 4; - effective += 4 * 4; - - /* handle */ - obj_len = ghdr->gh_handle.len; - round_len = (obj_len + 3) & ~ 3; - if (copy_to_user(outbuf, &obj_len, 4)) - return -EFAULT; - outbuf += 4; - if (copy_to_user(outbuf, (char *) ghdr->gh_handle.data, round_len)) - return -EFAULT; - outbuf += round_len; - effective += 4 + round_len; - - /* out token */ - obj_len = msg->lm_buflens[2]; - round_len = (obj_len + 3) & ~ 3; - if (copy_to_user(outbuf, &obj_len, 4)) - return -EFAULT; - outbuf += 4; - if (copy_to_user(outbuf, lustre_msg_buf(msg, 2, 0), round_len)) - return -EFAULT; - outbuf += round_len; - effective += 4 + round_len; - - return effective; -} - -/* XXX move to where lgssd could see */ -struct lgssd_ioctl_param { - int version; /* in */ - int secid; /* in */ - char *uuid; /* in */ - int lustre_svc; /* in */ - uid_t uid; /* in */ - gid_t gid; /* in */ - long send_token_size;/* in */ - char *send_token; /* in */ - long reply_buf_size; /* in */ - char *reply_buf; /* in */ - long status; /* out */ - long reply_length; /* out */ -}; - -int gss_do_ctx_init_rpc(__user char *buffer, unsigned long count) -{ - struct obd_import *imp; - struct ptlrpc_request *req; - struct lgssd_ioctl_param param; - struct obd_device *obd; - char obdname[64]; - long lsize; - int rc; - - if (count != sizeof(param)) { - CERROR("ioctl size %lu, expect %lu, please check lgss_keyring " - "version\n", count, (unsigned long) sizeof(param)); - return -EINVAL; - } - if (copy_from_user(¶m, buffer, sizeof(param))) { - CERROR("failed copy data from lgssd\n"); - return -EFAULT; - } - - if (param.version != GSSD_INTERFACE_VERSION) { - CERROR("gssd interface version %d (expect %d)\n", - param.version, GSSD_INTERFACE_VERSION); - return -EINVAL; - } - - /* take name */ - if (strncpy_from_user(obdname, param.uuid, sizeof(obdname)) <= 0) { - CERROR("Invalid obdname pointer\n"); - return -EFAULT; - } - - obd = class_name2obd(obdname); - if (!obd) { - CERROR("no such obd %s\n", obdname); - return -EINVAL; - } - - if (unlikely(!obd->obd_set_up)) { - CERROR("obd %s not setup\n", obdname); - return -EINVAL; - } - - spin_lock(&obd->obd_dev_lock); - if (obd->obd_stopping) { - CERROR("obd %s has stopped\n", obdname); - spin_unlock(&obd->obd_dev_lock); - return -EINVAL; - } - - if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) && - strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) && - strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) { - CERROR("obd %s is not a client device\n", obdname); - spin_unlock(&obd->obd_dev_lock); - return -EINVAL; - } - spin_unlock(&obd->obd_dev_lock); - - down_read(&obd->u.cli.cl_sem); - if (obd->u.cli.cl_import == NULL) { - CERROR("obd %s: import has gone\n", obd->obd_name); - up_read(&obd->u.cli.cl_sem); - return -EINVAL; - } - imp = class_import_get(obd->u.cli.cl_import); - up_read(&obd->u.cli.cl_sem); - - if (imp->imp_deactive) { - CERROR("import has been deactivated\n"); - class_import_put(imp); - return -EINVAL; - } - - req = ptlrpc_request_alloc_pack(imp, &RQF_SEC_CTX, LUSTRE_OBD_VERSION, - SEC_CTX_INIT); - if (req == NULL) { - param.status = -ENOMEM; - goto out_copy; - } - - if (req->rq_cli_ctx->cc_sec->ps_id != param.secid) { - CWARN("original secid %d, now has changed to %d, " - "cancel this negotiation\n", param.secid, - req->rq_cli_ctx->cc_sec->ps_id); - param.status = -EINVAL; - goto out_copy; - } - - /* get token */ - rc = ctx_init_pack_request(imp, req, - param.lustre_svc, - param.uid, param.gid, - param.send_token_size, - param.send_token); - if (rc) { - param.status = rc; - goto out_copy; - } - - ptlrpc_request_set_replen(req); - - rc = ptlrpc_queue_wait(req); - if (rc) { - /* If any _real_ denial be made, we expect server return - * -EACCES reply or return success but indicate gss error - * inside reply message. All other errors are treated as - * timeout, caller might try the negotiation repeatedly, - * leave recovery decisions to general ptlrpc layer. - * - * FIXME maybe some other error code shouldn't be treated - * as timeout. */ - param.status = rc; - if (rc != -EACCES) - param.status = -ETIMEDOUT; - goto out_copy; - } - - LASSERT(req->rq_repdata); - lsize = ctx_init_parse_reply(req->rq_repdata, - ptlrpc_rep_need_swab(req), - param.reply_buf, param.reply_buf_size); - if (lsize < 0) { - param.status = (int) lsize; - goto out_copy; - } - - param.status = 0; - param.reply_length = lsize; - -out_copy: - if (copy_to_user(buffer, ¶m, sizeof(param))) - rc = -EFAULT; - else - rc = 0; - - class_import_put(imp); - ptlrpc_req_finished(req); - return rc; -} - -int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx) -{ - struct ptlrpc_cli_ctx *ctx = &gctx->gc_base; - struct obd_import *imp = ctx->cc_sec->ps_import; - struct ptlrpc_request *req; - struct ptlrpc_user_desc *pud; - int rc; - - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - if (cli_ctx_is_error(ctx) || !cli_ctx_is_uptodate(ctx)) { - CDEBUG(D_SEC, "ctx %p(%u->%s) not uptodate, " - "don't send destroy rpc\n", ctx, - ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec)); - return 0; - } - - might_sleep(); - - CWARN("%s ctx %p idx "LPX64" (%u->%s)\n", - sec_is_reverse(ctx->cc_sec) ? - "server finishing reverse" : "client finishing forward", - ctx, gss_handle_to_u64(&gctx->gc_handle), - ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec)); - - gctx->gc_proc = PTLRPC_GSS_PROC_DESTROY; - - req = ptlrpc_request_alloc(imp, &RQF_SEC_CTX); - if (req == NULL) { - CWARN("ctx %p(%u): fail to prepare rpc, destroy locally\n", - ctx, ctx->cc_vcred.vc_uid); - GOTO(out, rc = -ENOMEM); - } - - rc = ptlrpc_request_bufs_pack(req, LUSTRE_OBD_VERSION, SEC_CTX_FINI, - NULL, ctx); - if (rc) { - ptlrpc_request_free(req); - GOTO(out_ref, rc); - } - - /* fix the user desc */ - if (req->rq_pack_udesc) { - /* we rely the fact that this request is in AUTH mode, - * and user_desc at offset 2. */ - pud = lustre_msg_buf(req->rq_reqbuf, 2, sizeof(*pud)); - LASSERT(pud); - pud->pud_uid = pud->pud_fsuid = ctx->cc_vcred.vc_uid; - pud->pud_gid = pud->pud_fsgid = ctx->cc_vcred.vc_gid; - pud->pud_cap = 0; - pud->pud_ngroups = 0; - } - - req->rq_phase = RQ_PHASE_RPC; - rc = ptl_send_rpc(req, 1); - if (rc) - CWARN("ctx %p(%u->%s): rpc error %d, destroy locally\n", ctx, - ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), rc); - -out_ref: - ptlrpc_req_finished(req); -out: - return rc; -} - -int __init gss_init_cli_upcall(void) -{ - return 0; -} - -void __exit gss_exit_cli_upcall(void) -{ -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h deleted file mode 100644 index 37ec101e14e5..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_err.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * Adapted from MIT Kerberos 5-1.2.1 include/gssapi/gssapi.h - * - * Copyright (c) 2002 The Regents of the University of Michigan. - * All rights reserved. - * - * Andy Adamson <andros@umich.edu> - */ - -/* - * Copyright 1993 by OpenVision Technologies, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appears in all copies and - * that both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of OpenVision not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. OpenVision makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __PTLRPC_GSS_GSS_ERR_H_ -#define __PTLRPC_GSS_GSS_ERR_H_ - -typedef unsigned int OM_uint32; - -/* - * Flag bits for context-level services. - */ -#define GSS_C_DELEG_FLAG (1) -#define GSS_C_MUTUAL_FLAG (2) -#define GSS_C_REPLAY_FLAG (4) -#define GSS_C_SEQUENCE_FLAG (8) -#define GSS_C_CONF_FLAG (16) -#define GSS_C_INTEG_FLAG (32) -#define GSS_C_ANON_FLAG (64) -#define GSS_C_PROT_READY_FLAG (128) -#define GSS_C_TRANS_FLAG (256) - -/* - * Credential usage options - */ -#define GSS_C_BOTH (0) -#define GSS_C_INITIATE (1) -#define GSS_C_ACCEPT (2) - -/* - * Status code types for gss_display_status - */ -#define GSS_C_GSS_CODE (1) -#define GSS_C_MECH_CODE (2) - - -/* - * Define the default Quality of Protection for per-message services. Note - * that an implementation that offers multiple levels of QOP may either reserve - * a value (for example zero, as assumed here) to mean "default protection", or - * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit - * QOP value. However a value of 0 should always be interpreted by a GSSAPI - * implementation as a request for the default protection level. - */ -#define GSS_C_QOP_DEFAULT (0) - -/* - * Expiration time of 2^32-1 seconds means infinite lifetime for a - * credential or security context - */ -#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful) - - -/* Major status codes */ - -#define GSS_S_COMPLETE (0) - -/* - * Some "helper" definitions to make the status code macros obvious. - */ -#define GSS_C_CALLING_ERROR_OFFSET (24) -#define GSS_C_ROUTINE_ERROR_OFFSET (16) -#define GSS_C_SUPPLEMENTARY_OFFSET (0) -#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul) -#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul) -#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul) - -/* - * The macros that test status codes for error conditions. Note that the - * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now - * evaluates its argument only once. - */ -#define GSS_CALLING_ERROR(x) \ - ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) -#define GSS_ROUTINE_ERROR(x) \ - ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) -#define GSS_SUPPLEMENTARY_INFO(x) \ - ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) -#define GSS_ERROR(x) \ - ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ - (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) - -/* - * Now the actual status code definitions - */ - -/* - * Calling errors: - */ -#define GSS_S_CALL_INACCESSIBLE_READ \ - (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET) -#define GSS_S_CALL_INACCESSIBLE_WRITE \ - (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET) -#define GSS_S_CALL_BAD_STRUCTURE \ - (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET) - -/* - * Routine errors: - */ -#define GSS_S_BAD_MECH \ - (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_NAME \ - (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_NAMETYPE \ - (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_BINDINGS \ - (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_STATUS \ - (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_SIG \ - (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_NO_CRED \ - (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_NO_CONTEXT \ - (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DEFECTIVE_TOKEN \ - (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DEFECTIVE_CREDENTIAL \ - (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_CREDENTIALS_EXPIRED \ - (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_CONTEXT_EXPIRED \ - (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_FAILURE \ - (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_QOP \ - (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_UNAUTHORIZED \ - (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_UNAVAILABLE \ - (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DUPLICATE_ELEMENT \ - (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_NAME_NOT_MN \ - (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET) - -/* - * Supplementary info bits: - */ -#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) -#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) -#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) -#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) -#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) - -/* XXXX these are not part of the GSSAPI C bindings! (but should be) */ - -#define GSS_CALLING_ERROR_FIELD(x) \ - (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK) -#define GSS_ROUTINE_ERROR_FIELD(x) \ - (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK) -#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \ - (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK) - -/* XXXX This is a necessary evil until the spec is fixed */ -#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE - -#endif /* __PTLRPC_GSS_GSS_ERR_H_ */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c deleted file mode 100644 index 8dc5c724958d..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_generic_token.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2011, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/net/sunrpc/gss_generic_token.c - * - * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic/util_token.c - * - * Copyright (c) 2000 The Regents of the University of Michigan. - * All rights reserved. - * - * Andy Adamson <andros@umich.edu> - */ - -/* - * Copyright 1993 by OpenVision Technologies, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appears in all copies and - * that both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of OpenVision not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. OpenVision makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" -#include "gss_krb5.h" -#include "gss_asn1.h" - - -/* TWRITE_STR from gssapiP_generic.h */ -#define TWRITE_STR(ptr, str, len) \ - memcpy((ptr), (char *) (str), (len)); \ - (ptr) += (len); - -/* XXXX this code currently makes the assumption that a mech oid will - never be longer than 127 bytes. This assumption is not inherent in - the interfaces, so the code can be fixed if the OSI namespace - balloons unexpectedly. */ - -/* Each token looks like this: - -0x60 tag for APPLICATION 0, SEQUENCE - (constructed, definite-length) - <length> possible multiple bytes, need to parse/generate - 0x06 tag for OBJECT IDENTIFIER - <moid_length> compile-time constant string (assume 1 byte) - <moid_bytes> compile-time constant string - <inner_bytes> the ANY containing the application token - bytes 0,1 are the token type - bytes 2,n are the token data - -For the purposes of this abstraction, the token "header" consists of -the sequence tag and length octets, the mech OID DER encoding, and the -first two inner bytes, which indicate the token type. The token -"body" consists of everything else. - -*/ - -static -int der_length_size(int length) -{ - if (length < (1 << 7)) - return 1; - else if (length < (1 << 8)) - return 2; -#if (SIZEOF_INT == 2) - else - return 3; -#else - else if (length < (1 << 16)) - return 3; - else if (length < (1 << 24)) - return 4; - else - return 5; -#endif -} - -static -void der_write_length(unsigned char **buf, int length) -{ - if (length < (1 << 7)) { - *(*buf)++ = (unsigned char) length; - } else { - *(*buf)++ = (unsigned char) (der_length_size(length) + 127); -#if (SIZEOF_INT > 2) - if (length >= (1 << 24)) - *(*buf)++ = (unsigned char) (length >> 24); - if (length >= (1 << 16)) - *(*buf)++ = (unsigned char) ((length >> 16) & 0xff); -#endif - if (length >= (1 << 8)) - *(*buf)++ = (unsigned char) ((length >> 8) & 0xff); - *(*buf)++ = (unsigned char) (length & 0xff); - } -} - -/* - * returns decoded length, or < 0 on failure. Advances buf and - * decrements bufsize - */ -static -int der_read_length(unsigned char **buf, int *bufsize) -{ - unsigned char sf; - int ret; - - if (*bufsize < 1) - return -1; - sf = *(*buf)++; - (*bufsize)--; - if (sf & 0x80) { - sf &= 0x7f; - if (((*bufsize) - 1) < sf) - return -1; - if (sf > SIZEOF_INT) - return -1; - ret = 0; - for (; sf; sf--) { - ret = (ret << 8) + (*(*buf)++); - (*bufsize)--; - } - } else { - ret = sf; - } - - return ret; -} - -/* - * returns the length of a token, given the mech oid and the body size - */ -int g_token_size(rawobj_t *mech, unsigned int body_size) -{ - /* set body_size to sequence contents size */ - body_size += 4 + (int) mech->len; /* NEED overflow check */ - return (1 + der_length_size(body_size) + body_size); -} - -/* - * fills in a buffer with the token header. The buffer is assumed to - * be the right size. buf is advanced past the token header - */ -void g_make_token_header(rawobj_t *mech, int body_size, unsigned char **buf) -{ - *(*buf)++ = 0x60; - der_write_length(buf, 4 + mech->len + body_size); - *(*buf)++ = 0x06; - *(*buf)++ = (unsigned char) mech->len; - TWRITE_STR(*buf, mech->data, ((int) mech->len)); -} - -/* - * Given a buffer containing a token, reads and verifies the token, - * leaving buf advanced past the token header, and setting body_size - * to the number of remaining bytes. Returns 0 on success, - * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the - * mechanism in the token does not match the mech argument. buf and - * *body_size are left unmodified on error. - */ -__u32 g_verify_token_header(rawobj_t *mech, int *body_size, - unsigned char **buf_in, int toksize) -{ - unsigned char *buf = *buf_in; - int seqsize; - rawobj_t toid; - int ret = 0; - - toksize -= 1; - if (0 > toksize) - return (G_BAD_TOK_HEADER); - if (*buf++ != 0x60) - return (G_BAD_TOK_HEADER); - - seqsize = der_read_length(&buf, &toksize); - if (seqsize < 0) - return(G_BAD_TOK_HEADER); - - if (seqsize != toksize) - return (G_BAD_TOK_HEADER); - - toksize -= 1; - if (0 > toksize) - return (G_BAD_TOK_HEADER); - if (*buf++ != 0x06) - return (G_BAD_TOK_HEADER); - - toksize -= 1; - if (0 > toksize) - return (G_BAD_TOK_HEADER); - toid.len = *buf++; - - toksize -= toid.len; - if (0 > toksize) - return (G_BAD_TOK_HEADER); - toid.data = buf; - buf += toid.len; - - if (!g_OID_equal(&toid, mech)) - ret = G_WRONG_MECH; - - /* G_WRONG_MECH is not returned immediately because it's more - * important to return G_BAD_TOK_HEADER if the token header is - * in fact bad - */ - toksize -= 2; - if (0 > toksize) - return (G_BAD_TOK_HEADER); - - if (ret) - return (ret); - - if (!ret) { - *buf_in = buf; - *body_size = toksize; - } - - return (ret); -} - -/* - * Given a buffer containing a token, returns a copy of the mech oid in - * the parameter mech. - */ -__u32 g_get_mech_oid(rawobj_t *mech, rawobj_t *in_buf) -{ - unsigned char *buf = in_buf->data; - int len = in_buf->len; - int ret = 0; - int seqsize; - - len -= 1; - if (0 > len) - return (G_BAD_TOK_HEADER); - if (*buf++ != 0x60) - return (G_BAD_TOK_HEADER); - - seqsize = der_read_length(&buf, &len); - if (seqsize < 0) - return (G_BAD_TOK_HEADER); - - len -= 1; - if (0 > len) - return (G_BAD_TOK_HEADER); - if (*buf++ != 0x06) - return (G_BAD_TOK_HEADER); - - len -= 1; - if (0 > len) - return (G_BAD_TOK_HEADER); - mech->len = *buf++; - - len -= mech->len; - if (0 > len) - return (G_BAD_TOK_HEADER); - OBD_ALLOC_LARGE(mech->data, mech->len); - if (!mech->data) - return (G_BUFFER_ALLOC); - memcpy(mech->data, buf, mech->len); - - return ret; -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h deleted file mode 100644 index cbfc47cb3f7b..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_internal.h +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Modified from NFSv4 project for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -#ifndef __PTLRPC_GSS_GSS_INTERNAL_H_ -#define __PTLRPC_GSS_GSS_INTERNAL_H_ - -#include <lustre_sec.h> - -/* - * rawobj stuff - */ -typedef struct netobj_s { - __u32 len; - __u8 data[0]; -} netobj_t; - -#define NETOBJ_EMPTY ((netobj_t) { 0 }) - -typedef struct rawobj_s { - __u32 len; - __u8 *data; -} rawobj_t; - -#define RAWOBJ_EMPTY ((rawobj_t) { 0, NULL }) - -typedef struct rawobj_buf_s { - __u32 dataoff; - __u32 datalen; - __u32 buflen; - __u8 *buf; -} rawobj_buf_t; - -int rawobj_empty(rawobj_t *obj); -int rawobj_alloc(rawobj_t *obj, char *buf, int len); -void rawobj_free(rawobj_t *obj); -int rawobj_equal(rawobj_t *a, rawobj_t *b); -int rawobj_dup(rawobj_t *dest, rawobj_t *src); -int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen); -int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen); -int rawobj_extract_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen); -int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen); -int rawobj_extract_local_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen); -int rawobj_from_netobj(rawobj_t *rawobj, netobj_t *netobj); -int rawobj_from_netobj_alloc(rawobj_t *obj, netobj_t *netobj); - -int buffer_extract_bytes(const void **buf, __u32 *buflen, - void *res, __u32 reslen); - -/* - * several timeout values. client refresh upcall timeout we using - * default in pipefs implemnetation. - */ -#define __TIMEOUT_DELTA (10) - -#define GSS_SECINIT_RPC_TIMEOUT \ - (obd_timeout < __TIMEOUT_DELTA ? \ - __TIMEOUT_DELTA : obd_timeout - __TIMEOUT_DELTA) - -#define GSS_SECFINI_RPC_TIMEOUT (__TIMEOUT_DELTA) -#define GSS_SECSVC_UPCALL_TIMEOUT (GSS_SECINIT_RPC_TIMEOUT) - -/* - * default gc interval - */ -#define GSS_GC_INTERVAL (60 * 60) /* 60 minutes */ - -static inline -unsigned long gss_round_ctx_expiry(unsigned long expiry, - unsigned long sec_flags) -{ - if (sec_flags & PTLRPC_SEC_FL_REVERSE) - return expiry; - - if (get_seconds() + __TIMEOUT_DELTA <= expiry) - return expiry - __TIMEOUT_DELTA; - - return expiry; -} - -/* - * Max encryption element in block cipher algorithms. - */ -#define GSS_MAX_CIPHER_BLOCK (16) - -/* - * XXX make it visible of kernel and lgssd/lsvcgssd - */ -#define GSSD_INTERFACE_VERSION (1) - -#define PTLRPC_GSS_VERSION (1) - - -enum ptlrpc_gss_proc { - PTLRPC_GSS_PROC_DATA = 0, - PTLRPC_GSS_PROC_INIT = 1, - PTLRPC_GSS_PROC_CONTINUE_INIT = 2, - PTLRPC_GSS_PROC_DESTROY = 3, - PTLRPC_GSS_PROC_ERR = 4, -}; - -enum ptlrpc_gss_tgt { - LUSTRE_GSS_TGT_MGS = 0, - LUSTRE_GSS_TGT_MDS = 1, - LUSTRE_GSS_TGT_OSS = 2, -}; - -enum ptlrpc_gss_header_flags { - LUSTRE_GSS_PACK_BULK = 1, - LUSTRE_GSS_PACK_USER = 2, -}; - -static inline -__u32 import_to_gss_svc(struct obd_import *imp) -{ - const char *name = imp->imp_obd->obd_type->typ_name; - - if (!strcmp(name, LUSTRE_MGC_NAME)) - return LUSTRE_GSS_TGT_MGS; - if (!strcmp(name, LUSTRE_MDC_NAME)) - return LUSTRE_GSS_TGT_MDS; - if (!strcmp(name, LUSTRE_OSC_NAME)) - return LUSTRE_GSS_TGT_OSS; - LBUG(); - return 0; -} - -/* - * following 3 header must have the same size and offset - */ -struct gss_header { - __u8 gh_version; /* gss version */ - __u8 gh_sp; /* sec part */ - __u16 gh_pad0; - __u32 gh_flags; /* wrap flags */ - __u32 gh_proc; /* proc */ - __u32 gh_seq; /* sequence */ - __u32 gh_svc; /* service */ - __u32 gh_pad1; - __u32 gh_pad2; - __u32 gh_pad3; - netobj_t gh_handle; /* context handle */ -}; - -struct gss_rep_header { - __u8 gh_version; - __u8 gh_sp; - __u16 gh_pad0; - __u32 gh_flags; - __u32 gh_proc; - __u32 gh_major; - __u32 gh_minor; - __u32 gh_seqwin; - __u32 gh_pad2; - __u32 gh_pad3; - netobj_t gh_handle; -}; - -struct gss_err_header { - __u8 gh_version; - __u8 gh_sp; - __u16 gh_pad0; - __u32 gh_flags; - __u32 gh_proc; - __u32 gh_major; - __u32 gh_minor; - __u32 gh_pad1; - __u32 gh_pad2; - __u32 gh_pad3; - netobj_t gh_handle; -}; - -/* - * part of wire context information send from client which be saved and - * used later by server. - */ -struct gss_wire_ctx { - __u32 gw_flags; - __u32 gw_proc; - __u32 gw_seq; - __u32 gw_svc; - rawobj_t gw_handle; -}; - -#define PTLRPC_GSS_MAX_HANDLE_SIZE (8) -#define PTLRPC_GSS_HEADER_SIZE (sizeof(struct gss_header) + \ - PTLRPC_GSS_MAX_HANDLE_SIZE) - - -static inline __u64 gss_handle_to_u64(rawobj_t *handle) -{ - if (handle->len != PTLRPC_GSS_MAX_HANDLE_SIZE) - return -1; - return *((__u64 *) handle->data); -} - -#define GSS_SEQ_WIN (2048) -#define GSS_SEQ_WIN_MAIN GSS_SEQ_WIN -#define GSS_SEQ_WIN_BACK (128) -#define GSS_SEQ_REPACK_THRESHOLD (GSS_SEQ_WIN_MAIN / 2 + \ - GSS_SEQ_WIN_MAIN / 4) - -struct gss_svc_seq_data { - spinlock_t ssd_lock; - /* - * highest sequence number seen so far, for main and back window - */ - __u32 ssd_max_main; - __u32 ssd_max_back; - /* - * main and back window - * for i such that ssd_max - GSS_SEQ_WIN < i <= ssd_max, the i-th bit - * of ssd_win is nonzero iff sequence number i has been seen already. - */ - unsigned long ssd_win_main[GSS_SEQ_WIN_MAIN/BITS_PER_LONG]; - unsigned long ssd_win_back[GSS_SEQ_WIN_BACK/BITS_PER_LONG]; -}; - -struct gss_svc_ctx { - struct gss_ctx *gsc_mechctx; - struct gss_svc_seq_data gsc_seqdata; - rawobj_t gsc_rvs_hdl; - __u32 gsc_rvs_seq; - uid_t gsc_uid; - gid_t gsc_gid; - uid_t gsc_mapped_uid; - unsigned int gsc_usr_root:1, - gsc_usr_mds:1, - gsc_usr_oss:1, - gsc_remote:1, - gsc_reverse:1; -}; - -struct gss_svc_reqctx { - struct ptlrpc_svc_ctx src_base; - /* - * context - */ - struct gss_wire_ctx src_wirectx; - struct gss_svc_ctx *src_ctx; - /* - * record place of bulk_sec_desc in request/reply buffer - */ - struct ptlrpc_bulk_sec_desc *src_reqbsd; - int src_reqbsd_size; - struct ptlrpc_bulk_sec_desc *src_repbsd; - int src_repbsd_size; - /* - * flags - */ - unsigned int src_init:1, - src_init_continue:1, - src_err_notify:1; - int src_reserve_len; -}; - -struct gss_cli_ctx { - struct ptlrpc_cli_ctx gc_base; - __u32 gc_flavor; - __u32 gc_proc; - __u32 gc_win; - atomic_t gc_seq; - rawobj_t gc_handle; - struct gss_ctx *gc_mechctx; - /* handle for the buddy svc ctx */ - rawobj_t gc_svc_handle; -}; - -struct gss_cli_ctx_keyring { - struct gss_cli_ctx gck_base; - struct key *gck_key; - struct timer_list *gck_timer; -}; - -struct gss_sec { - struct ptlrpc_sec gs_base; - struct gss_api_mech *gs_mech; - spinlock_t gs_lock; - __u64 gs_rvs_hdl; -}; - -struct gss_sec_pipefs { - struct gss_sec gsp_base; - int gsp_chash_size; /* must be 2^n */ - struct hlist_head gsp_chash[0]; -}; - -/* - * FIXME cleanup the keyring upcall mutexes - */ -#define HAVE_KEYRING_UPCALL_SERIALIZED 1 - -struct gss_sec_keyring { - struct gss_sec gsk_base; - /* - * all contexts listed here. access is protected by sec spinlock. - */ - struct hlist_head gsk_clist; - /* - * specially point to root ctx (only one at a time). access is - * protected by sec spinlock. - */ - struct ptlrpc_cli_ctx *gsk_root_ctx; - /* - * specially serialize upcalls for root context. - */ - struct mutex gsk_root_uc_lock; - -#ifdef HAVE_KEYRING_UPCALL_SERIALIZED - struct mutex gsk_uc_lock; /* serialize upcalls */ -#endif -}; - -static inline struct gss_cli_ctx *ctx2gctx(struct ptlrpc_cli_ctx *ctx) -{ - return container_of(ctx, struct gss_cli_ctx, gc_base); -} - -static inline -struct gss_cli_ctx_keyring *ctx2gctx_keyring(struct ptlrpc_cli_ctx *ctx) -{ - return container_of(ctx2gctx(ctx), - struct gss_cli_ctx_keyring, gck_base); -} - -static inline struct gss_sec *sec2gsec(struct ptlrpc_sec *sec) -{ - return container_of(sec, struct gss_sec, gs_base); -} - -static inline struct gss_sec_pipefs *sec2gsec_pipefs(struct ptlrpc_sec *sec) -{ - return container_of(sec2gsec(sec), struct gss_sec_pipefs, gsp_base); -} - -static inline struct gss_sec_keyring *sec2gsec_keyring(struct ptlrpc_sec *sec) -{ - return container_of(sec2gsec(sec), struct gss_sec_keyring, gsk_base); -} - - -#define GSS_CTX_INIT_MAX_LEN (1024) - -/* - * This only guaranteed be enough for current krb5 des-cbc-crc . We might - * adjust this when new enc type or mech added in. - */ -#define GSS_PRIVBUF_PREFIX_LEN (32) -#define GSS_PRIVBUF_SUFFIX_LEN (32) - -static inline -struct gss_svc_reqctx *gss_svc_ctx2reqctx(struct ptlrpc_svc_ctx *ctx) -{ - LASSERT(ctx); - return container_of(ctx, struct gss_svc_reqctx, src_base); -} - -static inline -struct gss_svc_ctx *gss_svc_ctx2gssctx(struct ptlrpc_svc_ctx *ctx) -{ - LASSERT(ctx); - return gss_svc_ctx2reqctx(ctx)->src_ctx; -} - -/* sec_gss.c */ -int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred); -int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize); -int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); -int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); -int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); -int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); - -int gss_sec_install_rctx(struct obd_import *imp, struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx); -int gss_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, - int msgsize); -void gss_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req); -int gss_alloc_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, - int msgsize); -void gss_free_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req); -int gss_enlarge_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, - int segment, int newsize); - -int gss_svc_accept(struct ptlrpc_sec_policy *policy, - struct ptlrpc_request *req); -void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx); -int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen); -int gss_svc_authorize(struct ptlrpc_request *req); -void gss_svc_free_rs(struct ptlrpc_reply_state *rs); -void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx); - -int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx); -int cli_ctx_check_death(struct ptlrpc_cli_ctx *ctx); - -int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx, - struct ptlrpc_svc_ctx *svc_ctx); - -struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment, - int swabbed); -netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment); - -void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx); -int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor); -int gss_check_seq_num(struct gss_svc_seq_data *sd, __u32 seq_num, int set); - -int gss_sec_create_common(struct gss_sec *gsec, - struct ptlrpc_sec_policy *policy, - struct obd_import *imp, - struct ptlrpc_svc_ctx *ctx, - struct sptlrpc_flavor *sf); -void gss_sec_destroy_common(struct gss_sec *gsec); -void gss_sec_kill(struct ptlrpc_sec *sec); - -int gss_cli_ctx_init_common(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_ctx_ops *ctxops, - struct vfs_cred *vcred); -int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx); - -void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize); - -/* gss_keyring.c */ -int __init gss_init_keyring(void); -void __exit gss_exit_keyring(void); - -/* gss_pipefs.c */ -int __init gss_init_pipefs(void); -void __exit gss_exit_pipefs(void); - -/* gss_bulk.c */ -int gss_cli_prep_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); -int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); -int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); -int gss_svc_prep_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); -int gss_svc_unwrap_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); -int gss_svc_wrap_bulk(struct ptlrpc_request *req, - struct ptlrpc_bulk_desc *desc); - -/* gss_mech_switch.c */ -int init_kerberos_module(void); -void cleanup_kerberos_module(void); - -/* gss_generic_token.c */ -int g_token_size(rawobj_t *mech, unsigned int body_size); -void g_make_token_header(rawobj_t *mech, int body_size, unsigned char **buf); -__u32 g_verify_token_header(rawobj_t *mech, int *body_size, - unsigned char **buf_in, int toksize); - - -/* gss_cli_upcall.c */ -int gss_do_ctx_init_rpc(char *buffer, unsigned long count); -int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx); - -int __init gss_init_cli_upcall(void); -void __exit gss_exit_cli_upcall(void); - -/* gss_svc_upcall.c */ -__u64 gss_get_next_ctx_index(void); -int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, - struct gss_sec *gsec, - struct gss_cli_ctx *gctx); -int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle); -int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx); -int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq); -int gss_svc_upcall_handle_init(struct ptlrpc_request *req, - struct gss_svc_reqctx *grctx, - struct gss_wire_ctx *gw, - struct obd_device *target, - __u32 lustre_svc, - rawobj_t *rvs_hdl, - rawobj_t *in_token); -struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req, - struct gss_wire_ctx *gw); -void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx); -void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx); - -int __init gss_init_svc_upcall(void); -void __exit gss_exit_svc_upcall(void); - -/* lproc_gss.c */ -void gss_stat_oos_record_cli(int behind); -void gss_stat_oos_record_svc(int phase, int replay); - -int __init gss_init_lproc(void); -void __exit gss_exit_lproc(void); - -/* gss_krb5_mech.c */ -int __init init_kerberos_module(void); -void __exit cleanup_kerberos_module(void); - - -/* debug */ -static inline -void __dbg_memdump(char *name, void *ptr, int size) -{ - char *buf, *p = (char *) ptr; - int bufsize = size * 2 + 1, i; - - OBD_ALLOC(buf, bufsize); - if (!buf) { - CDEBUG(D_ERROR, "DUMP ERROR: can't alloc %d bytes\n", bufsize); - return; - } - - for (i = 0; i < size; i++) - sprintf(&buf[i+i], "%02x", (__u8) p[i]); - buf[size + size] = '\0'; - LCONSOLE_INFO("DUMP %s@%p(%d): %s\n", name, ptr, size, buf); - OBD_FREE(buf, bufsize); -} - -#endif /* __PTLRPC_GSS_GSS_INTERNAL_H_ */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c deleted file mode 100644 index 4642bbfb9273..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/ptlrpc/gss/gss_keyring.c - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/crypto.h> -#include <linux/key.h> -#include <linux/keyctl.h> -#include <linux/key-type.h> -#include <linux/mutex.h> -#include <asm/atomic.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_sec.h> -#include <lustre_net.h> -#include <lustre_import.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -static struct ptlrpc_sec_policy gss_policy_keyring; -static struct ptlrpc_ctx_ops gss_keyring_ctxops; -static struct key_type gss_key_type; - -static int sec_install_rctx_kr(struct ptlrpc_sec *sec, - struct ptlrpc_svc_ctx *svc_ctx); - -/* - * the timeout is only for the case that upcall child process die abnormally. - * in any other cases it should finally update kernel key. - * - * FIXME we'd better to incorporate the client & server side upcall timeouts - * into the framework of Adaptive Timeouts, but we need to figure out how to - * make sure that kernel knows the upcall processes is in-progress or died - * unexpectedly. - */ -#define KEYRING_UPCALL_TIMEOUT (obd_timeout + obd_timeout) - -/**************************************** - * internal helpers * - ****************************************/ - -#define DUMP_PROCESS_KEYRINGS(tsk) \ -{ \ - CWARN("DUMP PK: %s[%u,%u/%u](<-%s[%u,%u/%u]): " \ - "a %d, t %d, p %d, s %d, u %d, us %d, df %d\n", \ - tsk->comm, tsk->pid, tsk->uid, tsk->fsuid, \ - tsk->parent->comm, tsk->parent->pid, \ - tsk->parent->uid, tsk->parent->fsuid, \ - tsk->request_key_auth ? \ - tsk->request_key_auth->serial : 0, \ - key_cred(tsk)->thread_keyring ? \ - key_cred(tsk)->thread_keyring->serial : 0, \ - key_tgcred(tsk)->process_keyring ? \ - key_tgcred(tsk)->process_keyring->serial : 0, \ - key_tgcred(tsk)->session_keyring ? \ - key_tgcred(tsk)->session_keyring->serial : 0, \ - key_cred(tsk)->user->uid_keyring ? \ - key_cred(tsk)->user->uid_keyring->serial : 0, \ - key_cred(tsk)->user->session_keyring ? \ - key_cred(tsk)->user->session_keyring->serial : 0, \ - key_cred(tsk)->jit_keyring \ - ); \ -} - -#define DUMP_KEY(key) \ -{ \ - CWARN("DUMP KEY: %p(%d) ref %d u%u/g%u desc %s\n", \ - key, key->serial, atomic_read(&key->usage), \ - key->uid, key->gid, \ - key->description ? key->description : "n/a" \ - ); \ -} - -#define key_cred(tsk) ((tsk)->cred) -#define key_tgcred(tsk) ((tsk)->cred->tgcred) - -static inline void keyring_upcall_lock(struct gss_sec_keyring *gsec_kr) -{ -#ifdef HAVE_KEYRING_UPCALL_SERIALIZED - mutex_lock(&gsec_kr->gsk_uc_lock); -#endif -} - -static inline void keyring_upcall_unlock(struct gss_sec_keyring *gsec_kr) -{ -#ifdef HAVE_KEYRING_UPCALL_SERIALIZED - mutex_unlock(&gsec_kr->gsk_uc_lock); -#endif -} - -static inline void key_revoke_locked(struct key *key) -{ - set_bit(KEY_FLAG_REVOKED, &key->flags); -} - -static void ctx_upcall_timeout_kr(unsigned long data) -{ - struct ptlrpc_cli_ctx *ctx = (struct ptlrpc_cli_ctx *) data; - struct key *key = ctx2gctx_keyring(ctx)->gck_key; - - CWARN("ctx %p, key %p\n", ctx, key); - - LASSERT(key); - - cli_ctx_expire(ctx); - key_revoke_locked(key); -} - -static -void ctx_start_timer_kr(struct ptlrpc_cli_ctx *ctx, long timeout) -{ - struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx); - struct timer_list *timer = gctx_kr->gck_timer; - - LASSERT(timer); - - CDEBUG(D_SEC, "ctx %p: start timer %lds\n", ctx, timeout); - timeout = timeout * HZ + cfs_time_current(); - - init_timer(timer); - timer->expires = timeout; - timer->data = (unsigned long) ctx; - timer->function = ctx_upcall_timeout_kr; - - add_timer(timer); -} - -/* - * caller should make sure no race with other threads - */ -static -void ctx_clear_timer_kr(struct ptlrpc_cli_ctx *ctx) -{ - struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx); - struct timer_list *timer = gctx_kr->gck_timer; - - if (timer == NULL) - return; - - CDEBUG(D_SEC, "ctx %p, key %p\n", ctx, gctx_kr->gck_key); - - gctx_kr->gck_timer = NULL; - - del_singleshot_timer_sync(timer); - - OBD_FREE_PTR(timer); -} - -static -struct ptlrpc_cli_ctx *ctx_create_kr(struct ptlrpc_sec *sec, - struct vfs_cred *vcred) -{ - struct ptlrpc_cli_ctx *ctx; - struct gss_cli_ctx_keyring *gctx_kr; - - OBD_ALLOC_PTR(gctx_kr); - if (gctx_kr == NULL) - return NULL; - - OBD_ALLOC_PTR(gctx_kr->gck_timer); - if (gctx_kr->gck_timer == NULL) { - OBD_FREE_PTR(gctx_kr); - return NULL; - } - init_timer(gctx_kr->gck_timer); - - ctx = &gctx_kr->gck_base.gc_base; - - if (gss_cli_ctx_init_common(sec, ctx, &gss_keyring_ctxops, vcred)) { - OBD_FREE_PTR(gctx_kr->gck_timer); - OBD_FREE_PTR(gctx_kr); - return NULL; - } - - ctx->cc_expire = cfs_time_current_sec() + KEYRING_UPCALL_TIMEOUT; - clear_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags); - atomic_inc(&ctx->cc_refcount); /* for the caller */ - - return ctx; -} - -static void ctx_destroy_kr(struct ptlrpc_cli_ctx *ctx) -{ - struct ptlrpc_sec *sec = ctx->cc_sec; - struct gss_cli_ctx_keyring *gctx_kr = ctx2gctx_keyring(ctx); - - CDEBUG(D_SEC, "destroying ctx %p\n", ctx); - - /* at this time the association with key has been broken. */ - LASSERT(sec); - LASSERT(atomic_read(&sec->ps_refcount) > 0); - LASSERT(atomic_read(&sec->ps_nctx) > 0); - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0); - LASSERT(gctx_kr->gck_key == NULL); - - ctx_clear_timer_kr(ctx); - LASSERT(gctx_kr->gck_timer == NULL); - - if (gss_cli_ctx_fini_common(sec, ctx)) - return; - - OBD_FREE_PTR(gctx_kr); - - atomic_dec(&sec->ps_nctx); - sptlrpc_sec_put(sec); -} - -static void ctx_release_kr(struct ptlrpc_cli_ctx *ctx, int sync) -{ - if (sync) { - ctx_destroy_kr(ctx); - } else { - atomic_inc(&ctx->cc_refcount); - sptlrpc_gc_add_ctx(ctx); - } -} - -static void ctx_put_kr(struct ptlrpc_cli_ctx *ctx, int sync) -{ - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - if (atomic_dec_and_test(&ctx->cc_refcount)) - ctx_release_kr(ctx, sync); -} - -/* - * key <-> ctx association and rules: - * - ctx might not bind with any key - * - key/ctx binding is protected by key semaphore (if the key present) - * - key and ctx each take a reference of the other - * - ctx enlist/unlist is protected by ctx spinlock - * - never enlist a ctx after it's been unlisted - * - whoever do enlist should also do bind, lock key before enlist: - * - lock key -> lock ctx -> enlist -> unlock ctx -> bind -> unlock key - * - whoever do unlist should also do unbind: - * - lock key -> lock ctx -> unlist -> unlock ctx -> unbind -> unlock key - * - lock ctx -> unlist -> unlock ctx -> lock key -> unbind -> unlock key - */ - -static inline void spin_lock_if(spinlock_t *lock, int condition) -{ - if (condition) - spin_lock(lock); -} - -static inline void spin_unlock_if(spinlock_t *lock, int condition) -{ - if (condition) - spin_unlock(lock); -} - -static void ctx_enlist_kr(struct ptlrpc_cli_ctx *ctx, int is_root, int locked) -{ - struct ptlrpc_sec *sec = ctx->cc_sec; - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - - LASSERT(!test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags)); - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - spin_lock_if(&sec->ps_lock, !locked); - - atomic_inc(&ctx->cc_refcount); - set_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags); - hlist_add_head(&ctx->cc_cache, &gsec_kr->gsk_clist); - if (is_root) - gsec_kr->gsk_root_ctx = ctx; - - spin_unlock_if(&sec->ps_lock, !locked); -} - -/* - * Note after this get called, caller should not access ctx again because - * it might have been freed, unless caller hold at least one refcount of - * the ctx. - * - * return non-zero if we indeed unlist this ctx. - */ -static int ctx_unlist_kr(struct ptlrpc_cli_ctx *ctx, int locked) -{ - struct ptlrpc_sec *sec = ctx->cc_sec; - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - - /* if hashed bit has gone, leave the job to somebody who is doing it */ - if (test_and_clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0) - return 0; - - /* drop ref inside spin lock to prevent race with other operations */ - spin_lock_if(&sec->ps_lock, !locked); - - if (gsec_kr->gsk_root_ctx == ctx) - gsec_kr->gsk_root_ctx = NULL; - hlist_del_init(&ctx->cc_cache); - atomic_dec(&ctx->cc_refcount); - - spin_unlock_if(&sec->ps_lock, !locked); - - return 1; -} - -/* - * bind a key with a ctx together. - * caller must hold write lock of the key, as well as ref on key & ctx. - */ -static void bind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx) -{ - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(atomic_read(&key->usage) > 0); - LASSERT(ctx2gctx_keyring(ctx)->gck_key == NULL); - LASSERT(key->payload.data == NULL); - - /* at this time context may or may not in list. */ - key_get(key); - atomic_inc(&ctx->cc_refcount); - ctx2gctx_keyring(ctx)->gck_key = key; - key->payload.data = ctx; -} - -/* - * unbind a key and a ctx. - * caller must hold write lock, as well as a ref of the key. - */ -static void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx) -{ - LASSERT(key->payload.data == ctx); - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0); - - /* must revoke the key, or others may treat it as newly created */ - key_revoke_locked(key); - - key->payload.data = NULL; - ctx2gctx_keyring(ctx)->gck_key = NULL; - - /* once ctx get split from key, the timer is meaningless */ - ctx_clear_timer_kr(ctx); - - ctx_put_kr(ctx, 1); - key_put(key); -} - -/* - * given a ctx, unbind with its coupled key, if any. - * unbind could only be called once, so we don't worry the key be released - * by someone else. - */ -static void unbind_ctx_kr(struct ptlrpc_cli_ctx *ctx) -{ - struct key *key = ctx2gctx_keyring(ctx)->gck_key; - - if (key) { - LASSERT(key->payload.data == ctx); - - key_get(key); - down_write(&key->sem); - unbind_key_ctx(key, ctx); - up_write(&key->sem); - key_put(key); - } -} - -/* - * given a key, unbind with its coupled ctx, if any. - * caller must hold write lock, as well as a ref of the key. - */ -static void unbind_key_locked(struct key *key) -{ - struct ptlrpc_cli_ctx *ctx = key->payload.data; - - if (ctx) - unbind_key_ctx(key, ctx); -} - -/* - * unlist a ctx, and unbind from coupled key - */ -static void kill_ctx_kr(struct ptlrpc_cli_ctx *ctx) -{ - if (ctx_unlist_kr(ctx, 0)) - unbind_ctx_kr(ctx); -} - -/* - * given a key, unlist and unbind with the coupled ctx (if any). - * caller must hold write lock, as well as a ref of the key. - */ -static void kill_key_locked(struct key *key) -{ - struct ptlrpc_cli_ctx *ctx = key->payload.data; - - if (ctx && ctx_unlist_kr(ctx, 0)) - unbind_key_locked(key); -} - -/* - * caller should hold one ref on contexts in freelist. - */ -static void dispose_ctx_list_kr(struct hlist_head *freelist) -{ - struct hlist_node *next; - struct ptlrpc_cli_ctx *ctx; - struct gss_cli_ctx *gctx; - - hlist_for_each_entry_safe(ctx, next, freelist, cc_cache) { - hlist_del_init(&ctx->cc_cache); - - /* reverse ctx: update current seq to buddy svcctx if exist. - * ideally this should be done at gss_cli_ctx_finalize(), but - * the ctx destroy could be delayed by: - * 1) ctx still has reference; - * 2) ctx destroy is asynchronous; - * and reverse import call inval_all_ctx() require this be done - *_immediately_ otherwise newly created reverse ctx might copy - * the very old sequence number from svcctx. */ - gctx = ctx2gctx(ctx); - if (!rawobj_empty(&gctx->gc_svc_handle) && - sec_is_reverse(gctx->gc_base.cc_sec)) { - gss_svc_upcall_update_sequence(&gctx->gc_svc_handle, - (__u32) atomic_read(&gctx->gc_seq)); - } - - /* we need to wakeup waiting reqs here. the context might - * be forced released before upcall finished, then the - * late-arrived downcall can't find the ctx even. */ - sptlrpc_cli_ctx_wakeup(ctx); - - unbind_ctx_kr(ctx); - ctx_put_kr(ctx, 0); - } -} - -/* - * lookup a root context directly in a sec, return root ctx with a - * reference taken or NULL. - */ -static -struct ptlrpc_cli_ctx * sec_lookup_root_ctx_kr(struct ptlrpc_sec *sec) -{ - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - struct ptlrpc_cli_ctx *ctx = NULL; - - spin_lock(&sec->ps_lock); - - ctx = gsec_kr->gsk_root_ctx; - - if (ctx == NULL && unlikely(sec_is_reverse(sec))) { - struct ptlrpc_cli_ctx *tmp; - - /* reverse ctx, search root ctx in list, choose the one - * with shortest expire time, which is most possibly have - * an established peer ctx at client side. */ - hlist_for_each_entry(tmp, &gsec_kr->gsk_clist, cc_cache) { - if (ctx == NULL || ctx->cc_expire == 0 || - ctx->cc_expire > tmp->cc_expire) { - ctx = tmp; - /* promote to be root_ctx */ - gsec_kr->gsk_root_ctx = ctx; - } - } - } - - if (ctx) { - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(!hlist_empty(&gsec_kr->gsk_clist)); - atomic_inc(&ctx->cc_refcount); - } - - spin_unlock(&sec->ps_lock); - - return ctx; -} - -#define RVS_CTX_EXPIRE_NICE (10) - -static -void rvs_sec_install_root_ctx_kr(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *new_ctx, - struct key *key) -{ - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - struct ptlrpc_cli_ctx *ctx; - cfs_time_t now; - - LASSERT(sec_is_reverse(sec)); - - spin_lock(&sec->ps_lock); - - now = cfs_time_current_sec(); - - /* set all existing ctxs short expiry */ - hlist_for_each_entry(ctx, &gsec_kr->gsk_clist, cc_cache) { - if (ctx->cc_expire > now + RVS_CTX_EXPIRE_NICE) { - ctx->cc_early_expire = 1; - ctx->cc_expire = now + RVS_CTX_EXPIRE_NICE; - } - } - - /* if there's root_ctx there, instead obsolete the current - * immediately, we leave it continue operating for a little while. - * hopefully when the first backward rpc with newest ctx send out, - * the client side already have the peer ctx well established. */ - ctx_enlist_kr(new_ctx, gsec_kr->gsk_root_ctx ? 0 : 1, 1); - - if (key) - bind_key_ctx(key, new_ctx); - - spin_unlock(&sec->ps_lock); -} - -static void construct_key_desc(void *buf, int bufsize, - struct ptlrpc_sec *sec, uid_t uid) -{ - snprintf(buf, bufsize, "%d@%x", uid, sec->ps_id); - ((char *)buf)[bufsize - 1] = '\0'; -} - -/**************************************** - * sec apis * - ****************************************/ - -static -struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp, - struct ptlrpc_svc_ctx *svcctx, - struct sptlrpc_flavor *sf) -{ - struct gss_sec_keyring *gsec_kr; - - OBD_ALLOC(gsec_kr, sizeof(*gsec_kr)); - if (gsec_kr == NULL) - return NULL; - - INIT_HLIST_HEAD(&gsec_kr->gsk_clist); - gsec_kr->gsk_root_ctx = NULL; - mutex_init(&gsec_kr->gsk_root_uc_lock); -#ifdef HAVE_KEYRING_UPCALL_SERIALIZED - mutex_init(&gsec_kr->gsk_uc_lock); -#endif - - if (gss_sec_create_common(&gsec_kr->gsk_base, &gss_policy_keyring, - imp, svcctx, sf)) - goto err_free; - - if (svcctx != NULL && - sec_install_rctx_kr(&gsec_kr->gsk_base.gs_base, svcctx)) { - gss_sec_destroy_common(&gsec_kr->gsk_base); - goto err_free; - } - - return &gsec_kr->gsk_base.gs_base; - -err_free: - OBD_FREE(gsec_kr, sizeof(*gsec_kr)); - return NULL; -} - -static -void gss_sec_destroy_kr(struct ptlrpc_sec *sec) -{ - struct gss_sec *gsec = sec2gsec(sec); - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - - CDEBUG(D_SEC, "destroy %s@%p\n", sec->ps_policy->sp_name, sec); - - LASSERT(hlist_empty(&gsec_kr->gsk_clist)); - LASSERT(gsec_kr->gsk_root_ctx == NULL); - - gss_sec_destroy_common(gsec); - - OBD_FREE(gsec_kr, sizeof(*gsec_kr)); -} - -static inline int user_is_root(struct ptlrpc_sec *sec, struct vfs_cred *vcred) -{ - /* except the ROOTONLY flag, treat it as root user only if real uid - * is 0, euid/fsuid being 0 are handled as setuid scenarios */ - if (sec_is_rootonly(sec) || (vcred->vc_uid == 0)) - return 1; - else - return 0; -} - -/* - * unlink request key from it's ring, which is linked during request_key(). - * sadly, we have to 'guess' which keyring it's linked to. - * - * FIXME this code is fragile, depend on how request_key_link() is implemented. - */ -static void request_key_unlink(struct key *key) -{ - struct task_struct *tsk = current; - struct key *ring; - - switch (key_cred(tsk)->jit_keyring) { - case KEY_REQKEY_DEFL_DEFAULT: - case KEY_REQKEY_DEFL_THREAD_KEYRING: - ring = key_get(key_cred(tsk)->thread_keyring); - if (ring) - break; - case KEY_REQKEY_DEFL_PROCESS_KEYRING: - ring = key_get(key_tgcred(tsk)->process_keyring); - if (ring) - break; - case KEY_REQKEY_DEFL_SESSION_KEYRING: - rcu_read_lock(); - ring = key_get(rcu_dereference(key_tgcred(tsk) - ->session_keyring)); - rcu_read_unlock(); - if (ring) - break; - case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: - ring = key_get(key_cred(tsk)->user->session_keyring); - break; - case KEY_REQKEY_DEFL_USER_KEYRING: - ring = key_get(key_cred(tsk)->user->uid_keyring); - break; - case KEY_REQKEY_DEFL_GROUP_KEYRING: - default: - LBUG(); - } - - LASSERT(ring); - key_unlink(ring, key); - key_put(ring); -} - -static -struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec, - struct vfs_cred *vcred, - int create, int remove_dead) -{ - struct obd_import *imp = sec->ps_import; - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - struct ptlrpc_cli_ctx *ctx = NULL; - unsigned int is_root = 0, create_new = 0; - struct key *key; - char desc[24]; - char *coinfo; - int coinfo_size; - char *co_flags = ""; - - LASSERT(imp != NULL); - - is_root = user_is_root(sec, vcred); - - /* a little bit optimization for root context */ - if (is_root) { - ctx = sec_lookup_root_ctx_kr(sec); - /* - * Only lookup directly for REVERSE sec, which should - * always succeed. - */ - if (ctx || sec_is_reverse(sec)) - return ctx; - } - - LASSERT(create != 0); - - /* for root context, obtain lock and check again, this time hold - * the root upcall lock, make sure nobody else populated new root - * context after last check. */ - if (is_root) { - mutex_lock(&gsec_kr->gsk_root_uc_lock); - - ctx = sec_lookup_root_ctx_kr(sec); - if (ctx) - goto out; - - /* update reverse handle for root user */ - sec2gsec(sec)->gs_rvs_hdl = gss_get_next_ctx_index(); - - switch (sec->ps_part) { - case LUSTRE_SP_MDT: - co_flags = "m"; - break; - case LUSTRE_SP_OST: - co_flags = "o"; - break; - case LUSTRE_SP_MGC: - co_flags = "rmo"; - break; - case LUSTRE_SP_CLI: - co_flags = "r"; - break; - case LUSTRE_SP_MGS: - default: - LBUG(); - } - } - - /* in case of setuid, key will be constructed as owner of fsuid/fsgid, - * but we do authentication based on real uid/gid. the key permission - * bits will be exactly as POS_ALL, so only processes who subscribed - * this key could have the access, although the quota might be counted - * on others (fsuid/fsgid). - * - * keyring will use fsuid/fsgid as upcall parameters, so we have to - * encode real uid/gid into callout info. - */ - - construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid); - - /* callout info format: - * secid:mech:uid:gid:flags:svc_type:peer_nid:target_uuid - */ - coinfo_size = sizeof(struct obd_uuid) + MAX_OBD_NAME + 64; - OBD_ALLOC(coinfo, coinfo_size); - if (coinfo == NULL) - goto out; - - snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s", - sec->ps_id, sec2gsec(sec)->gs_mech->gm_name, - vcred->vc_uid, vcred->vc_gid, - co_flags, import_to_gss_svc(imp), - imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name); - - CDEBUG(D_SEC, "requesting key for %s\n", desc); - - keyring_upcall_lock(gsec_kr); - key = request_key(&gss_key_type, desc, coinfo); - keyring_upcall_unlock(gsec_kr); - - OBD_FREE(coinfo, coinfo_size); - - if (IS_ERR(key)) { - CERROR("failed request key: %ld\n", PTR_ERR(key)); - goto out; - } - CDEBUG(D_SEC, "obtained key %08x for %s\n", key->serial, desc); - - /* once payload.data was pointed to a ctx, it never changes until - * we de-associate them; but parallel request_key() may return - * a key with payload.data == NULL at the same time. so we still - * need wirtelock of key->sem to serialize them. */ - down_write(&key->sem); - - if (likely(key->payload.data != NULL)) { - ctx = key->payload.data; - - LASSERT(atomic_read(&ctx->cc_refcount) >= 1); - LASSERT(ctx2gctx_keyring(ctx)->gck_key == key); - LASSERT(atomic_read(&key->usage) >= 2); - - /* simply take a ref and return. it's upper layer's - * responsibility to detect & replace dead ctx. */ - atomic_inc(&ctx->cc_refcount); - } else { - /* pre initialization with a cli_ctx. this can't be done in - * key_instantiate() because we'v no enough information - * there. */ - ctx = ctx_create_kr(sec, vcred); - if (ctx != NULL) { - ctx_enlist_kr(ctx, is_root, 0); - bind_key_ctx(key, ctx); - - ctx_start_timer_kr(ctx, KEYRING_UPCALL_TIMEOUT); - - CDEBUG(D_SEC, "installed key %p <-> ctx %p (sec %p)\n", - key, ctx, sec); - } else { - /* we'd prefer to call key_revoke(), but we more like - * to revoke it within this key->sem locked period. */ - key_revoke_locked(key); - } - - create_new = 1; - } - - up_write(&key->sem); - - if (is_root && create_new) - request_key_unlink(key); - - key_put(key); -out: - if (is_root) - mutex_unlock(&gsec_kr->gsk_root_uc_lock); - return ctx; -} - -static -void gss_sec_release_ctx_kr(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx, - int sync) -{ - LASSERT(atomic_read(&sec->ps_refcount) > 0); - LASSERT(atomic_read(&ctx->cc_refcount) == 0); - ctx_release_kr(ctx, sync); -} - -/* - * flush context of normal user, we must resort to keyring itself to find out - * contexts which belong to me. - * - * Note here we suppose only to flush _my_ context, the "uid" will - * be ignored in the search. - */ -static -void flush_user_ctx_cache_kr(struct ptlrpc_sec *sec, - uid_t uid, - int grace, int force) -{ - struct key *key; - char desc[24]; - - /* nothing to do for reverse or rootonly sec */ - if (sec_is_reverse(sec) || sec_is_rootonly(sec)) - return; - - construct_key_desc(desc, sizeof(desc), sec, uid); - - /* there should be only one valid key, but we put it in the - * loop in case of any weird cases */ - for (;;) { - key = request_key(&gss_key_type, desc, NULL); - if (IS_ERR(key)) { - CDEBUG(D_SEC, "No more key found for current user\n"); - break; - } - - down_write(&key->sem); - - kill_key_locked(key); - - /* kill_key_locked() should usually revoke the key, but we - * revoke it again to make sure, e.g. some case the key may - * not well coupled with a context. */ - key_revoke_locked(key); - - up_write(&key->sem); - - key_put(key); - } -} - -/* - * flush context of root or all, we iterate through the list. - */ -static -void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec, - uid_t uid, - int grace, int force) -{ - struct gss_sec_keyring *gsec_kr; - struct hlist_head freelist = HLIST_HEAD_INIT; - struct hlist_node *next; - struct ptlrpc_cli_ctx *ctx; - - gsec_kr = sec2gsec_keyring(sec); - - spin_lock(&sec->ps_lock); - hlist_for_each_entry_safe(ctx, next, - &gsec_kr->gsk_clist, cc_cache) { - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - if (uid != -1 && uid != ctx->cc_vcred.vc_uid) - continue; - - /* at this moment there's at least 2 base reference: - * key association and in-list. */ - if (atomic_read(&ctx->cc_refcount) > 2) { - if (!force) - continue; - CWARN("flush busy ctx %p(%u->%s, extra ref %d)\n", - ctx, ctx->cc_vcred.vc_uid, - sec2target_str(ctx->cc_sec), - atomic_read(&ctx->cc_refcount) - 2); - } - - set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags); - if (!grace) - clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags); - - atomic_inc(&ctx->cc_refcount); - - if (ctx_unlist_kr(ctx, 1)) { - hlist_add_head(&ctx->cc_cache, &freelist); - } else { - LASSERT(atomic_read(&ctx->cc_refcount) >= 2); - atomic_dec(&ctx->cc_refcount); - } - } - spin_unlock(&sec->ps_lock); - - dispose_ctx_list_kr(&freelist); -} - -static -int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec, - uid_t uid, int grace, int force) -{ - CDEBUG(D_SEC, "sec %p(%d, nctx %d), uid %d, grace %d, force %d\n", - sec, atomic_read(&sec->ps_refcount), - atomic_read(&sec->ps_nctx), - uid, grace, force); - - if (uid != -1 && uid != 0) - flush_user_ctx_cache_kr(sec, uid, grace, force); - else - flush_spec_ctx_cache_kr(sec, uid, grace, force); - - return 0; -} - -static -void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec) -{ - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - struct hlist_head freelist = HLIST_HEAD_INIT; - struct hlist_node *next; - struct ptlrpc_cli_ctx *ctx; - - CWARN("running gc\n"); - - spin_lock(&sec->ps_lock); - hlist_for_each_entry_safe(ctx, next, - &gsec_kr->gsk_clist, cc_cache) { - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - atomic_inc(&ctx->cc_refcount); - - if (cli_ctx_check_death(ctx) && ctx_unlist_kr(ctx, 1)) { - hlist_add_head(&ctx->cc_cache, &freelist); - CWARN("unhashed ctx %p\n", ctx); - } else { - LASSERT(atomic_read(&ctx->cc_refcount) >= 2); - atomic_dec(&ctx->cc_refcount); - } - } - spin_unlock(&sec->ps_lock); - - dispose_ctx_list_kr(&freelist); -} - -static -int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq) -{ - struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); - struct hlist_node *next; - struct ptlrpc_cli_ctx *ctx; - struct gss_cli_ctx *gctx; - time_t now = cfs_time_current_sec(); - - spin_lock(&sec->ps_lock); - hlist_for_each_entry_safe(ctx, next, - &gsec_kr->gsk_clist, cc_cache) { - struct key *key; - char flags_str[40]; - char mech[40]; - - gctx = ctx2gctx(ctx); - key = ctx2gctx_keyring(ctx)->gck_key; - - gss_cli_ctx_flags2str(ctx->cc_flags, - flags_str, sizeof(flags_str)); - - if (gctx->gc_mechctx) - lgss_display(gctx->gc_mechctx, mech, sizeof(mech)); - else - snprintf(mech, sizeof(mech), "N/A"); - mech[sizeof(mech) - 1] = '\0'; - - seq_printf(seq, "%p: uid %u, ref %d, expire %ld(%+ld), fl %s, " - "seq %d, win %u, key %08x(ref %d), " - "hdl "LPX64":"LPX64", mech: %s\n", - ctx, ctx->cc_vcred.vc_uid, - atomic_read(&ctx->cc_refcount), - ctx->cc_expire, - ctx->cc_expire ? ctx->cc_expire - now : 0, - flags_str, - atomic_read(&gctx->gc_seq), - gctx->gc_win, - key ? key->serial : 0, - key ? atomic_read(&key->usage) : 0, - gss_handle_to_u64(&gctx->gc_handle), - gss_handle_to_u64(&gctx->gc_svc_handle), - mech); - } - spin_unlock(&sec->ps_lock); - - return 0; -} - -/**************************************** - * cli_ctx apis * - ****************************************/ - -static -int gss_cli_ctx_refresh_kr(struct ptlrpc_cli_ctx *ctx) -{ - /* upcall is already on the way */ - return 0; -} - -static -int gss_cli_ctx_validate_kr(struct ptlrpc_cli_ctx *ctx) -{ - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(ctx->cc_sec); - - if (cli_ctx_check_death(ctx)) { - kill_ctx_kr(ctx); - return 1; - } - - if (cli_ctx_is_ready(ctx)) - return 0; - return 1; -} - -static -void gss_cli_ctx_die_kr(struct ptlrpc_cli_ctx *ctx, int grace) -{ - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(ctx->cc_sec); - - cli_ctx_expire(ctx); - kill_ctx_kr(ctx); -} - -/**************************************** - * (reverse) service * - ****************************************/ - -/* - * reverse context could have nothing to do with keyrings. here we still keep - * the version which bind to a key, for future reference. - */ -#define HAVE_REVERSE_CTX_NOKEY - - -static -int sec_install_rctx_kr(struct ptlrpc_sec *sec, - struct ptlrpc_svc_ctx *svc_ctx) -{ - struct ptlrpc_cli_ctx *cli_ctx; - struct vfs_cred vcred = { 0, 0 }; - int rc; - - LASSERT(sec); - LASSERT(svc_ctx); - - cli_ctx = ctx_create_kr(sec, &vcred); - if (cli_ctx == NULL) - return -ENOMEM; - - rc = gss_copy_rvc_cli_ctx(cli_ctx, svc_ctx); - if (rc) { - CERROR("failed copy reverse cli ctx: %d\n", rc); - - ctx_put_kr(cli_ctx, 1); - return rc; - } - - rvs_sec_install_root_ctx_kr(sec, cli_ctx, NULL); - - ctx_put_kr(cli_ctx, 1); - - return 0; -} - - -/**************************************** - * service apis * - ****************************************/ - -static -int gss_svc_accept_kr(struct ptlrpc_request *req) -{ - return gss_svc_accept(&gss_policy_keyring, req); -} - -static -int gss_svc_install_rctx_kr(struct obd_import *imp, - struct ptlrpc_svc_ctx *svc_ctx) -{ - struct ptlrpc_sec *sec; - int rc; - - sec = sptlrpc_import_sec_ref(imp); - LASSERT(sec); - - rc = sec_install_rctx_kr(sec, svc_ctx); - sptlrpc_sec_put(sec); - - return rc; -} - -/**************************************** - * key apis * - ****************************************/ - -static -int gss_kt_instantiate(struct key *key, const void *data, size_t datalen) -{ - int rc; - - if (data != NULL || datalen != 0) { - CERROR("invalid: data %p, len %lu\n", data, (long)datalen); - return -EINVAL; - } - - if (key->payload.data != 0) { - CERROR("key already have payload\n"); - return -EINVAL; - } - - /* link the key to session keyring, so following context negotiation - * rpc fired from user space could find this key. This will be unlinked - * automatically when upcall processes die. - * - * we can't do this through keyctl from userspace, because the upcall - * might be neither possessor nor owner of the key (setuid). - * - * the session keyring is created upon upcall, and don't change all - * the way until upcall finished, so rcu lock is not needed here. - */ - LASSERT(key_tgcred(current)->session_keyring); - - lockdep_off(); - rc = key_link(key_tgcred(current)->session_keyring, key); - lockdep_on(); - if (unlikely(rc)) { - CERROR("failed to link key %08x to keyring %08x: %d\n", - key->serial, - key_tgcred(current)->session_keyring->serial, rc); - return rc; - } - - CDEBUG(D_SEC, "key %p instantiated, ctx %p\n", key, key->payload.data); - return 0; -} - -/* - * called with key semaphore write locked. it means we can operate - * on the context without fear of losing refcount. - */ -static -int gss_kt_update(struct key *key, const void *data, size_t datalen) -{ - struct ptlrpc_cli_ctx *ctx = key->payload.data; - struct gss_cli_ctx *gctx; - rawobj_t tmpobj = RAWOBJ_EMPTY; - __u32 datalen32 = (__u32) datalen; - int rc; - - if (data == NULL || datalen == 0) { - CWARN("invalid: data %p, len %lu\n", data, (long)datalen); - return -EINVAL; - } - - /* if upcall finished negotiation too fast (mostly likely because - * of local error happened) and call kt_update(), the ctx - * might be still NULL. but the key will finally be associate - * with a context, or be revoked. if key status is fine, return - * -EAGAIN to allow userspace sleep a while and call again. */ - if (ctx == NULL) { - CDEBUG(D_SEC, "update too soon: key %p(%x) flags %lx\n", - key, key->serial, key->flags); - - rc = key_validate(key); - if (rc == 0) - return -EAGAIN; - else - return rc; - } - - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(ctx->cc_sec); - - ctx_clear_timer_kr(ctx); - - /* don't proceed if already refreshed */ - if (cli_ctx_is_refreshed(ctx)) { - CWARN("ctx already done refresh\n"); - return 0; - } - - sptlrpc_cli_ctx_get(ctx); - gctx = ctx2gctx(ctx); - - rc = buffer_extract_bytes(&data, &datalen32, &gctx->gc_win, - sizeof(gctx->gc_win)); - if (rc) { - CERROR("failed extract seq_win\n"); - goto out; - } - - if (gctx->gc_win == 0) { - __u32 nego_rpc_err, nego_gss_err; - - rc = buffer_extract_bytes(&data, &datalen32, &nego_rpc_err, - sizeof(nego_rpc_err)); - if (rc) { - CERROR("failed to extrace rpc rc\n"); - goto out; - } - - rc = buffer_extract_bytes(&data, &datalen32, &nego_gss_err, - sizeof(nego_gss_err)); - if (rc) { - CERROR("failed to extrace gss rc\n"); - goto out; - } - - CERROR("negotiation: rpc err %d, gss err %x\n", - nego_rpc_err, nego_gss_err); - - rc = nego_rpc_err ? nego_rpc_err : -EACCES; - } else { - rc = rawobj_extract_local_alloc(&gctx->gc_handle, - (__u32 **) &data, &datalen32); - if (rc) { - CERROR("failed extract handle\n"); - goto out; - } - - rc = rawobj_extract_local(&tmpobj, (__u32 **) &data,&datalen32); - if (rc) { - CERROR("failed extract mech\n"); - goto out; - } - - rc = lgss_import_sec_context(&tmpobj, - sec2gsec(ctx->cc_sec)->gs_mech, - &gctx->gc_mechctx); - if (rc != GSS_S_COMPLETE) - CERROR("failed import context\n"); - else - rc = 0; - } -out: - /* we don't care what current status of this ctx, even someone else - * is operating on the ctx at the same time. we just add up our own - * opinions here. */ - if (rc == 0) { - gss_cli_ctx_uptodate(gctx); - } else { - /* this will also revoke the key. has to be done before - * wakeup waiters otherwise they can find the stale key */ - kill_key_locked(key); - - cli_ctx_expire(ctx); - - if (rc != -ERESTART) - set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags); - } - - /* let user space think it's a success */ - sptlrpc_cli_ctx_put(ctx, 1); - return 0; -} - -static -int gss_kt_match(const struct key *key, const void *desc) -{ - return (strcmp(key->description, (const char *) desc) == 0); -} - -static -void gss_kt_destroy(struct key *key) -{ - LASSERT(key->payload.data == NULL); - CDEBUG(D_SEC, "destroy key %p\n", key); -} - -static -void gss_kt_describe(const struct key *key, struct seq_file *s) -{ - if (key->description == NULL) - seq_puts(s, "[null]"); - else - seq_puts(s, key->description); -} - -static struct key_type gss_key_type = -{ - .name = "lgssc", - .def_datalen = 0, - .instantiate = gss_kt_instantiate, - .update = gss_kt_update, - .match = gss_kt_match, - .destroy = gss_kt_destroy, - .describe = gss_kt_describe, -}; - -/**************************************** - * lustre gss keyring policy * - ****************************************/ - -static struct ptlrpc_ctx_ops gss_keyring_ctxops = { - .match = gss_cli_ctx_match, - .refresh = gss_cli_ctx_refresh_kr, - .validate = gss_cli_ctx_validate_kr, - .die = gss_cli_ctx_die_kr, - .sign = gss_cli_ctx_sign, - .verify = gss_cli_ctx_verify, - .seal = gss_cli_ctx_seal, - .unseal = gss_cli_ctx_unseal, - .wrap_bulk = gss_cli_ctx_wrap_bulk, - .unwrap_bulk = gss_cli_ctx_unwrap_bulk, -}; - -static struct ptlrpc_sec_cops gss_sec_keyring_cops = { - .create_sec = gss_sec_create_kr, - .destroy_sec = gss_sec_destroy_kr, - .kill_sec = gss_sec_kill, - .lookup_ctx = gss_sec_lookup_ctx_kr, - .release_ctx = gss_sec_release_ctx_kr, - .flush_ctx_cache = gss_sec_flush_ctx_cache_kr, - .gc_ctx = gss_sec_gc_ctx_kr, - .install_rctx = gss_sec_install_rctx, - .alloc_reqbuf = gss_alloc_reqbuf, - .free_reqbuf = gss_free_reqbuf, - .alloc_repbuf = gss_alloc_repbuf, - .free_repbuf = gss_free_repbuf, - .enlarge_reqbuf = gss_enlarge_reqbuf, - .display = gss_sec_display_kr, -}; - -static struct ptlrpc_sec_sops gss_sec_keyring_sops = { - .accept = gss_svc_accept_kr, - .invalidate_ctx = gss_svc_invalidate_ctx, - .alloc_rs = gss_svc_alloc_rs, - .authorize = gss_svc_authorize, - .free_rs = gss_svc_free_rs, - .free_ctx = gss_svc_free_ctx, - .prep_bulk = gss_svc_prep_bulk, - .unwrap_bulk = gss_svc_unwrap_bulk, - .wrap_bulk = gss_svc_wrap_bulk, - .install_rctx = gss_svc_install_rctx_kr, -}; - -static struct ptlrpc_sec_policy gss_policy_keyring = { - .sp_owner = THIS_MODULE, - .sp_name = "gss.keyring", - .sp_policy = SPTLRPC_POLICY_GSS, - .sp_cops = &gss_sec_keyring_cops, - .sp_sops = &gss_sec_keyring_sops, -}; - - -int __init gss_init_keyring(void) -{ - int rc; - - rc = register_key_type(&gss_key_type); - if (rc) { - CERROR("failed to register keyring type: %d\n", rc); - return rc; - } - - rc = sptlrpc_register_policy(&gss_policy_keyring); - if (rc) { - unregister_key_type(&gss_key_type); - return rc; - } - - return 0; -} - -void __exit gss_exit_keyring(void) -{ - unregister_key_type(&gss_key_type); - sptlrpc_unregister_policy(&gss_policy_keyring); -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h deleted file mode 100644 index 676d4b96311a..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/include/linux/sunrpc/gss_krb5_types.h - * - * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, - * lib/gssapi/krb5/gssapiP_krb5.h, and others - * - * Copyright (c) 2000 The Regents of the University of Michigan. - * All rights reserved. - * - * Andy Adamson <andros@umich.edu> - * Bruce Fields <bfields@umich.edu> - */ - -/* - * Copyright 1995 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - */ - -#ifndef PTLRPC_GSS_KRB5_H -#define PTLRPC_GSS_KRB5_H - -/* - * RFC 4142 - */ - -#define KG_USAGE_ACCEPTOR_SEAL 22 -#define KG_USAGE_ACCEPTOR_SIGN 23 -#define KG_USAGE_INITIATOR_SEAL 24 -#define KG_USAGE_INITIATOR_SIGN 25 - -#define KG_TOK_MIC_MSG 0x0404 -#define KG_TOK_WRAP_MSG 0x0504 - -#define FLAG_SENDER_IS_ACCEPTOR 0x01 -#define FLAG_WRAP_CONFIDENTIAL 0x02 -#define FLAG_ACCEPTOR_SUBKEY 0x04 - -struct krb5_header { - __u16 kh_tok_id; /* token id */ - __u8 kh_flags; /* acceptor flags */ - __u8 kh_filler; /* 0xff */ - __u16 kh_ec; /* extra count */ - __u16 kh_rrc; /* right rotation count */ - __u64 kh_seq; /* sequence number */ - __u8 kh_cksum[0]; /* checksum */ -}; - -struct krb5_keyblock { - rawobj_t kb_key; - struct ll_crypto_cipher *kb_tfm; -}; - -struct krb5_ctx { - unsigned int kc_initiate:1, - kc_cfx:1, - kc_seed_init:1, - kc_have_acceptor_subkey:1; - __s32 kc_endtime; - __u8 kc_seed[16]; - __u64 kc_seq_send; - __u64 kc_seq_recv; - __u32 kc_enctype; - struct krb5_keyblock kc_keye; /* encryption */ - struct krb5_keyblock kc_keyi; /* integrity */ - struct krb5_keyblock kc_keyc; /* checksum */ - rawobj_t kc_mech_used; -}; - -enum sgn_alg { - SGN_ALG_DES_MAC_MD5 = 0x0000, - SGN_ALG_MD2_5 = 0x0001, - SGN_ALG_DES_MAC = 0x0002, - SGN_ALG_3 = 0x0003, /* not published */ - SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ - SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 -}; - -enum seal_alg { - SEAL_ALG_NONE = 0xffff, - SEAL_ALG_DES = 0x0000, - SEAL_ALG_1 = 0x0001, /* not published */ - SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; no support */ - SEAL_ALG_DES3KD = 0x0002 -}; - -#define CKSUMTYPE_CRC32 0x0001 -#define CKSUMTYPE_RSA_MD4 0x0002 -#define CKSUMTYPE_RSA_MD4_DES 0x0003 -#define CKSUMTYPE_DESCBC 0x0004 -/* des-mac-k */ -/* rsa-md4-des-k */ -#define CKSUMTYPE_RSA_MD5 0x0007 -#define CKSUMTYPE_RSA_MD5_DES 0x0008 -#define CKSUMTYPE_NIST_SHA 0x0009 -#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c -#define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f -#define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 -#define CKSUMTYPE_HMAC_MD5_ARCFOUR -138 - -/* from gssapi_err_krb5.h */ -#define KG_CCACHE_NOMATCH (39756032L) -#define KG_KEYTAB_NOMATCH (39756033L) -#define KG_TGT_MISSING (39756034L) -#define KG_NO_SUBKEY (39756035L) -#define KG_CONTEXT_ESTABLISHED (39756036L) -#define KG_BAD_SIGN_TYPE (39756037L) -#define KG_BAD_LENGTH (39756038L) -#define KG_CTX_INCOMPLETE (39756039L) -#define KG_CONTEXT (39756040L) -#define KG_CRED (39756041L) -#define KG_ENC_DESC (39756042L) -#define KG_BAD_SEQ (39756043L) -#define KG_EMPTY_CCACHE (39756044L) -#define KG_NO_CTYPES (39756045L) - -/* per Kerberos v5 protocol spec crypto types from the wire. - * these get mapped to linux kernel crypto routines. - */ -#define ENCTYPE_NULL 0x0000 -#define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ -#define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */ -#define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */ -#define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */ -/* XXX deprecated? */ -#define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */ -#define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */ -#define ENCTYPE_DES_HMAC_SHA1 0x0008 -#define ENCTYPE_DES3_CBC_SHA1 0x0010 -#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011 -#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012 -#define ENCTYPE_ARCFOUR_HMAC 0x0017 -#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018 -#define ENCTYPE_UNKNOWN 0x01ff - -#endif /* PTLRPC_GSS_KRB5_H */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c deleted file mode 100644 index d03f6c114171..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c +++ /dev/null @@ -1,1786 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2011, 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/net/sunrpc/gss_krb5_mech.c - * linux/net/sunrpc/gss_krb5_crypto.c - * linux/net/sunrpc/gss_krb5_seal.c - * linux/net/sunrpc/gss_krb5_seqnum.c - * linux/net/sunrpc/gss_krb5_unseal.c - * - * Copyright (c) 2001 The Regents of the University of Michigan. - * All rights reserved. - * - * Andy Adamson <andros@umich.edu> - * J. Bruce Fields <bfields@umich.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/crypto.h> -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" -#include "gss_asn1.h" -#include "gss_krb5.h" - -static spinlock_t krb5_seq_lock; - -struct krb5_enctype { - char *ke_dispname; - char *ke_enc_name; /* linux tfm name */ - char *ke_hash_name; /* linux tfm name */ - int ke_enc_mode; /* linux tfm mode */ - int ke_hash_size; /* checksum size */ - int ke_conf_size; /* confounder size */ - unsigned int ke_hash_hmac:1; /* is hmac? */ -}; - -/* - * NOTE: for aes128-cts and aes256-cts, MIT implementation use CTS encryption. - * but currently we simply CBC with padding, because linux doesn't support CTS - * yet. this need to be fixed in the future. - */ -static struct krb5_enctype enctypes[] = { - [ENCTYPE_DES_CBC_RAW] = { /* des-cbc-md5 */ - "des-cbc-md5", - "cbc(des)", - "md5", - 0, - 16, - 8, - 0, - }, - [ENCTYPE_DES3_CBC_RAW] = { /* des3-hmac-sha1 */ - "des3-hmac-sha1", - "cbc(des3_ede)", - "hmac(sha1)", - 0, - 20, - 8, - 1, - }, - [ENCTYPE_AES128_CTS_HMAC_SHA1_96] = { /* aes128-cts */ - "aes128-cts-hmac-sha1-96", - "cbc(aes)", - "hmac(sha1)", - 0, - 12, - 16, - 1, - }, - [ENCTYPE_AES256_CTS_HMAC_SHA1_96] = { /* aes256-cts */ - "aes256-cts-hmac-sha1-96", - "cbc(aes)", - "hmac(sha1)", - 0, - 12, - 16, - 1, - }, - [ENCTYPE_ARCFOUR_HMAC] = { /* arcfour-hmac-md5 */ - "arcfour-hmac-md5", - "ecb(arc4)", - "hmac(md5)", - 0, - 16, - 8, - 1, - }, -}; - -#define MAX_ENCTYPES sizeof(enctypes)/sizeof(struct krb5_enctype) - -static const char * enctype2str(__u32 enctype) -{ - if (enctype < MAX_ENCTYPES && enctypes[enctype].ke_dispname) - return enctypes[enctype].ke_dispname; - - return "unknown"; -} - -static -int keyblock_init(struct krb5_keyblock *kb, char *alg_name, int alg_mode) -{ - kb->kb_tfm = crypto_alloc_blkcipher(alg_name, alg_mode, 0); - if (IS_ERR(kb->kb_tfm)) { - CERROR("failed to alloc tfm: %s, mode %d\n", - alg_name, alg_mode); - return -1; - } - - if (crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data, kb->kb_key.len)) { - CERROR("failed to set %s key, len %d\n", - alg_name, kb->kb_key.len); - return -1; - } - - return 0; -} - -static -int krb5_init_keys(struct krb5_ctx *kctx) -{ - struct krb5_enctype *ke; - - if (kctx->kc_enctype >= MAX_ENCTYPES || - enctypes[kctx->kc_enctype].ke_hash_size == 0) { - CERROR("unsupported enctype %x\n", kctx->kc_enctype); - return -1; - } - - ke = &enctypes[kctx->kc_enctype]; - - /* tfm arc4 is stateful, user should alloc-use-free by his own */ - if (kctx->kc_enctype != ENCTYPE_ARCFOUR_HMAC && - keyblock_init(&kctx->kc_keye, ke->ke_enc_name, ke->ke_enc_mode)) - return -1; - - /* tfm hmac is stateful, user should alloc-use-free by his own */ - if (ke->ke_hash_hmac == 0 && - keyblock_init(&kctx->kc_keyi, ke->ke_enc_name, ke->ke_enc_mode)) - return -1; - if (ke->ke_hash_hmac == 0 && - keyblock_init(&kctx->kc_keyc, ke->ke_enc_name, ke->ke_enc_mode)) - return -1; - - return 0; -} - -static -void keyblock_free(struct krb5_keyblock *kb) -{ - rawobj_free(&kb->kb_key); - if (kb->kb_tfm) - crypto_free_blkcipher(kb->kb_tfm); -} - -static -int keyblock_dup(struct krb5_keyblock *new, struct krb5_keyblock *kb) -{ - return rawobj_dup(&new->kb_key, &kb->kb_key); -} - -static -int get_bytes(char **ptr, const char *end, void *res, int len) -{ - char *p, *q; - p = *ptr; - q = p + len; - if (q > end || q < p) - return -1; - memcpy(res, p, len); - *ptr = q; - return 0; -} - -static -int get_rawobj(char **ptr, const char *end, rawobj_t *res) -{ - char *p, *q; - __u32 len; - - p = *ptr; - if (get_bytes(&p, end, &len, sizeof(len))) - return -1; - - q = p + len; - if (q > end || q < p) - return -1; - - OBD_ALLOC_LARGE(res->data, len); - if (!res->data) - return -1; - - res->len = len; - memcpy(res->data, p, len); - *ptr = q; - return 0; -} - -static -int get_keyblock(char **ptr, const char *end, - struct krb5_keyblock *kb, __u32 keysize) -{ - char *buf; - - OBD_ALLOC_LARGE(buf, keysize); - if (buf == NULL) - return -1; - - if (get_bytes(ptr, end, buf, keysize)) { - OBD_FREE_LARGE(buf, keysize); - return -1; - } - - kb->kb_key.len = keysize; - kb->kb_key.data = buf; - return 0; -} - -static -void delete_context_kerberos(struct krb5_ctx *kctx) -{ - rawobj_free(&kctx->kc_mech_used); - - keyblock_free(&kctx->kc_keye); - keyblock_free(&kctx->kc_keyi); - keyblock_free(&kctx->kc_keyc); -} - -static -__u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end) -{ - unsigned int tmp_uint, keysize; - - /* seed_init flag */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) - goto out_err; - kctx->kc_seed_init = (tmp_uint != 0); - - /* seed */ - if (get_bytes(&p, end, kctx->kc_seed, sizeof(kctx->kc_seed))) - goto out_err; - - /* sign/seal algorithm, not really used now */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) || - get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) - goto out_err; - - /* end time */ - if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime))) - goto out_err; - - /* seq send */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) - goto out_err; - kctx->kc_seq_send = tmp_uint; - - /* mech oid */ - if (get_rawobj(&p, end, &kctx->kc_mech_used)) - goto out_err; - - /* old style enc/seq keys in format: - * - enctype (u32) - * - keysize (u32) - * - keydata - * we decompose them to fit into the new context - */ - - /* enc key */ - if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype))) - goto out_err; - - if (get_bytes(&p, end, &keysize, sizeof(keysize))) - goto out_err; - - if (get_keyblock(&p, end, &kctx->kc_keye, keysize)) - goto out_err; - - /* seq key */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) || - tmp_uint != kctx->kc_enctype) - goto out_err; - - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) || - tmp_uint != keysize) - goto out_err; - - if (get_keyblock(&p, end, &kctx->kc_keyc, keysize)) - goto out_err; - - /* old style fallback */ - if (keyblock_dup(&kctx->kc_keyi, &kctx->kc_keyc)) - goto out_err; - - if (p != end) - goto out_err; - - CDEBUG(D_SEC, "successfully imported rfc1964 context\n"); - return 0; -out_err: - return GSS_S_FAILURE; -} - -/* Flags for version 2 context flags */ -#define KRB5_CTX_FLAG_INITIATOR 0x00000001 -#define KRB5_CTX_FLAG_CFX 0x00000002 -#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 - -static -__u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end) -{ - unsigned int tmp_uint, keysize; - - /* end time */ - if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime))) - goto out_err; - - /* flags */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) - goto out_err; - - if (tmp_uint & KRB5_CTX_FLAG_INITIATOR) - kctx->kc_initiate = 1; - if (tmp_uint & KRB5_CTX_FLAG_CFX) - kctx->kc_cfx = 1; - if (tmp_uint & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) - kctx->kc_have_acceptor_subkey = 1; - - /* seq send */ - if (get_bytes(&p, end, &kctx->kc_seq_send, sizeof(kctx->kc_seq_send))) - goto out_err; - - /* enctype */ - if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype))) - goto out_err; - - /* size of each key */ - if (get_bytes(&p, end, &keysize, sizeof(keysize))) - goto out_err; - - /* number of keys - should always be 3 */ - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) - goto out_err; - - if (tmp_uint != 3) { - CERROR("Invalid number of keys: %u\n", tmp_uint); - goto out_err; - } - - /* ke */ - if (get_keyblock(&p, end, &kctx->kc_keye, keysize)) - goto out_err; - /* ki */ - if (get_keyblock(&p, end, &kctx->kc_keyi, keysize)) - goto out_err; - /* ki */ - if (get_keyblock(&p, end, &kctx->kc_keyc, keysize)) - goto out_err; - - CDEBUG(D_SEC, "successfully imported v2 context\n"); - return 0; -out_err: - return GSS_S_FAILURE; -} - -/* - * The whole purpose here is trying to keep user level gss context parsing - * from nfs-utils unchanged as possible as we can, they are not quite mature - * yet, and many stuff still not clear, like heimdal etc. - */ -static -__u32 gss_import_sec_context_kerberos(rawobj_t *inbuf, - struct gss_ctx *gctx) -{ - struct krb5_ctx *kctx; - char *p = (char *) inbuf->data; - char *end = (char *) (inbuf->data + inbuf->len); - unsigned int tmp_uint, rc; - - if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) { - CERROR("Fail to read version\n"); - return GSS_S_FAILURE; - } - - /* only support 0, 1 for the moment */ - if (tmp_uint > 2) { - CERROR("Invalid version %u\n", tmp_uint); - return GSS_S_FAILURE; - } - - OBD_ALLOC_PTR(kctx); - if (!kctx) - return GSS_S_FAILURE; - - if (tmp_uint == 0 || tmp_uint == 1) { - kctx->kc_initiate = tmp_uint; - rc = import_context_rfc1964(kctx, p, end); - } else { - rc = import_context_rfc4121(kctx, p, end); - } - - if (rc == 0) - rc = krb5_init_keys(kctx); - - if (rc) { - delete_context_kerberos(kctx); - OBD_FREE_PTR(kctx); - - return GSS_S_FAILURE; - } - - gctx->internal_ctx_id = kctx; - return GSS_S_COMPLETE; -} - -static -__u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx, - struct gss_ctx *gctx_new) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_ctx *knew; - - OBD_ALLOC_PTR(knew); - if (!knew) - return GSS_S_FAILURE; - - knew->kc_initiate = kctx->kc_initiate ? 0 : 1; - knew->kc_cfx = kctx->kc_cfx; - knew->kc_seed_init = kctx->kc_seed_init; - knew->kc_have_acceptor_subkey = kctx->kc_have_acceptor_subkey; - knew->kc_endtime = kctx->kc_endtime; - - memcpy(knew->kc_seed, kctx->kc_seed, sizeof(kctx->kc_seed)); - knew->kc_seq_send = kctx->kc_seq_recv; - knew->kc_seq_recv = kctx->kc_seq_send; - knew->kc_enctype = kctx->kc_enctype; - - if (rawobj_dup(&knew->kc_mech_used, &kctx->kc_mech_used)) - goto out_err; - - if (keyblock_dup(&knew->kc_keye, &kctx->kc_keye)) - goto out_err; - if (keyblock_dup(&knew->kc_keyi, &kctx->kc_keyi)) - goto out_err; - if (keyblock_dup(&knew->kc_keyc, &kctx->kc_keyc)) - goto out_err; - if (krb5_init_keys(knew)) - goto out_err; - - gctx_new->internal_ctx_id = knew; - CDEBUG(D_SEC, "successfully copied reverse context\n"); - return GSS_S_COMPLETE; - -out_err: - delete_context_kerberos(knew); - OBD_FREE_PTR(knew); - return GSS_S_FAILURE; -} - -static -__u32 gss_inquire_context_kerberos(struct gss_ctx *gctx, - unsigned long *endtime) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - - *endtime = (unsigned long) ((__u32) kctx->kc_endtime); - return GSS_S_COMPLETE; -} - -static -void gss_delete_sec_context_kerberos(void *internal_ctx) -{ - struct krb5_ctx *kctx = internal_ctx; - - delete_context_kerberos(kctx); - OBD_FREE_PTR(kctx); -} - -static -void buf_to_sg(struct scatterlist *sg, void *ptr, int len) -{ - sg_set_buf(sg, ptr, len); -} - -static -__u32 krb5_encrypt(struct crypto_blkcipher *tfm, - int decrypt, - void * iv, - void * in, - void * out, - int length) -{ - struct blkcipher_desc desc; - struct scatterlist sg; - __u8 local_iv[16] = {0}; - __u32 ret = -EINVAL; - - LASSERT(tfm); - desc.tfm = tfm; - desc.info = local_iv; - desc.flags= 0; - - if (length % crypto_blkcipher_blocksize(tfm) != 0) { - CERROR("output length %d mismatch blocksize %d\n", - length, crypto_blkcipher_blocksize(tfm)); - goto out; - } - - if (crypto_blkcipher_ivsize(tfm) > 16) { - CERROR("iv size too large %d\n", crypto_blkcipher_ivsize(tfm)); - goto out; - } - - if (iv) - memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm)); - - memcpy(out, in, length); - buf_to_sg(&sg, out, length); - - if (decrypt) - ret = crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, length); - else - ret = crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, length); - -out: - return(ret); -} - - -static inline -int krb5_digest_hmac(struct crypto_hash *tfm, - rawobj_t *key, - struct krb5_header *khdr, - int msgcnt, rawobj_t *msgs, - int iovcnt, lnet_kiov_t *iovs, - rawobj_t *cksum) -{ - struct hash_desc desc; - struct scatterlist sg[1]; - int i; - - crypto_hash_setkey(tfm, key->data, key->len); - desc.tfm = tfm; - desc.flags= 0; - - crypto_hash_init(&desc); - - for (i = 0; i < msgcnt; i++) { - if (msgs[i].len == 0) - continue; - buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len); - crypto_hash_update(&desc, sg, msgs[i].len); - } - - for (i = 0; i < iovcnt; i++) { - if (iovs[i].kiov_len == 0) - continue; - - sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len, - iovs[i].kiov_offset); - crypto_hash_update(&desc, sg, iovs[i].kiov_len); - } - - if (khdr) { - buf_to_sg(sg, (char *) khdr, sizeof(*khdr)); - crypto_hash_update(&desc, sg, sizeof(*khdr)); - } - - return crypto_hash_final(&desc, cksum->data); -} - - -static inline -int krb5_digest_norm(struct crypto_hash *tfm, - struct krb5_keyblock *kb, - struct krb5_header *khdr, - int msgcnt, rawobj_t *msgs, - int iovcnt, lnet_kiov_t *iovs, - rawobj_t *cksum) -{ - struct hash_desc desc; - struct scatterlist sg[1]; - int i; - - LASSERT(kb->kb_tfm); - desc.tfm = tfm; - desc.flags= 0; - - crypto_hash_init(&desc); - - for (i = 0; i < msgcnt; i++) { - if (msgs[i].len == 0) - continue; - buf_to_sg(sg, (char *) msgs[i].data, msgs[i].len); - crypto_hash_update(&desc, sg, msgs[i].len); - } - - for (i = 0; i < iovcnt; i++) { - if (iovs[i].kiov_len == 0) - continue; - - sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len, - iovs[i].kiov_offset); - crypto_hash_update(&desc, sg, iovs[i].kiov_len); - } - - if (khdr) { - buf_to_sg(sg, (char *) khdr, sizeof(*khdr)); - crypto_hash_update(&desc, sg, sizeof(*khdr)); - } - - crypto_hash_final(&desc, cksum->data); - - return krb5_encrypt(kb->kb_tfm, 0, NULL, cksum->data, - cksum->data, cksum->len); -} - -/* - * compute (keyed/keyless) checksum against the plain text which appended - * with krb5 wire token header. - */ -static -__s32 krb5_make_checksum(__u32 enctype, - struct krb5_keyblock *kb, - struct krb5_header *khdr, - int msgcnt, rawobj_t *msgs, - int iovcnt, lnet_kiov_t *iovs, - rawobj_t *cksum) -{ - struct krb5_enctype *ke = &enctypes[enctype]; - struct crypto_hash *tfm; - __u32 code = GSS_S_FAILURE; - int rc; - - tfm = ll_crypto_alloc_hash(ke->ke_hash_name, 0, 0); - if (!tfm) { - CERROR("failed to alloc TFM: %s\n", ke->ke_hash_name); - return GSS_S_FAILURE; - } - - cksum->len = crypto_hash_digestsize(tfm); - OBD_ALLOC_LARGE(cksum->data, cksum->len); - if (!cksum->data) { - cksum->len = 0; - goto out_tfm; - } - - if (ke->ke_hash_hmac) - rc = krb5_digest_hmac(tfm, &kb->kb_key, - khdr, msgcnt, msgs, iovcnt, iovs, cksum); - else - rc = krb5_digest_norm(tfm, kb, - khdr, msgcnt, msgs, iovcnt, iovs, cksum); - - if (rc == 0) - code = GSS_S_COMPLETE; -out_tfm: - crypto_free_hash(tfm); - return code; -} - -static void fill_krb5_header(struct krb5_ctx *kctx, - struct krb5_header *khdr, - int privacy) -{ - unsigned char acceptor_flag; - - acceptor_flag = kctx->kc_initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; - - if (privacy) { - khdr->kh_tok_id = cpu_to_be16(KG_TOK_WRAP_MSG); - khdr->kh_flags = acceptor_flag | FLAG_WRAP_CONFIDENTIAL; - khdr->kh_ec = cpu_to_be16(0); - khdr->kh_rrc = cpu_to_be16(0); - } else { - khdr->kh_tok_id = cpu_to_be16(KG_TOK_MIC_MSG); - khdr->kh_flags = acceptor_flag; - khdr->kh_ec = cpu_to_be16(0xffff); - khdr->kh_rrc = cpu_to_be16(0xffff); - } - - khdr->kh_filler = 0xff; - spin_lock(&krb5_seq_lock); - khdr->kh_seq = cpu_to_be64(kctx->kc_seq_send++); - spin_unlock(&krb5_seq_lock); -} - -static __u32 verify_krb5_header(struct krb5_ctx *kctx, - struct krb5_header *khdr, - int privacy) -{ - unsigned char acceptor_flag; - __u16 tok_id, ec_rrc; - - acceptor_flag = kctx->kc_initiate ? FLAG_SENDER_IS_ACCEPTOR : 0; - - if (privacy) { - tok_id = KG_TOK_WRAP_MSG; - ec_rrc = 0x0; - } else { - tok_id = KG_TOK_MIC_MSG; - ec_rrc = 0xffff; - } - - /* sanity checks */ - if (be16_to_cpu(khdr->kh_tok_id) != tok_id) { - CERROR("bad token id\n"); - return GSS_S_DEFECTIVE_TOKEN; - } - if ((khdr->kh_flags & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { - CERROR("bad direction flag\n"); - return GSS_S_BAD_SIG; - } - if (privacy && (khdr->kh_flags & FLAG_WRAP_CONFIDENTIAL) == 0) { - CERROR("missing confidential flag\n"); - return GSS_S_BAD_SIG; - } - if (khdr->kh_filler != 0xff) { - CERROR("bad filler\n"); - return GSS_S_DEFECTIVE_TOKEN; - } - if (be16_to_cpu(khdr->kh_ec) != ec_rrc || - be16_to_cpu(khdr->kh_rrc) != ec_rrc) { - CERROR("bad EC or RRC\n"); - return GSS_S_DEFECTIVE_TOKEN; - } - return GSS_S_COMPLETE; -} - -static -__u32 gss_get_mic_kerberos(struct gss_ctx *gctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *token) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - rawobj_t cksum = RAWOBJ_EMPTY; - - /* fill krb5 header */ - LASSERT(token->len >= sizeof(*khdr)); - khdr = (struct krb5_header *) token->data; - fill_krb5_header(kctx, khdr, 0); - - /* checksum */ - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc, - khdr, msgcnt, msgs, iovcnt, iovs, &cksum)) - return GSS_S_FAILURE; - - LASSERT(cksum.len >= ke->ke_hash_size); - LASSERT(token->len >= sizeof(*khdr) + ke->ke_hash_size); - memcpy(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size); - - token->len = sizeof(*khdr) + ke->ke_hash_size; - rawobj_free(&cksum); - return GSS_S_COMPLETE; -} - -static -__u32 gss_verify_mic_kerberos(struct gss_ctx *gctx, - int msgcnt, - rawobj_t *msgs, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *token) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - rawobj_t cksum = RAWOBJ_EMPTY; - __u32 major; - - if (token->len < sizeof(*khdr)) { - CERROR("short signature: %u\n", token->len); - return GSS_S_DEFECTIVE_TOKEN; - } - - khdr = (struct krb5_header *) token->data; - - major = verify_krb5_header(kctx, khdr, 0); - if (major != GSS_S_COMPLETE) { - CERROR("bad krb5 header\n"); - return major; - } - - if (token->len < sizeof(*khdr) + ke->ke_hash_size) { - CERROR("short signature: %u, require %d\n", - token->len, (int) sizeof(*khdr) + ke->ke_hash_size); - return GSS_S_FAILURE; - } - - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyc, - khdr, msgcnt, msgs, iovcnt, iovs, &cksum)) { - CERROR("failed to make checksum\n"); - return GSS_S_FAILURE; - } - - LASSERT(cksum.len >= ke->ke_hash_size); - if (memcmp(khdr + 1, cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size)) { - CERROR("checksum mismatch\n"); - rawobj_free(&cksum); - return GSS_S_BAD_SIG; - } - - rawobj_free(&cksum); - return GSS_S_COMPLETE; -} - -static -int add_padding(rawobj_t *msg, int msg_buflen, int blocksize) -{ - int padding; - - padding = (blocksize - (msg->len & (blocksize - 1))) & - (blocksize - 1); - if (!padding) - return 0; - - if (msg->len + padding > msg_buflen) { - CERROR("bufsize %u too small: datalen %u, padding %u\n", - msg_buflen, msg->len, padding); - return -EINVAL; - } - - memset(msg->data + msg->len, padding, padding); - msg->len += padding; - return 0; -} - -static -int krb5_encrypt_rawobjs(struct crypto_blkcipher *tfm, - int mode_ecb, - int inobj_cnt, - rawobj_t *inobjs, - rawobj_t *outobj, - int enc) -{ - struct blkcipher_desc desc; - struct scatterlist src, dst; - __u8 local_iv[16] = {0}, *buf; - __u32 datalen = 0; - int i, rc; - - buf = outobj->data; - desc.tfm = tfm; - desc.info = local_iv; - desc.flags = 0; - - for (i = 0; i < inobj_cnt; i++) { - LASSERT(buf + inobjs[i].len <= outobj->data + outobj->len); - - buf_to_sg(&src, inobjs[i].data, inobjs[i].len); - buf_to_sg(&dst, buf, outobj->len - datalen); - - if (mode_ecb) { - if (enc) - rc = crypto_blkcipher_encrypt( - &desc, &dst, &src, src.length); - else - rc = crypto_blkcipher_decrypt( - &desc, &dst, &src, src.length); - } else { - if (enc) - rc = crypto_blkcipher_encrypt_iv( - &desc, &dst, &src, src.length); - else - rc = crypto_blkcipher_decrypt_iv( - &desc, &dst, &src, src.length); - } - - if (rc) { - CERROR("encrypt error %d\n", rc); - return rc; - } - - datalen += inobjs[i].len; - buf += inobjs[i].len; - } - - outobj->len = datalen; - return 0; -} - -/* - * if adj_nob != 0, we adjust desc->bd_nob to the actual cipher text size. - */ -static -int krb5_encrypt_bulk(struct crypto_blkcipher *tfm, - struct krb5_header *khdr, - char *confounder, - struct ptlrpc_bulk_desc *desc, - rawobj_t *cipher, - int adj_nob) -{ - struct blkcipher_desc ciph_desc; - __u8 local_iv[16] = {0}; - struct scatterlist src, dst; - int blocksize, i, rc, nob = 0; - - LASSERT(desc->bd_iov_count); - LASSERT(desc->bd_enc_iov); - - blocksize = crypto_blkcipher_blocksize(tfm); - LASSERT(blocksize > 1); - LASSERT(cipher->len == blocksize + sizeof(*khdr)); - - ciph_desc.tfm = tfm; - ciph_desc.info = local_iv; - ciph_desc.flags = 0; - - /* encrypt confounder */ - buf_to_sg(&src, confounder, blocksize); - buf_to_sg(&dst, cipher->data, blocksize); - - rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src, blocksize); - if (rc) { - CERROR("error to encrypt confounder: %d\n", rc); - return rc; - } - - /* encrypt clear pages */ - for (i = 0; i < desc->bd_iov_count; i++) { - sg_set_page(&src, desc->bd_iov[i].kiov_page, - (desc->bd_iov[i].kiov_len + blocksize - 1) & - (~(blocksize - 1)), - desc->bd_iov[i].kiov_offset); - if (adj_nob) - nob += src.length; - sg_set_page(&dst, desc->bd_enc_iov[i].kiov_page, src.length, - src.offset); - - desc->bd_enc_iov[i].kiov_offset = dst.offset; - desc->bd_enc_iov[i].kiov_len = dst.length; - - rc = crypto_blkcipher_encrypt_iv(&ciph_desc, &dst, &src, - src.length); - if (rc) { - CERROR("error to encrypt page: %d\n", rc); - return rc; - } - } - - /* encrypt krb5 header */ - buf_to_sg(&src, khdr, sizeof(*khdr)); - buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr)); - - rc = crypto_blkcipher_encrypt_iv(&ciph_desc, - &dst, &src, sizeof(*khdr)); - if (rc) { - CERROR("error to encrypt krb5 header: %d\n", rc); - return rc; - } - - if (adj_nob) - desc->bd_nob = nob; - - return 0; -} - -/* - * desc->bd_nob_transferred is the size of cipher text received. - * desc->bd_nob is the target size of plain text supposed to be. - * - * if adj_nob != 0, we adjust each page's kiov_len to the actual - * plain text size. - * - for client read: we don't know data size for each page, so - * bd_iov[]->kiov_len is set to PAGE_SIZE, but actual data received might - * be smaller, so we need to adjust it according to bd_enc_iov[]->kiov_len. - * this means we DO NOT support the situation that server send an odd size - * data in a page which is not the last one. - * - for server write: we knows exactly data size for each page being expected, - * thus kiov_len is accurate already, so we should not adjust it at all. - * and bd_enc_iov[]->kiov_len should be round_up(bd_iov[]->kiov_len) which - * should have been done by prep_bulk(). - */ -static -int krb5_decrypt_bulk(struct crypto_blkcipher *tfm, - struct krb5_header *khdr, - struct ptlrpc_bulk_desc *desc, - rawobj_t *cipher, - rawobj_t *plain, - int adj_nob) -{ - struct blkcipher_desc ciph_desc; - __u8 local_iv[16] = {0}; - struct scatterlist src, dst; - int ct_nob = 0, pt_nob = 0; - int blocksize, i, rc; - - LASSERT(desc->bd_iov_count); - LASSERT(desc->bd_enc_iov); - LASSERT(desc->bd_nob_transferred); - - blocksize = crypto_blkcipher_blocksize(tfm); - LASSERT(blocksize > 1); - LASSERT(cipher->len == blocksize + sizeof(*khdr)); - - ciph_desc.tfm = tfm; - ciph_desc.info = local_iv; - ciph_desc.flags = 0; - - if (desc->bd_nob_transferred % blocksize) { - CERROR("odd transferred nob: %d\n", desc->bd_nob_transferred); - return -EPROTO; - } - - /* decrypt head (confounder) */ - buf_to_sg(&src, cipher->data, blocksize); - buf_to_sg(&dst, plain->data, blocksize); - - rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src, blocksize); - if (rc) { - CERROR("error to decrypt confounder: %d\n", rc); - return rc; - } - - for (i = 0; i < desc->bd_iov_count && ct_nob < desc->bd_nob_transferred; - i++) { - if (desc->bd_enc_iov[i].kiov_offset % blocksize != 0 || - desc->bd_enc_iov[i].kiov_len % blocksize != 0) { - CERROR("page %d: odd offset %u len %u, blocksize %d\n", - i, desc->bd_enc_iov[i].kiov_offset, - desc->bd_enc_iov[i].kiov_len, blocksize); - return -EFAULT; - } - - if (adj_nob) { - if (ct_nob + desc->bd_enc_iov[i].kiov_len > - desc->bd_nob_transferred) - desc->bd_enc_iov[i].kiov_len = - desc->bd_nob_transferred - ct_nob; - - desc->bd_iov[i].kiov_len = desc->bd_enc_iov[i].kiov_len; - if (pt_nob + desc->bd_enc_iov[i].kiov_len >desc->bd_nob) - desc->bd_iov[i].kiov_len = desc->bd_nob -pt_nob; - } else { - /* this should be guaranteed by LNET */ - LASSERT(ct_nob + desc->bd_enc_iov[i].kiov_len <= - desc->bd_nob_transferred); - LASSERT(desc->bd_iov[i].kiov_len <= - desc->bd_enc_iov[i].kiov_len); - } - - if (desc->bd_enc_iov[i].kiov_len == 0) - continue; - - sg_set_page(&src, desc->bd_enc_iov[i].kiov_page, - desc->bd_enc_iov[i].kiov_len, - desc->bd_enc_iov[i].kiov_offset); - dst = src; - if (desc->bd_iov[i].kiov_len % blocksize == 0) - sg_assign_page(&dst, desc->bd_iov[i].kiov_page); - - rc = crypto_blkcipher_decrypt_iv(&ciph_desc, &dst, &src, - src.length); - if (rc) { - CERROR("error to decrypt page: %d\n", rc); - return rc; - } - - if (desc->bd_iov[i].kiov_len % blocksize != 0) { - memcpy(page_address(desc->bd_iov[i].kiov_page) + - desc->bd_iov[i].kiov_offset, - page_address(desc->bd_enc_iov[i].kiov_page) + - desc->bd_iov[i].kiov_offset, - desc->bd_iov[i].kiov_len); - } - - ct_nob += desc->bd_enc_iov[i].kiov_len; - pt_nob += desc->bd_iov[i].kiov_len; - } - - if (unlikely(ct_nob != desc->bd_nob_transferred)) { - CERROR("%d cipher text transferred but only %d decrypted\n", - desc->bd_nob_transferred, ct_nob); - return -EFAULT; - } - - if (unlikely(!adj_nob && pt_nob != desc->bd_nob)) { - CERROR("%d plain text expected but only %d received\n", - desc->bd_nob, pt_nob); - return -EFAULT; - } - - /* if needed, clear up the rest unused iovs */ - if (adj_nob) - while (i < desc->bd_iov_count) - desc->bd_iov[i++].kiov_len = 0; - - /* decrypt tail (krb5 header) */ - buf_to_sg(&src, cipher->data + blocksize, sizeof(*khdr)); - buf_to_sg(&dst, cipher->data + blocksize, sizeof(*khdr)); - - rc = crypto_blkcipher_decrypt_iv(&ciph_desc, - &dst, &src, sizeof(*khdr)); - if (rc) { - CERROR("error to decrypt tail: %d\n", rc); - return rc; - } - - if (memcmp(cipher->data + blocksize, khdr, sizeof(*khdr))) { - CERROR("krb5 header doesn't match\n"); - return -EACCES; - } - - return 0; -} - -static -__u32 gss_wrap_kerberos(struct gss_ctx *gctx, - rawobj_t *gsshdr, - rawobj_t *msg, - int msg_buflen, - rawobj_t *token) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - int blocksize; - rawobj_t cksum = RAWOBJ_EMPTY; - rawobj_t data_desc[3], cipher; - __u8 conf[GSS_MAX_CIPHER_BLOCK]; - int rc = 0; - - LASSERT(ke); - LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK); - LASSERT(kctx->kc_keye.kb_tfm == NULL || - ke->ke_conf_size >= - crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm)); - - /* - * final token format: - * --------------------------------------------------- - * | krb5 header | cipher text | checksum (16 bytes) | - * --------------------------------------------------- - */ - - /* fill krb5 header */ - LASSERT(token->len >= sizeof(*khdr)); - khdr = (struct krb5_header *) token->data; - fill_krb5_header(kctx, khdr, 1); - - /* generate confounder */ - cfs_get_random_bytes(conf, ke->ke_conf_size); - - /* get encryption blocksize. note kc_keye might not associated with - * a tfm, currently only for arcfour-hmac */ - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - LASSERT(kctx->kc_keye.kb_tfm == NULL); - blocksize = 1; - } else { - LASSERT(kctx->kc_keye.kb_tfm); - blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm); - } - LASSERT(blocksize <= ke->ke_conf_size); - - /* padding the message */ - if (add_padding(msg, msg_buflen, blocksize)) - return GSS_S_FAILURE; - - /* - * clear text layout for checksum: - * ------------------------------------------------------ - * | confounder | gss header | clear msgs | krb5 header | - * ------------------------------------------------------ - */ - data_desc[0].data = conf; - data_desc[0].len = ke->ke_conf_size; - data_desc[1].data = gsshdr->data; - data_desc[1].len = gsshdr->len; - data_desc[2].data = msg->data; - data_desc[2].len = msg->len; - - /* compute checksum */ - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 3, data_desc, 0, NULL, &cksum)) - return GSS_S_FAILURE; - LASSERT(cksum.len >= ke->ke_hash_size); - - /* - * clear text layout for encryption: - * ----------------------------------------- - * | confounder | clear msgs | krb5 header | - * ----------------------------------------- - */ - data_desc[0].data = conf; - data_desc[0].len = ke->ke_conf_size; - data_desc[1].data = msg->data; - data_desc[1].len = msg->len; - data_desc[2].data = (__u8 *) khdr; - data_desc[2].len = sizeof(*khdr); - - /* cipher text will be directly inplace */ - cipher.data = (__u8 *) (khdr + 1); - cipher.len = token->len - sizeof(*khdr); - LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr)); - - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - rawobj_t arc4_keye; - struct crypto_blkcipher *arc4_tfm; - - if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi, - NULL, 1, &cksum, 0, NULL, &arc4_keye)) { - CERROR("failed to obtain arc4 enc key\n"); - GOTO(arc4_out, rc = -EACCES); - } - - arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0); - if (IS_ERR(arc4_tfm)) { - CERROR("failed to alloc tfm arc4 in ECB mode\n"); - GOTO(arc4_out_key, rc = -EACCES); - } - - if (crypto_blkcipher_setkey(arc4_tfm, arc4_keye.data, - arc4_keye.len)) { - CERROR("failed to set arc4 key, len %d\n", - arc4_keye.len); - GOTO(arc4_out_tfm, rc = -EACCES); - } - - rc = krb5_encrypt_rawobjs(arc4_tfm, 1, - 3, data_desc, &cipher, 1); -arc4_out_tfm: - crypto_free_blkcipher(arc4_tfm); -arc4_out_key: - rawobj_free(&arc4_keye); -arc4_out: - do {} while (0); /* just to avoid compile warning */ - } else { - rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0, - 3, data_desc, &cipher, 1); - } - - if (rc != 0) { - rawobj_free(&cksum); - return GSS_S_FAILURE; - } - - /* fill in checksum */ - LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size); - memcpy((char *)(khdr + 1) + cipher.len, - cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size); - rawobj_free(&cksum); - - /* final token length */ - token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size; - return GSS_S_COMPLETE; -} - -static -__u32 gss_prep_bulk_kerberos(struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - int blocksize, i; - - LASSERT(desc->bd_iov_count); - LASSERT(desc->bd_enc_iov); - LASSERT(kctx->kc_keye.kb_tfm); - - blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm); - - for (i = 0; i < desc->bd_iov_count; i++) { - LASSERT(desc->bd_enc_iov[i].kiov_page); - /* - * offset should always start at page boundary of either - * client or server side. - */ - if (desc->bd_iov[i].kiov_offset & blocksize) { - CERROR("odd offset %d in page %d\n", - desc->bd_iov[i].kiov_offset, i); - return GSS_S_FAILURE; - } - - desc->bd_enc_iov[i].kiov_offset = desc->bd_iov[i].kiov_offset; - desc->bd_enc_iov[i].kiov_len = (desc->bd_iov[i].kiov_len + - blocksize - 1) & (~(blocksize - 1)); - } - - return GSS_S_COMPLETE; -} - -static -__u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, int adj_nob) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - int blocksize; - rawobj_t cksum = RAWOBJ_EMPTY; - rawobj_t data_desc[1], cipher; - __u8 conf[GSS_MAX_CIPHER_BLOCK]; - int rc = 0; - - LASSERT(ke); - LASSERT(ke->ke_conf_size <= GSS_MAX_CIPHER_BLOCK); - - /* - * final token format: - * -------------------------------------------------- - * | krb5 header | head/tail cipher text | checksum | - * -------------------------------------------------- - */ - - /* fill krb5 header */ - LASSERT(token->len >= sizeof(*khdr)); - khdr = (struct krb5_header *) token->data; - fill_krb5_header(kctx, khdr, 1); - - /* generate confounder */ - cfs_get_random_bytes(conf, ke->ke_conf_size); - - /* get encryption blocksize. note kc_keye might not associated with - * a tfm, currently only for arcfour-hmac */ - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - LASSERT(kctx->kc_keye.kb_tfm == NULL); - blocksize = 1; - } else { - LASSERT(kctx->kc_keye.kb_tfm); - blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm); - } - - /* - * we assume the size of krb5_header (16 bytes) must be n * blocksize. - * the bulk token size would be exactly (sizeof(krb5_header) + - * blocksize + sizeof(krb5_header) + hashsize) - */ - LASSERT(blocksize <= ke->ke_conf_size); - LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0); - LASSERT(token->len >= sizeof(*khdr) + blocksize + sizeof(*khdr) + 16); - - /* - * clear text layout for checksum: - * ------------------------------------------ - * | confounder | clear pages | krb5 header | - * ------------------------------------------ - */ - data_desc[0].data = conf; - data_desc[0].len = ke->ke_conf_size; - - /* compute checksum */ - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 1, data_desc, - desc->bd_iov_count, desc->bd_iov, - &cksum)) - return GSS_S_FAILURE; - LASSERT(cksum.len >= ke->ke_hash_size); - - /* - * clear text layout for encryption: - * ------------------------------------------ - * | confounder | clear pages | krb5 header | - * ------------------------------------------ - * | | | - * ---------- (cipher pages) | - * result token: | | - * ------------------------------------------- - * | krb5 header | cipher text | cipher text | - * ------------------------------------------- - */ - data_desc[0].data = conf; - data_desc[0].len = ke->ke_conf_size; - - cipher.data = (__u8 *) (khdr + 1); - cipher.len = blocksize + sizeof(*khdr); - - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - LBUG(); - rc = 0; - } else { - rc = krb5_encrypt_bulk(kctx->kc_keye.kb_tfm, khdr, - conf, desc, &cipher, adj_nob); - } - - if (rc != 0) { - rawobj_free(&cksum); - return GSS_S_FAILURE; - } - - /* fill in checksum */ - LASSERT(token->len >= sizeof(*khdr) + cipher.len + ke->ke_hash_size); - memcpy((char *)(khdr + 1) + cipher.len, - cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size); - rawobj_free(&cksum); - - /* final token length */ - token->len = sizeof(*khdr) + cipher.len + ke->ke_hash_size; - return GSS_S_COMPLETE; -} - -static -__u32 gss_unwrap_kerberos(struct gss_ctx *gctx, - rawobj_t *gsshdr, - rawobj_t *token, - rawobj_t *msg) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - unsigned char *tmpbuf; - int blocksize, bodysize; - rawobj_t cksum = RAWOBJ_EMPTY; - rawobj_t cipher_in, plain_out; - rawobj_t hash_objs[3]; - int rc = 0; - __u32 major; - - LASSERT(ke); - - if (token->len < sizeof(*khdr)) { - CERROR("short signature: %u\n", token->len); - return GSS_S_DEFECTIVE_TOKEN; - } - - khdr = (struct krb5_header *) token->data; - - major = verify_krb5_header(kctx, khdr, 1); - if (major != GSS_S_COMPLETE) { - CERROR("bad krb5 header\n"); - return major; - } - - /* block size */ - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - LASSERT(kctx->kc_keye.kb_tfm == NULL); - blocksize = 1; - } else { - LASSERT(kctx->kc_keye.kb_tfm); - blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm); - } - - /* expected token layout: - * ---------------------------------------- - * | krb5 header | cipher text | checksum | - * ---------------------------------------- - */ - bodysize = token->len - sizeof(*khdr) - ke->ke_hash_size; - - if (bodysize % blocksize) { - CERROR("odd bodysize %d\n", bodysize); - return GSS_S_DEFECTIVE_TOKEN; - } - - if (bodysize <= ke->ke_conf_size + sizeof(*khdr)) { - CERROR("incomplete token: bodysize %d\n", bodysize); - return GSS_S_DEFECTIVE_TOKEN; - } - - if (msg->len < bodysize - ke->ke_conf_size - sizeof(*khdr)) { - CERROR("buffer too small: %u, require %d\n", - msg->len, bodysize - ke->ke_conf_size); - return GSS_S_FAILURE; - } - - /* decrypting */ - OBD_ALLOC_LARGE(tmpbuf, bodysize); - if (!tmpbuf) - return GSS_S_FAILURE; - - major = GSS_S_FAILURE; - - cipher_in.data = (__u8 *) (khdr + 1); - cipher_in.len = bodysize; - plain_out.data = tmpbuf; - plain_out.len = bodysize; - - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - rawobj_t arc4_keye; - struct crypto_blkcipher *arc4_tfm; - - cksum.data = token->data + token->len - ke->ke_hash_size; - cksum.len = ke->ke_hash_size; - - if (krb5_make_checksum(ENCTYPE_ARCFOUR_HMAC, &kctx->kc_keyi, - NULL, 1, &cksum, 0, NULL, &arc4_keye)) { - CERROR("failed to obtain arc4 enc key\n"); - GOTO(arc4_out, rc = -EACCES); - } - - arc4_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, 0); - if (IS_ERR(arc4_tfm)) { - CERROR("failed to alloc tfm arc4 in ECB mode\n"); - GOTO(arc4_out_key, rc = -EACCES); - } - - if (crypto_blkcipher_setkey(arc4_tfm, - arc4_keye.data, arc4_keye.len)) { - CERROR("failed to set arc4 key, len %d\n", - arc4_keye.len); - GOTO(arc4_out_tfm, rc = -EACCES); - } - - rc = krb5_encrypt_rawobjs(arc4_tfm, 1, - 1, &cipher_in, &plain_out, 0); -arc4_out_tfm: - crypto_free_blkcipher(arc4_tfm); -arc4_out_key: - rawobj_free(&arc4_keye); -arc4_out: - cksum = RAWOBJ_EMPTY; - } else { - rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0, - 1, &cipher_in, &plain_out, 0); - } - - if (rc != 0) { - CERROR("error decrypt\n"); - goto out_free; - } - LASSERT(plain_out.len == bodysize); - - /* expected clear text layout: - * ----------------------------------------- - * | confounder | clear msgs | krb5 header | - * ----------------------------------------- - */ - - /* verify krb5 header in token is not modified */ - if (memcmp(khdr, plain_out.data + plain_out.len - sizeof(*khdr), - sizeof(*khdr))) { - CERROR("decrypted krb5 header mismatch\n"); - goto out_free; - } - - /* verify checksum, compose clear text as layout: - * ------------------------------------------------------ - * | confounder | gss header | clear msgs | krb5 header | - * ------------------------------------------------------ - */ - hash_objs[0].len = ke->ke_conf_size; - hash_objs[0].data = plain_out.data; - hash_objs[1].len = gsshdr->len; - hash_objs[1].data = gsshdr->data; - hash_objs[2].len = plain_out.len - ke->ke_conf_size - sizeof(*khdr); - hash_objs[2].data = plain_out.data + ke->ke_conf_size; - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 3, hash_objs, 0, NULL, &cksum)) - goto out_free; - - LASSERT(cksum.len >= ke->ke_hash_size); - if (memcmp((char *)(khdr + 1) + bodysize, - cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size)) { - CERROR("checksum mismatch\n"); - goto out_free; - } - - msg->len = bodysize - ke->ke_conf_size - sizeof(*khdr); - memcpy(msg->data, tmpbuf + ke->ke_conf_size, msg->len); - - major = GSS_S_COMPLETE; -out_free: - OBD_FREE_LARGE(tmpbuf, bodysize); - rawobj_free(&cksum); - return major; -} - -static -__u32 gss_unwrap_bulk_kerberos(struct gss_ctx *gctx, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, int adj_nob) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - struct krb5_enctype *ke = &enctypes[kctx->kc_enctype]; - struct krb5_header *khdr; - int blocksize; - rawobj_t cksum = RAWOBJ_EMPTY; - rawobj_t cipher, plain; - rawobj_t data_desc[1]; - int rc; - __u32 major; - - LASSERT(ke); - - if (token->len < sizeof(*khdr)) { - CERROR("short signature: %u\n", token->len); - return GSS_S_DEFECTIVE_TOKEN; - } - - khdr = (struct krb5_header *) token->data; - - major = verify_krb5_header(kctx, khdr, 1); - if (major != GSS_S_COMPLETE) { - CERROR("bad krb5 header\n"); - return major; - } - - /* block size */ - if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) { - LASSERT(kctx->kc_keye.kb_tfm == NULL); - blocksize = 1; - LBUG(); - } else { - LASSERT(kctx->kc_keye.kb_tfm); - blocksize = crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm); - } - LASSERT(sizeof(*khdr) >= blocksize && sizeof(*khdr) % blocksize == 0); - - /* - * token format is expected as: - * ----------------------------------------------- - * | krb5 header | head/tail cipher text | cksum | - * ----------------------------------------------- - */ - if (token->len < sizeof(*khdr) + blocksize + sizeof(*khdr) + - ke->ke_hash_size) { - CERROR("short token size: %u\n", token->len); - return GSS_S_DEFECTIVE_TOKEN; - } - - cipher.data = (__u8 *) (khdr + 1); - cipher.len = blocksize + sizeof(*khdr); - plain.data = cipher.data; - plain.len = cipher.len; - - rc = krb5_decrypt_bulk(kctx->kc_keye.kb_tfm, khdr, - desc, &cipher, &plain, adj_nob); - if (rc) - return GSS_S_DEFECTIVE_TOKEN; - - /* - * verify checksum, compose clear text as layout: - * ------------------------------------------ - * | confounder | clear pages | krb5 header | - * ------------------------------------------ - */ - data_desc[0].data = plain.data; - data_desc[0].len = blocksize; - - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 1, data_desc, - desc->bd_iov_count, desc->bd_iov, - &cksum)) - return GSS_S_FAILURE; - LASSERT(cksum.len >= ke->ke_hash_size); - - if (memcmp(plain.data + blocksize + sizeof(*khdr), - cksum.data + cksum.len - ke->ke_hash_size, - ke->ke_hash_size)) { - CERROR("checksum mismatch\n"); - rawobj_free(&cksum); - return GSS_S_BAD_SIG; - } - - rawobj_free(&cksum); - return GSS_S_COMPLETE; -} - -int gss_display_kerberos(struct gss_ctx *ctx, - char *buf, - int bufsize) -{ - struct krb5_ctx *kctx = ctx->internal_ctx_id; - int written; - - written = snprintf(buf, bufsize, "krb5 (%s)", - enctype2str(kctx->kc_enctype)); - return written; -} - -static struct gss_api_ops gss_kerberos_ops = { - .gss_import_sec_context = gss_import_sec_context_kerberos, - .gss_copy_reverse_context = gss_copy_reverse_context_kerberos, - .gss_inquire_context = gss_inquire_context_kerberos, - .gss_get_mic = gss_get_mic_kerberos, - .gss_verify_mic = gss_verify_mic_kerberos, - .gss_wrap = gss_wrap_kerberos, - .gss_unwrap = gss_unwrap_kerberos, - .gss_prep_bulk = gss_prep_bulk_kerberos, - .gss_wrap_bulk = gss_wrap_bulk_kerberos, - .gss_unwrap_bulk = gss_unwrap_bulk_kerberos, - .gss_delete_sec_context = gss_delete_sec_context_kerberos, - .gss_display = gss_display_kerberos, -}; - -static struct subflavor_desc gss_kerberos_sfs[] = { - { - .sf_subflavor = SPTLRPC_SUBFLVR_KRB5N, - .sf_qop = 0, - .sf_service = SPTLRPC_SVC_NULL, - .sf_name = "krb5n" - }, - { - .sf_subflavor = SPTLRPC_SUBFLVR_KRB5A, - .sf_qop = 0, - .sf_service = SPTLRPC_SVC_AUTH, - .sf_name = "krb5a" - }, - { - .sf_subflavor = SPTLRPC_SUBFLVR_KRB5I, - .sf_qop = 0, - .sf_service = SPTLRPC_SVC_INTG, - .sf_name = "krb5i" - }, - { - .sf_subflavor = SPTLRPC_SUBFLVR_KRB5P, - .sf_qop = 0, - .sf_service = SPTLRPC_SVC_PRIV, - .sf_name = "krb5p" - }, -}; - -/* - * currently we leave module owner NULL - */ -static struct gss_api_mech gss_kerberos_mech = { - .gm_owner = NULL, /*THIS_MODULE, */ - .gm_name = "krb5", - .gm_oid = (rawobj_t) - {9, "\052\206\110\206\367\022\001\002\002"}, - .gm_ops = &gss_kerberos_ops, - .gm_sf_num = 4, - .gm_sfs = gss_kerberos_sfs, -}; - -int __init init_kerberos_module(void) -{ - int status; - - spin_lock_init(&krb5_seq_lock); - - status = lgss_mech_register(&gss_kerberos_mech); - if (status) - CERROR("Failed to register kerberos gss mechanism!\n"); - return status; -} - -void __exit cleanup_kerberos_module(void) -{ - lgss_mech_unregister(&gss_kerberos_mech); -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c deleted file mode 100644 index 99462e085da7..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_mech_switch.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/net/sunrpc/gss_mech_switch.c - * - * Copyright (c) 2001 The Regents of the University of Michigan. - * All rights reserved. - * - * J. Bruce Fields <bfields@umich.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -static LIST_HEAD(registered_mechs); -static DEFINE_SPINLOCK(registered_mechs_lock); - -int lgss_mech_register(struct gss_api_mech *gm) -{ - spin_lock(®istered_mechs_lock); - list_add(&gm->gm_list, ®istered_mechs); - spin_unlock(®istered_mechs_lock); - CWARN("Register %s mechanism\n", gm->gm_name); - return 0; -} - -void lgss_mech_unregister(struct gss_api_mech *gm) -{ - spin_lock(®istered_mechs_lock); - list_del(&gm->gm_list); - spin_unlock(®istered_mechs_lock); - CWARN("Unregister %s mechanism\n", gm->gm_name); -} - - -struct gss_api_mech *lgss_mech_get(struct gss_api_mech *gm) -{ - __module_get(gm->gm_owner); - return gm; -} - -struct gss_api_mech *lgss_name_to_mech(char *name) -{ - struct gss_api_mech *pos, *gm = NULL; - - spin_lock(®istered_mechs_lock); - list_for_each_entry(pos, ®istered_mechs, gm_list) { - if (0 == strcmp(name, pos->gm_name)) { - if (!try_module_get(pos->gm_owner)) - continue; - gm = pos; - break; - } - } - spin_unlock(®istered_mechs_lock); - return gm; - -} - -static inline -int mech_supports_subflavor(struct gss_api_mech *gm, __u32 subflavor) -{ - int i; - - for (i = 0; i < gm->gm_sf_num; i++) { - if (gm->gm_sfs[i].sf_subflavor == subflavor) - return 1; - } - return 0; -} - -struct gss_api_mech *lgss_subflavor_to_mech(__u32 subflavor) -{ - struct gss_api_mech *pos, *gm = NULL; - - spin_lock(®istered_mechs_lock); - list_for_each_entry(pos, ®istered_mechs, gm_list) { - if (!try_module_get(pos->gm_owner)) - continue; - if (!mech_supports_subflavor(pos, subflavor)) { - module_put(pos->gm_owner); - continue; - } - gm = pos; - break; - } - spin_unlock(®istered_mechs_lock); - return gm; -} - -void lgss_mech_put(struct gss_api_mech *gm) -{ - module_put(gm->gm_owner); -} - -/* The mech could probably be determined from the token instead, but it's just - * as easy for now to pass it in. */ -__u32 lgss_import_sec_context(rawobj_t *input_token, - struct gss_api_mech *mech, - struct gss_ctx **ctx_id) -{ - OBD_ALLOC_PTR(*ctx_id); - if (*ctx_id == NULL) - return GSS_S_FAILURE; - - (*ctx_id)->mech_type = lgss_mech_get(mech); - - LASSERT(mech); - LASSERT(mech->gm_ops); - LASSERT(mech->gm_ops->gss_import_sec_context); - return mech->gm_ops->gss_import_sec_context(input_token, *ctx_id); -} - -__u32 lgss_copy_reverse_context(struct gss_ctx *ctx_id, - struct gss_ctx **ctx_id_new) -{ - struct gss_api_mech *mech = ctx_id->mech_type; - __u32 major; - - LASSERT(mech); - - OBD_ALLOC_PTR(*ctx_id_new); - if (*ctx_id_new == NULL) - return GSS_S_FAILURE; - - (*ctx_id_new)->mech_type = lgss_mech_get(mech); - - LASSERT(mech); - LASSERT(mech->gm_ops); - LASSERT(mech->gm_ops->gss_copy_reverse_context); - - major = mech->gm_ops->gss_copy_reverse_context(ctx_id, *ctx_id_new); - if (major != GSS_S_COMPLETE) { - lgss_mech_put(mech); - OBD_FREE_PTR(*ctx_id_new); - *ctx_id_new = NULL; - } - return major; -} - -/* - * this interface is much simplified, currently we only need endtime. - */ -__u32 lgss_inquire_context(struct gss_ctx *context_handle, - unsigned long *endtime) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_inquire_context); - - return context_handle->mech_type->gm_ops - ->gss_inquire_context(context_handle, - endtime); -} - -/* gss_get_mic: compute a mic over message and return mic_token. */ -__u32 lgss_get_mic(struct gss_ctx *context_handle, - int msgcnt, - rawobj_t *msg, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_get_mic); - - return context_handle->mech_type->gm_ops - ->gss_get_mic(context_handle, - msgcnt, - msg, - iovcnt, - iovs, - mic_token); -} - -/* gss_verify_mic: check whether the provided mic_token verifies message. */ -__u32 lgss_verify_mic(struct gss_ctx *context_handle, - int msgcnt, - rawobj_t *msg, - int iovcnt, - lnet_kiov_t *iovs, - rawobj_t *mic_token) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_verify_mic); - - return context_handle->mech_type->gm_ops - ->gss_verify_mic(context_handle, - msgcnt, - msg, - iovcnt, - iovs, - mic_token); -} - -__u32 lgss_wrap(struct gss_ctx *context_handle, - rawobj_t *gsshdr, - rawobj_t *msg, - int msg_buflen, - rawobj_t *out_token) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_wrap); - - return context_handle->mech_type->gm_ops - ->gss_wrap(context_handle, gsshdr, msg, msg_buflen, out_token); -} - -__u32 lgss_unwrap(struct gss_ctx *context_handle, - rawobj_t *gsshdr, - rawobj_t *token, - rawobj_t *out_msg) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_unwrap); - - return context_handle->mech_type->gm_ops - ->gss_unwrap(context_handle, gsshdr, token, out_msg); -} - - -__u32 lgss_prep_bulk(struct gss_ctx *context_handle, - struct ptlrpc_bulk_desc *desc) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_prep_bulk); - - return context_handle->mech_type->gm_ops - ->gss_prep_bulk(context_handle, desc); -} - -__u32 lgss_wrap_bulk(struct gss_ctx *context_handle, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_wrap_bulk); - - return context_handle->mech_type->gm_ops - ->gss_wrap_bulk(context_handle, desc, token, adj_nob); -} - -__u32 lgss_unwrap_bulk(struct gss_ctx *context_handle, - struct ptlrpc_bulk_desc *desc, - rawobj_t *token, - int adj_nob) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_unwrap_bulk); - - return context_handle->mech_type->gm_ops - ->gss_unwrap_bulk(context_handle, desc, token, adj_nob); -} - -/* gss_delete_sec_context: free all resources associated with context_handle. - * Note this differs from the RFC 2744-specified prototype in that we don't - * bother returning an output token, since it would never be used anyway. */ - -__u32 lgss_delete_sec_context(struct gss_ctx **context_handle) -{ - struct gss_api_mech *mech; - - CDEBUG(D_SEC, "deleting %p\n", *context_handle); - - if (!*context_handle) - return(GSS_S_NO_CONTEXT); - - mech = (*context_handle)->mech_type; - if ((*context_handle)->internal_ctx_id != 0) { - LASSERT(mech); - LASSERT(mech->gm_ops); - LASSERT(mech->gm_ops->gss_delete_sec_context); - mech->gm_ops->gss_delete_sec_context( - (*context_handle)->internal_ctx_id); - } - if (mech) - lgss_mech_put(mech); - - OBD_FREE_PTR(*context_handle); - *context_handle=NULL; - return GSS_S_COMPLETE; -} - -int lgss_display(struct gss_ctx *ctx, - char *buf, - int bufsize) -{ - LASSERT(ctx); - LASSERT(ctx->mech_type); - LASSERT(ctx->mech_type->gm_ops); - LASSERT(ctx->mech_type->gm_ops->gss_display); - - return ctx->mech_type->gm_ops->gss_display(ctx, buf, bufsize); -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c deleted file mode 100644 index 3be5bc14c4ed..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/net/sunrpc/auth_gss.c - * - * RPCSEC_GSS client authentication. - * - * Copyright (c) 2000 The Regents of the University of Michigan. - * All rights reserved. - * - * Dug Song <dugsong@monkey.org> - * Andy Adamson <andros@umich.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/mutex.h> -#include <linux/crypto.h> -#include <asm/atomic.h> -struct rpc_clnt; /* for rpc_pipefs */ -#include <linux/sunrpc/rpc_pipe_fs.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_sec.h> -#include <lustre_net.h> -#include <lustre_import.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -static struct ptlrpc_sec_policy gss_policy_pipefs; -static struct ptlrpc_ctx_ops gss_pipefs_ctxops; - -static int gss_cli_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx); - -static int gss_sec_pipe_upcall_init(struct gss_sec *gsec) -{ - return 0; -} - -static void gss_sec_pipe_upcall_fini(struct gss_sec *gsec) -{ -} - -/**************************************** - * internal context helpers * - ****************************************/ - -static -struct ptlrpc_cli_ctx *ctx_create_pf(struct ptlrpc_sec *sec, - struct vfs_cred *vcred) -{ - struct gss_cli_ctx *gctx; - int rc; - - OBD_ALLOC_PTR(gctx); - if (gctx == NULL) - return NULL; - - rc = gss_cli_ctx_init_common(sec, &gctx->gc_base, - &gss_pipefs_ctxops, vcred); - if (rc) { - OBD_FREE_PTR(gctx); - return NULL; - } - - return &gctx->gc_base; -} - -static -void ctx_destroy_pf(struct ptlrpc_sec *sec, struct ptlrpc_cli_ctx *ctx) -{ - struct gss_cli_ctx *gctx = ctx2gctx(ctx); - - if (gss_cli_ctx_fini_common(sec, ctx)) - return; - - OBD_FREE_PTR(gctx); - - atomic_dec(&sec->ps_nctx); - sptlrpc_sec_put(sec); -} - -static -void ctx_enhash_pf(struct ptlrpc_cli_ctx *ctx, struct hlist_head *hash) -{ - set_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags); - atomic_inc(&ctx->cc_refcount); - hlist_add_head(&ctx->cc_cache, hash); -} - -/* - * caller must hold spinlock - */ -static -void ctx_unhash_pf(struct ptlrpc_cli_ctx *ctx, struct hlist_head *freelist) -{ - assert_spin_locked(&ctx->cc_sec->ps_lock); - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags)); - LASSERT(!hlist_unhashed(&ctx->cc_cache)); - - clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags); - - if (atomic_dec_and_test(&ctx->cc_refcount)) { - __hlist_del(&ctx->cc_cache); - hlist_add_head(&ctx->cc_cache, freelist); - } else { - hlist_del_init(&ctx->cc_cache); - } -} - -/* - * return 1 if the context is dead. - */ -static -int ctx_check_death_pf(struct ptlrpc_cli_ctx *ctx, - struct hlist_head *freelist) -{ - if (cli_ctx_check_death(ctx)) { - if (freelist) - ctx_unhash_pf(ctx, freelist); - return 1; - } - - return 0; -} - -static inline -int ctx_check_death_locked_pf(struct ptlrpc_cli_ctx *ctx, - struct hlist_head *freelist) -{ - LASSERT(ctx->cc_sec); - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags)); - - return ctx_check_death_pf(ctx, freelist); -} - -static inline -int ctx_match_pf(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred) -{ - /* a little bit optimization for null policy */ - if (!ctx->cc_ops->match) - return 1; - - return ctx->cc_ops->match(ctx, vcred); -} - -static -void ctx_list_destroy_pf(struct hlist_head *head) -{ - struct ptlrpc_cli_ctx *ctx; - - while (!hlist_empty(head)) { - ctx = hlist_entry(head->first, struct ptlrpc_cli_ctx, - cc_cache); - - LASSERT(atomic_read(&ctx->cc_refcount) == 0); - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, - &ctx->cc_flags) == 0); - - hlist_del_init(&ctx->cc_cache); - ctx_destroy_pf(ctx->cc_sec, ctx); - } -} - -/**************************************** - * context apis * - ****************************************/ - -static -int gss_cli_ctx_validate_pf(struct ptlrpc_cli_ctx *ctx) -{ - if (ctx_check_death_pf(ctx, NULL)) - return 1; - if (cli_ctx_is_ready(ctx)) - return 0; - return 1; -} - -static -void gss_cli_ctx_die_pf(struct ptlrpc_cli_ctx *ctx, int grace) -{ - LASSERT(ctx->cc_sec); - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - cli_ctx_expire(ctx); - - spin_lock(&ctx->cc_sec->ps_lock); - - if (test_and_clear_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags)) { - LASSERT(!hlist_unhashed(&ctx->cc_cache)); - LASSERT(atomic_read(&ctx->cc_refcount) > 1); - - hlist_del_init(&ctx->cc_cache); - if (atomic_dec_and_test(&ctx->cc_refcount)) - LBUG(); - } - - spin_unlock(&ctx->cc_sec->ps_lock); -} - -/**************************************** - * reverse context installation * - ****************************************/ - -static inline -unsigned int ctx_hash_index(int hashsize, __u64 key) -{ - return (unsigned int) (key & ((__u64) hashsize - 1)); -} - -static -void gss_sec_ctx_replace_pf(struct gss_sec *gsec, - struct ptlrpc_cli_ctx *new) -{ - struct gss_sec_pipefs *gsec_pf; - struct ptlrpc_cli_ctx *ctx; - struct hlist_node *next; - HLIST_HEAD(freelist); - unsigned int hash; - - gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base); - - hash = ctx_hash_index(gsec_pf->gsp_chash_size, - (__u64) new->cc_vcred.vc_uid); - LASSERT(hash < gsec_pf->gsp_chash_size); - - spin_lock(&gsec->gs_base.ps_lock); - - hlist_for_each_entry_safe(ctx, next, - &gsec_pf->gsp_chash[hash], cc_cache) { - if (!ctx_match_pf(ctx, &new->cc_vcred)) - continue; - - cli_ctx_expire(ctx); - ctx_unhash_pf(ctx, &freelist); - break; - } - - ctx_enhash_pf(new, &gsec_pf->gsp_chash[hash]); - - spin_unlock(&gsec->gs_base.ps_lock); - - ctx_list_destroy_pf(&freelist); -} - -static -int gss_install_rvs_cli_ctx_pf(struct gss_sec *gsec, - struct ptlrpc_svc_ctx *svc_ctx) -{ - struct vfs_cred vcred; - struct ptlrpc_cli_ctx *cli_ctx; - int rc; - - vcred.vc_uid = 0; - vcred.vc_gid = 0; - - cli_ctx = ctx_create_pf(&gsec->gs_base, &vcred); - if (!cli_ctx) - return -ENOMEM; - - rc = gss_copy_rvc_cli_ctx(cli_ctx, svc_ctx); - if (rc) { - ctx_destroy_pf(cli_ctx->cc_sec, cli_ctx); - return rc; - } - - gss_sec_ctx_replace_pf(gsec, cli_ctx); - return 0; -} - -static -void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf, - struct hlist_head *freelist) -{ - struct ptlrpc_sec *sec; - struct ptlrpc_cli_ctx *ctx; - struct hlist_node *next; - int i; - - sec = &gsec_pf->gsp_base.gs_base; - - CDEBUG(D_SEC, "do gc on sec %s@%p\n", sec->ps_policy->sp_name, sec); - - for (i = 0; i < gsec_pf->gsp_chash_size; i++) { - hlist_for_each_entry_safe(ctx, next, - &gsec_pf->gsp_chash[i], cc_cache) - ctx_check_death_locked_pf(ctx, freelist); - } - - sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval; -} - -static -struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp, - struct ptlrpc_svc_ctx *ctx, - struct sptlrpc_flavor *sf) -{ - struct gss_sec_pipefs *gsec_pf; - int alloc_size, hash_size, i; - -#define GSS_SEC_PIPEFS_CTX_HASH_SIZE (32) - - if (ctx || - sf->sf_flags & (PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_REVERSE)) - hash_size = 1; - else - hash_size = GSS_SEC_PIPEFS_CTX_HASH_SIZE; - - alloc_size = sizeof(*gsec_pf) + - sizeof(struct hlist_head) * hash_size; - - OBD_ALLOC(gsec_pf, alloc_size); - if (!gsec_pf) - return NULL; - - gsec_pf->gsp_chash_size = hash_size; - for (i = 0; i < hash_size; i++) - INIT_HLIST_HEAD(&gsec_pf->gsp_chash[i]); - - if (gss_sec_create_common(&gsec_pf->gsp_base, &gss_policy_pipefs, - imp, ctx, sf)) - goto err_free; - - if (ctx == NULL) { - if (gss_sec_pipe_upcall_init(&gsec_pf->gsp_base)) - goto err_destroy; - } else { - if (gss_install_rvs_cli_ctx_pf(&gsec_pf->gsp_base, ctx)) - goto err_destroy; - } - - return &gsec_pf->gsp_base.gs_base; - -err_destroy: - gss_sec_destroy_common(&gsec_pf->gsp_base); -err_free: - OBD_FREE(gsec_pf, alloc_size); - return NULL; -} - -static -void gss_sec_destroy_pf(struct ptlrpc_sec *sec) -{ - struct gss_sec_pipefs *gsec_pf; - struct gss_sec *gsec; - - CWARN("destroy %s@%p\n", sec->ps_policy->sp_name, sec); - - gsec = container_of(sec, struct gss_sec, gs_base); - gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base); - - LASSERT(gsec_pf->gsp_chash); - LASSERT(gsec_pf->gsp_chash_size); - - gss_sec_pipe_upcall_fini(gsec); - - gss_sec_destroy_common(gsec); - - OBD_FREE(gsec, sizeof(*gsec_pf) + - sizeof(struct hlist_head) * gsec_pf->gsp_chash_size); -} - -static -struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_pf(struct ptlrpc_sec *sec, - struct vfs_cred *vcred, - int create, int remove_dead) -{ - struct gss_sec *gsec; - struct gss_sec_pipefs *gsec_pf; - struct ptlrpc_cli_ctx *ctx = NULL, *new = NULL; - struct hlist_head *hash_head; - struct hlist_node *next; - HLIST_HEAD(freelist); - unsigned int hash, gc = 0, found = 0; - - might_sleep(); - - gsec = container_of(sec, struct gss_sec, gs_base); - gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base); - - hash = ctx_hash_index(gsec_pf->gsp_chash_size, - (__u64) vcred->vc_uid); - hash_head = &gsec_pf->gsp_chash[hash]; - LASSERT(hash < gsec_pf->gsp_chash_size); - -retry: - spin_lock(&sec->ps_lock); - - /* gc_next == 0 means never do gc */ - if (remove_dead && sec->ps_gc_next && - cfs_time_after(cfs_time_current_sec(), sec->ps_gc_next)) { - gss_ctx_cache_gc_pf(gsec_pf, &freelist); - gc = 1; - } - - hlist_for_each_entry_safe(ctx, next, hash_head, cc_cache) { - if (gc == 0 && - ctx_check_death_locked_pf(ctx, - remove_dead ? &freelist : NULL)) - continue; - - if (ctx_match_pf(ctx, vcred)) { - found = 1; - break; - } - } - - if (found) { - if (new && new != ctx) { - /* lost the race, just free it */ - hlist_add_head(&new->cc_cache, &freelist); - new = NULL; - } - - /* hot node, move to head */ - if (hash_head->first != &ctx->cc_cache) { - __hlist_del(&ctx->cc_cache); - hlist_add_head(&ctx->cc_cache, hash_head); - } - } else { - /* don't allocate for reverse sec */ - if (sec_is_reverse(sec)) { - spin_unlock(&sec->ps_lock); - return NULL; - } - - if (new) { - ctx_enhash_pf(new, hash_head); - ctx = new; - } else if (create) { - spin_unlock(&sec->ps_lock); - new = ctx_create_pf(sec, vcred); - if (new) { - clear_bit(PTLRPC_CTX_NEW_BIT, &new->cc_flags); - goto retry; - } - } else { - ctx = NULL; - } - } - - /* hold a ref */ - if (ctx) - atomic_inc(&ctx->cc_refcount); - - spin_unlock(&sec->ps_lock); - - /* the allocator of the context must give the first push to refresh */ - if (new) { - LASSERT(new == ctx); - gss_cli_ctx_refresh_pf(new); - } - - ctx_list_destroy_pf(&freelist); - return ctx; -} - -static -void gss_sec_release_ctx_pf(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx, - int sync) -{ - LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0); - LASSERT(hlist_unhashed(&ctx->cc_cache)); - - /* if required async, we must clear the UPTODATE bit to prevent extra - * rpcs during destroy procedure. */ - if (!sync) - clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags); - - /* destroy this context */ - ctx_destroy_pf(sec, ctx); -} - -/* - * @uid: which user. "-1" means flush all. - * @grace: mark context DEAD, allow graceful destroy like notify - * server side, etc. - * @force: also flush busy entries. - * - * return the number of busy context encountered. - * - * In any cases, never touch "eternal" contexts. - */ -static -int gss_sec_flush_ctx_cache_pf(struct ptlrpc_sec *sec, - uid_t uid, - int grace, int force) -{ - struct gss_sec *gsec; - struct gss_sec_pipefs *gsec_pf; - struct ptlrpc_cli_ctx *ctx; - struct hlist_node *next; - HLIST_HEAD(freelist); - int i, busy = 0; - - might_sleep_if(grace); - - gsec = container_of(sec, struct gss_sec, gs_base); - gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base); - - spin_lock(&sec->ps_lock); - for (i = 0; i < gsec_pf->gsp_chash_size; i++) { - hlist_for_each_entry_safe(ctx, next, - &gsec_pf->gsp_chash[i], - cc_cache) { - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - - if (uid != -1 && uid != ctx->cc_vcred.vc_uid) - continue; - - if (atomic_read(&ctx->cc_refcount) > 1) { - busy++; - if (!force) - continue; - - CWARN("flush busy(%d) ctx %p(%u->%s) by force, " - "grace %d\n", - atomic_read(&ctx->cc_refcount), - ctx, ctx->cc_vcred.vc_uid, - sec2target_str(ctx->cc_sec), grace); - } - ctx_unhash_pf(ctx, &freelist); - - set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags); - if (!grace) - clear_bit(PTLRPC_CTX_UPTODATE_BIT, - &ctx->cc_flags); - } - } - spin_unlock(&sec->ps_lock); - - ctx_list_destroy_pf(&freelist); - return busy; -} - -/**************************************** - * service apis * - ****************************************/ - -static -int gss_svc_accept_pf(struct ptlrpc_request *req) -{ - return gss_svc_accept(&gss_policy_pipefs, req); -} - -static -int gss_svc_install_rctx_pf(struct obd_import *imp, - struct ptlrpc_svc_ctx *ctx) -{ - struct ptlrpc_sec *sec; - int rc; - - sec = sptlrpc_import_sec_ref(imp); - LASSERT(sec); - rc = gss_install_rvs_cli_ctx_pf(sec2gsec(sec), ctx); - - sptlrpc_sec_put(sec); - return rc; -} - -/**************************************** - * rpc_pipefs definitions * - ****************************************/ - -#define LUSTRE_PIPE_ROOT "/lustre" -#define LUSTRE_PIPE_KRB5 LUSTRE_PIPE_ROOT"/krb5" - -struct gss_upcall_msg_data { - __u32 gum_seq; - __u32 gum_uid; - __u32 gum_gid; - __u32 gum_svc; /* MDS/OSS... */ - __u64 gum_nid; /* peer NID */ - __u8 gum_obd[64]; /* client obd name */ -}; - -struct gss_upcall_msg { - struct rpc_pipe_msg gum_base; - atomic_t gum_refcount; - struct list_head gum_list; - __u32 gum_mechidx; - struct gss_sec *gum_gsec; - struct gss_cli_ctx *gum_gctx; - struct gss_upcall_msg_data gum_data; -}; - -static atomic_t upcall_seq = ATOMIC_INIT(0); - -static inline -__u32 upcall_get_sequence(void) -{ - return (__u32) atomic_inc_return(&upcall_seq); -} - -enum mech_idx_t { - MECH_KRB5 = 0, - MECH_MAX -}; - -static inline -__u32 mech_name2idx(const char *name) -{ - LASSERT(!strcmp(name, "krb5")); - return MECH_KRB5; -} - -/* pipefs dentries for each mechanisms */ -static struct dentry *de_pipes[MECH_MAX] = { NULL, }; -/* all upcall messages linked here */ -static struct list_head upcall_lists[MECH_MAX]; -/* and protected by this */ -static spinlock_t upcall_locks[MECH_MAX]; - -static inline -void upcall_list_lock(int idx) -{ - spin_lock(&upcall_locks[idx]); -} - -static inline -void upcall_list_unlock(int idx) -{ - spin_unlock(&upcall_locks[idx]); -} - -static -void upcall_msg_enlist(struct gss_upcall_msg *msg) -{ - __u32 idx = msg->gum_mechidx; - - upcall_list_lock(idx); - list_add(&msg->gum_list, &upcall_lists[idx]); - upcall_list_unlock(idx); -} - -static -void upcall_msg_delist(struct gss_upcall_msg *msg) -{ - __u32 idx = msg->gum_mechidx; - - upcall_list_lock(idx); - list_del_init(&msg->gum_list); - upcall_list_unlock(idx); -} - -/**************************************** - * rpc_pipefs upcall helpers * - ****************************************/ - -static -void gss_release_msg(struct gss_upcall_msg *gmsg) -{ - LASSERT(atomic_read(&gmsg->gum_refcount) > 0); - - if (!atomic_dec_and_test(&gmsg->gum_refcount)) { - return; - } - - if (gmsg->gum_gctx) { - sptlrpc_cli_ctx_wakeup(&gmsg->gum_gctx->gc_base); - sptlrpc_cli_ctx_put(&gmsg->gum_gctx->gc_base, 1); - gmsg->gum_gctx = NULL; - } - - LASSERT(list_empty(&gmsg->gum_list)); - LASSERT(list_empty(&gmsg->gum_base.list)); - OBD_FREE_PTR(gmsg); -} - -static -void gss_unhash_msg_nolock(struct gss_upcall_msg *gmsg) -{ - __u32 idx = gmsg->gum_mechidx; - - LASSERT(idx < MECH_MAX); - assert_spin_locked(&upcall_locks[idx]); - - if (list_empty(&gmsg->gum_list)) - return; - - list_del_init(&gmsg->gum_list); - LASSERT(atomic_read(&gmsg->gum_refcount) > 1); - atomic_dec(&gmsg->gum_refcount); -} - -static -void gss_unhash_msg(struct gss_upcall_msg *gmsg) -{ - __u32 idx = gmsg->gum_mechidx; - - LASSERT(idx < MECH_MAX); - upcall_list_lock(idx); - gss_unhash_msg_nolock(gmsg); - upcall_list_unlock(idx); -} - -static -void gss_msg_fail_ctx(struct gss_upcall_msg *gmsg) -{ - if (gmsg->gum_gctx) { - struct ptlrpc_cli_ctx *ctx = &gmsg->gum_gctx->gc_base; - - LASSERT(atomic_read(&ctx->cc_refcount) > 0); - sptlrpc_cli_ctx_expire(ctx); - set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags); - } -} - -static -struct gss_upcall_msg * gss_find_upcall(__u32 mechidx, __u32 seq) -{ - struct gss_upcall_msg *gmsg; - - upcall_list_lock(mechidx); - list_for_each_entry(gmsg, &upcall_lists[mechidx], gum_list) { - if (gmsg->gum_data.gum_seq != seq) - continue; - - LASSERT(atomic_read(&gmsg->gum_refcount) > 0); - LASSERT(gmsg->gum_mechidx == mechidx); - - atomic_inc(&gmsg->gum_refcount); - upcall_list_unlock(mechidx); - return gmsg; - } - upcall_list_unlock(mechidx); - return NULL; -} - -static -int simple_get_bytes(char **buf, __u32 *buflen, void *res, __u32 reslen) -{ - if (*buflen < reslen) { - CERROR("buflen %u < %u\n", *buflen, reslen); - return -EINVAL; - } - - memcpy(res, *buf, reslen); - *buf += reslen; - *buflen -= reslen; - return 0; -} - -/**************************************** - * rpc_pipefs apis * - ****************************************/ - -static -ssize_t gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, - char *dst, size_t buflen) -{ - char *data = (char *)msg->data + msg->copied; - ssize_t mlen = msg->len; - ssize_t left; - - if (mlen > buflen) - mlen = buflen; - left = copy_to_user(dst, data, mlen); - if (left < 0) { - msg->errno = left; - return left; - } - mlen -= left; - msg->copied += mlen; - msg->errno = 0; - return mlen; -} - -static -ssize_t gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) -{ - struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode); - struct gss_upcall_msg *gss_msg; - struct ptlrpc_cli_ctx *ctx; - struct gss_cli_ctx *gctx = NULL; - char *buf, *data; - int datalen; - int timeout, rc; - __u32 mechidx, seq, gss_err; - - mechidx = (__u32) (long) rpci->private; - LASSERT(mechidx < MECH_MAX); - - OBD_ALLOC(buf, mlen); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, src, mlen)) { - CERROR("failed copy user space data\n"); - GOTO(out_free, rc = -EFAULT); - } - data = buf; - datalen = mlen; - - /* data passed down format: - * - seq - * - timeout - * - gc_win / error - * - wire_ctx (rawobj) - * - mech_ctx (rawobj) - */ - if (simple_get_bytes(&data, &datalen, &seq, sizeof(seq))) { - CERROR("fail to get seq\n"); - GOTO(out_free, rc = -EFAULT); - } - - gss_msg = gss_find_upcall(mechidx, seq); - if (!gss_msg) { - CERROR("upcall %u has aborted earlier\n", seq); - GOTO(out_free, rc = -EINVAL); - } - - gss_unhash_msg(gss_msg); - gctx = gss_msg->gum_gctx; - LASSERT(gctx); - LASSERT(atomic_read(&gctx->gc_base.cc_refcount) > 0); - - /* timeout is not in use for now */ - if (simple_get_bytes(&data, &datalen, &timeout, sizeof(timeout))) - GOTO(out_msg, rc = -EFAULT); - - /* lgssd signal an error by gc_win == 0 */ - if (simple_get_bytes(&data, &datalen, &gctx->gc_win, - sizeof(gctx->gc_win))) - GOTO(out_msg, rc = -EFAULT); - - if (gctx->gc_win == 0) { - /* followed by: - * - rpc error - * - gss error - */ - if (simple_get_bytes(&data, &datalen, &rc, sizeof(rc))) - GOTO(out_msg, rc = -EFAULT); - if (simple_get_bytes(&data, &datalen, &gss_err,sizeof(gss_err))) - GOTO(out_msg, rc = -EFAULT); - - if (rc == 0 && gss_err == GSS_S_COMPLETE) { - CWARN("both rpc & gss error code not set\n"); - rc = -EPERM; - } - } else { - rawobj_t tmpobj; - - /* handle */ - if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen)) - GOTO(out_msg, rc = -EFAULT); - if (rawobj_dup(&gctx->gc_handle, &tmpobj)) - GOTO(out_msg, rc = -ENOMEM); - - /* mechctx */ - if (rawobj_extract_local(&tmpobj, (__u32 **) &data, &datalen)) - GOTO(out_msg, rc = -EFAULT); - gss_err = lgss_import_sec_context(&tmpobj, - gss_msg->gum_gsec->gs_mech, - &gctx->gc_mechctx); - rc = 0; - } - - if (likely(rc == 0 && gss_err == GSS_S_COMPLETE)) { - gss_cli_ctx_uptodate(gctx); - } else { - ctx = &gctx->gc_base; - sptlrpc_cli_ctx_expire(ctx); - if (rc != -ERESTART || gss_err != GSS_S_COMPLETE) - set_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags); - - CERROR("refresh ctx %p(uid %d) failed: %d/0x%08x: %s\n", - ctx, ctx->cc_vcred.vc_uid, rc, gss_err, - test_bit(PTLRPC_CTX_ERROR_BIT, &ctx->cc_flags) ? - "fatal error" : "non-fatal"); - } - - rc = mlen; - -out_msg: - gss_release_msg(gss_msg); - -out_free: - OBD_FREE(buf, mlen); - /* FIXME - * hack pipefs: always return asked length unless all following - * downcalls might be messed up. */ - rc = mlen; - return rc; -} - -static -void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) -{ - struct gss_upcall_msg *gmsg; - struct gss_upcall_msg_data *gumd; - static cfs_time_t ratelimit = 0; - - LASSERT(list_empty(&msg->list)); - - /* normally errno is >= 0 */ - if (msg->errno >= 0) { - return; - } - - gmsg = container_of(msg, struct gss_upcall_msg, gum_base); - gumd = &gmsg->gum_data; - LASSERT(atomic_read(&gmsg->gum_refcount) > 0); - - CERROR("failed msg %p (seq %u, uid %u, svc %u, nid "LPX64", obd %.*s): " - "errno %d\n", msg, gumd->gum_seq, gumd->gum_uid, gumd->gum_svc, - gumd->gum_nid, (int) sizeof(gumd->gum_obd), - gumd->gum_obd, msg->errno); - - atomic_inc(&gmsg->gum_refcount); - gss_unhash_msg(gmsg); - if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) { - cfs_time_t now = cfs_time_current_sec(); - - if (cfs_time_after(now, ratelimit)) { - CWARN("upcall timed out, is lgssd running?\n"); - ratelimit = now + 15; - } - } - gss_msg_fail_ctx(gmsg); - gss_release_msg(gmsg); -} - -static -void gss_pipe_release(struct inode *inode) -{ - struct rpc_inode *rpci = RPC_I(inode); - __u32 idx; - - idx = (__u32) (long) rpci->private; - LASSERT(idx < MECH_MAX); - - upcall_list_lock(idx); - while (!list_empty(&upcall_lists[idx])) { - struct gss_upcall_msg *gmsg; - struct gss_upcall_msg_data *gumd; - - gmsg = list_entry(upcall_lists[idx].next, - struct gss_upcall_msg, gum_list); - gumd = &gmsg->gum_data; - LASSERT(list_empty(&gmsg->gum_base.list)); - - CERROR("failing remaining msg %p:seq %u, uid %u, svc %u, " - "nid "LPX64", obd %.*s\n", gmsg, - gumd->gum_seq, gumd->gum_uid, gumd->gum_svc, - gumd->gum_nid, (int) sizeof(gumd->gum_obd), - gumd->gum_obd); - - gmsg->gum_base.errno = -EPIPE; - atomic_inc(&gmsg->gum_refcount); - gss_unhash_msg_nolock(gmsg); - - gss_msg_fail_ctx(gmsg); - - upcall_list_unlock(idx); - gss_release_msg(gmsg); - upcall_list_lock(idx); - } - upcall_list_unlock(idx); -} - -static struct rpc_pipe_ops gss_upcall_ops = { - .upcall = gss_pipe_upcall, - .downcall = gss_pipe_downcall, - .destroy_msg = gss_pipe_destroy_msg, - .release_pipe = gss_pipe_release, -}; - -/**************************************** - * upcall helper functions * - ****************************************/ - -static -int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx) -{ - struct obd_import *imp; - struct gss_sec *gsec; - struct gss_upcall_msg *gmsg; - int rc = 0; - - might_sleep(); - - LASSERT(ctx->cc_sec); - LASSERT(ctx->cc_sec->ps_import); - LASSERT(ctx->cc_sec->ps_import->imp_obd); - - imp = ctx->cc_sec->ps_import; - if (!imp->imp_connection) { - CERROR("import has no connection set\n"); - return -EINVAL; - } - - gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base); - - OBD_ALLOC_PTR(gmsg); - if (!gmsg) - return -ENOMEM; - - /* initialize pipefs base msg */ - INIT_LIST_HEAD(&gmsg->gum_base.list); - gmsg->gum_base.data = &gmsg->gum_data; - gmsg->gum_base.len = sizeof(gmsg->gum_data); - gmsg->gum_base.copied = 0; - gmsg->gum_base.errno = 0; - - /* init upcall msg */ - atomic_set(&gmsg->gum_refcount, 1); - gmsg->gum_mechidx = mech_name2idx(gsec->gs_mech->gm_name); - gmsg->gum_gsec = gsec; - gmsg->gum_gctx = container_of(sptlrpc_cli_ctx_get(ctx), - struct gss_cli_ctx, gc_base); - gmsg->gum_data.gum_seq = upcall_get_sequence(); - gmsg->gum_data.gum_uid = ctx->cc_vcred.vc_uid; - gmsg->gum_data.gum_gid = 0; /* not used for now */ - gmsg->gum_data.gum_svc = import_to_gss_svc(imp); - gmsg->gum_data.gum_nid = imp->imp_connection->c_peer.nid; - strncpy(gmsg->gum_data.gum_obd, imp->imp_obd->obd_name, - sizeof(gmsg->gum_data.gum_obd)); - - /* This only could happen when sysadmin set it dead/expired - * using lctl by force. */ - if (ctx->cc_flags & PTLRPC_CTX_STATUS_MASK) { - CWARN("ctx %p(%u->%s) was set flags %lx unexpectedly\n", - ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), - ctx->cc_flags); - - LASSERT(!(ctx->cc_flags & PTLRPC_CTX_UPTODATE)); - ctx->cc_flags |= PTLRPC_CTX_DEAD | PTLRPC_CTX_ERROR; - - rc = -EIO; - goto err_free; - } - - upcall_msg_enlist(gmsg); - - rc = rpc_queue_upcall(de_pipes[gmsg->gum_mechidx]->d_inode, - &gmsg->gum_base); - if (rc) { - CERROR("rpc_queue_upcall failed: %d\n", rc); - - upcall_msg_delist(gmsg); - goto err_free; - } - - return 0; -err_free: - OBD_FREE_PTR(gmsg); - return rc; -} - -static -int gss_cli_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx) -{ - /* if we are refreshing for root, also update the reverse - * handle index, do not confuse reverse contexts. */ - if (ctx->cc_vcred.vc_uid == 0) { - struct gss_sec *gsec; - - gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base); - gsec->gs_rvs_hdl = gss_get_next_ctx_index(); - } - - return gss_ctx_refresh_pf(ctx); -} - -/**************************************** - * lustre gss pipefs policy * - ****************************************/ - -static struct ptlrpc_ctx_ops gss_pipefs_ctxops = { - .match = gss_cli_ctx_match, - .refresh = gss_cli_ctx_refresh_pf, - .validate = gss_cli_ctx_validate_pf, - .die = gss_cli_ctx_die_pf, - .sign = gss_cli_ctx_sign, - .verify = gss_cli_ctx_verify, - .seal = gss_cli_ctx_seal, - .unseal = gss_cli_ctx_unseal, - .wrap_bulk = gss_cli_ctx_wrap_bulk, - .unwrap_bulk = gss_cli_ctx_unwrap_bulk, -}; - -static struct ptlrpc_sec_cops gss_sec_pipefs_cops = { - .create_sec = gss_sec_create_pf, - .destroy_sec = gss_sec_destroy_pf, - .kill_sec = gss_sec_kill, - .lookup_ctx = gss_sec_lookup_ctx_pf, - .release_ctx = gss_sec_release_ctx_pf, - .flush_ctx_cache = gss_sec_flush_ctx_cache_pf, - .install_rctx = gss_sec_install_rctx, - .alloc_reqbuf = gss_alloc_reqbuf, - .free_reqbuf = gss_free_reqbuf, - .alloc_repbuf = gss_alloc_repbuf, - .free_repbuf = gss_free_repbuf, - .enlarge_reqbuf = gss_enlarge_reqbuf, -}; - -static struct ptlrpc_sec_sops gss_sec_pipefs_sops = { - .accept = gss_svc_accept_pf, - .invalidate_ctx = gss_svc_invalidate_ctx, - .alloc_rs = gss_svc_alloc_rs, - .authorize = gss_svc_authorize, - .free_rs = gss_svc_free_rs, - .free_ctx = gss_svc_free_ctx, - .unwrap_bulk = gss_svc_unwrap_bulk, - .wrap_bulk = gss_svc_wrap_bulk, - .install_rctx = gss_svc_install_rctx_pf, -}; - -static struct ptlrpc_sec_policy gss_policy_pipefs = { - .sp_owner = THIS_MODULE, - .sp_name = "gss.pipefs", - .sp_policy = SPTLRPC_POLICY_GSS_PIPEFS, - .sp_cops = &gss_sec_pipefs_cops, - .sp_sops = &gss_sec_pipefs_sops, -}; - -static -int __init gss_init_pipefs_upcall(void) -{ - struct dentry *de; - - /* pipe dir */ - de = rpc_mkdir(LUSTRE_PIPE_ROOT, NULL); - if (IS_ERR(de) && PTR_ERR(de) != -EEXIST) { - CERROR("Failed to create gss pipe dir: %ld\n", PTR_ERR(de)); - return PTR_ERR(de); - } - - /* FIXME hack pipefs: dput will sometimes cause oops during module - * unload and lgssd close the pipe fds. */ - - /* krb5 mechanism */ - de = rpc_mkpipe(LUSTRE_PIPE_KRB5, (void *) MECH_KRB5, &gss_upcall_ops, - RPC_PIPE_WAIT_FOR_OPEN); - if (!de || IS_ERR(de)) { - CERROR("failed to make rpc_pipe %s: %ld\n", - LUSTRE_PIPE_KRB5, PTR_ERR(de)); - rpc_rmdir(LUSTRE_PIPE_ROOT); - return PTR_ERR(de); - } - - de_pipes[MECH_KRB5] = de; - INIT_LIST_HEAD(&upcall_lists[MECH_KRB5]); - spin_lock_init(&upcall_locks[MECH_KRB5]); - - return 0; -} - -static -void __exit gss_exit_pipefs_upcall(void) -{ - __u32 i; - - for (i = 0; i < MECH_MAX; i++) { - LASSERT(list_empty(&upcall_lists[i])); - - /* dput pipe dentry here might cause lgssd oops. */ - de_pipes[i] = NULL; - } - - rpc_unlink(LUSTRE_PIPE_KRB5); - rpc_rmdir(LUSTRE_PIPE_ROOT); -} - -int __init gss_init_pipefs(void) -{ - int rc; - - rc = gss_init_pipefs_upcall(); - if (rc) - return rc; - - rc = sptlrpc_register_policy(&gss_policy_pipefs); - if (rc) { - gss_exit_pipefs_upcall(); - return rc; - } - - return 0; -} - -void __exit gss_exit_pipefs(void) -{ - gss_exit_pipefs_upcall(); - sptlrpc_unregister_policy(&gss_policy_pipefs); -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c deleted file mode 100644 index fb298aef66eb..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_rawobj.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/ptlrpc/gss/gss_rawobj.c - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -#define DEBUG_SUBSYSTEM S_SEC - -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre_sec.h> - -#include "gss_internal.h" - -int rawobj_empty(rawobj_t *obj) -{ - LASSERT(equi(obj->len, obj->data)); - return (obj->len == 0); -} - -int rawobj_alloc(rawobj_t *obj, char *buf, int len) -{ - LASSERT(obj); - LASSERT(len >= 0); - - obj->len = len; - if (len) { - OBD_ALLOC_LARGE(obj->data, len); - if (!obj->data) { - obj->len = 0; - return -ENOMEM; - } - memcpy(obj->data, buf, len); - } else - obj->data = NULL; - return 0; -} - -void rawobj_free(rawobj_t *obj) -{ - LASSERT(obj); - - if (obj->len) { - LASSERT(obj->data); - OBD_FREE_LARGE(obj->data, obj->len); - obj->len = 0; - obj->data = NULL; - } else - LASSERT(!obj->data); -} - -int rawobj_equal(rawobj_t *a, rawobj_t *b) -{ - LASSERT(a && b); - - return (a->len == b->len && - (!a->len || !memcmp(a->data, b->data, a->len))); -} - -int rawobj_dup(rawobj_t *dest, rawobj_t *src) -{ - LASSERT(src && dest); - - dest->len = src->len; - if (dest->len) { - OBD_ALLOC_LARGE(dest->data, dest->len); - if (!dest->data) { - dest->len = 0; - return -ENOMEM; - } - memcpy(dest->data, src->data, dest->len); - } else - dest->data = NULL; - return 0; -} - -int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen) -{ - __u32 len; - - LASSERT(obj); - LASSERT(buf); - LASSERT(buflen); - - len = cfs_size_round4(obj->len); - - if (*buflen < 4 + len) { - CERROR("buflen %u < %u\n", *buflen, 4 + len); - return -EINVAL; - } - - *(*buf)++ = cpu_to_le32(obj->len); - memcpy(*buf, obj->data, obj->len); - *buf += (len >> 2); - *buflen -= (4 + len); - - return 0; -} - -static int __rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen, - int alloc, int local) -{ - __u32 len; - - if (*buflen < sizeof(__u32)) { - CERROR("buflen %u\n", *buflen); - return -EINVAL; - } - - obj->len = *(*buf)++; - if (!local) - obj->len = le32_to_cpu(obj->len); - *buflen -= sizeof(__u32); - - if (!obj->len) { - obj->data = NULL; - return 0; - } - - len = local ? obj->len : cfs_size_round4(obj->len); - if (*buflen < len) { - CERROR("buflen %u < %u\n", *buflen, len); - obj->len = 0; - return -EINVAL; - } - - if (!alloc) - obj->data = (__u8 *) *buf; - else { - OBD_ALLOC_LARGE(obj->data, obj->len); - if (!obj->data) { - CERROR("fail to alloc %u bytes\n", obj->len); - obj->len = 0; - return -ENOMEM; - } - memcpy(obj->data, *buf, obj->len); - } - - *((char **)buf) += len; - *buflen -= len; - - return 0; -} - -int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen) -{ - return __rawobj_extract(obj, buf, buflen, 0, 0); -} - -int rawobj_extract_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen) -{ - return __rawobj_extract(obj, buf, buflen, 1, 0); -} - -int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen) -{ - return __rawobj_extract(obj, buf, buflen, 0, 1); -} - -int rawobj_extract_local_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen) -{ - return __rawobj_extract(obj, buf, buflen, 1, 1); -} - -int rawobj_from_netobj(rawobj_t *rawobj, netobj_t *netobj) -{ - rawobj->len = netobj->len; - rawobj->data = netobj->data; - return 0; -} - -int rawobj_from_netobj_alloc(rawobj_t *rawobj, netobj_t *netobj) -{ - rawobj->len = 0; - rawobj->data = NULL; - - if (netobj->len == 0) - return 0; - - OBD_ALLOC_LARGE(rawobj->data, netobj->len); - if (rawobj->data == NULL) - return -ENOMEM; - - rawobj->len = netobj->len; - memcpy(rawobj->data, netobj->data, netobj->len); - return 0; -} - -/**************************************** - * misc more * - ****************************************/ - -int buffer_extract_bytes(const void **buf, __u32 *buflen, - void *res, __u32 reslen) -{ - if (*buflen < reslen) { - CERROR("buflen %u < %u\n", *buflen, reslen); - return -EINVAL; - } - - memcpy(res, *buf, reslen); - *buf += reslen; - *buflen -= reslen; - return 0; -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c deleted file mode 100644 index 359c48ec2f5b..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2011, 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * Neil Brown <neilb@cse.unsw.edu.au> - * J. Bruce Fields <bfields@umich.edu> - * Andy Adamson <andros@umich.edu> - * Dug Song <dugsong@monkey.org> - * - * RPCSEC_GSS server authentication. - * This implements RPCSEC_GSS as defined in rfc2203 (rpcsec_gss) and rfc2078 - * (gssapi) - * - * The RPCSEC_GSS involves three stages: - * 1/ context creation - * 2/ data exchange - * 3/ context destruction - * - * Context creation is handled largely by upcalls to user-space. - * In particular, GSS_Accept_sec_context is handled by an upcall - * Data exchange is handled entirely within the kernel - * In particular, GSS_GetMIC, GSS_VerifyMIC, GSS_Seal, GSS_Unseal are in-kernel. - * Context destruction is handled in-kernel - * GSS_Delete_sec_context is in-kernel - * - * Context creation is initiated by a RPCSEC_GSS_INIT request arriving. - * The context handle and gss_token are used as a key into the rpcsec_init cache. - * The content of this cache includes some of the outputs of GSS_Accept_sec_context, - * being major_status, minor_status, context_handle, reply_token. - * These are sent back to the client. - * Sequence window management is handled by the kernel. The window size if currently - * a compile time constant. - * - * When user-space is happy that a context is established, it places an entry - * in the rpcsec_context cache. The key for this cache is the context_handle. - * The content includes: - * uid/gidlist - for determining access rights - * mechanism type - * mechanism specific information, such as a key - * - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/types.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/hash.h> -#include <linux/mutex.h> -#include <linux/sunrpc/cache.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -#define GSS_SVC_UPCALL_TIMEOUT (20) - -static spinlock_t __ctx_index_lock; -static __u64 __ctx_index; - -__u64 gss_get_next_ctx_index(void) -{ - __u64 idx; - - spin_lock(&__ctx_index_lock); - idx = __ctx_index++; - spin_unlock(&__ctx_index_lock); - - return idx; -} - -static inline unsigned long hash_mem(char *buf, int length, int bits) -{ - unsigned long hash = 0; - unsigned long l = 0; - int len = 0; - unsigned char c; - - do { - if (len == length) { - c = (char) len; - len = -1; - } else - c = *buf++; - - l = (l << 8) | c; - len++; - - if ((len & (BITS_PER_LONG/8-1)) == 0) - hash = hash_long(hash^l, BITS_PER_LONG); - } while (len); - - return hash >> (BITS_PER_LONG - bits); -} - -/**************************************** - * rsi cache * - ****************************************/ - -#define RSI_HASHBITS (6) -#define RSI_HASHMAX (1 << RSI_HASHBITS) -#define RSI_HASHMASK (RSI_HASHMAX - 1) - -struct rsi { - struct cache_head h; - __u32 lustre_svc; - __u64 nid; - wait_queue_head_t waitq; - rawobj_t in_handle, in_token; - rawobj_t out_handle, out_token; - int major_status, minor_status; -}; - -static struct cache_head *rsi_table[RSI_HASHMAX]; -static struct cache_detail rsi_cache; -static struct rsi *rsi_update(struct rsi *new, struct rsi *old); -static struct rsi *rsi_lookup(struct rsi *item); - -static inline int rsi_hash(struct rsi *item) -{ - return hash_mem((char *)item->in_handle.data, item->in_handle.len, - RSI_HASHBITS) ^ - hash_mem((char *)item->in_token.data, item->in_token.len, - RSI_HASHBITS); -} - -static inline int __rsi_match(struct rsi *item, struct rsi *tmp) -{ - return (rawobj_equal(&item->in_handle, &tmp->in_handle) && - rawobj_equal(&item->in_token, &tmp->in_token)); -} - -static void rsi_free(struct rsi *rsi) -{ - rawobj_free(&rsi->in_handle); - rawobj_free(&rsi->in_token); - rawobj_free(&rsi->out_handle); - rawobj_free(&rsi->out_token); -} - -static void rsi_request(struct cache_detail *cd, - struct cache_head *h, - char **bpp, int *blen) -{ - struct rsi *rsi = container_of(h, struct rsi, h); - __u64 index = 0; - - /* if in_handle is null, provide kernel suggestion */ - if (rsi->in_handle.len == 0) - index = gss_get_next_ctx_index(); - - qword_addhex(bpp, blen, (char *) &rsi->lustre_svc, - sizeof(rsi->lustre_svc)); - qword_addhex(bpp, blen, (char *) &rsi->nid, sizeof(rsi->nid)); - qword_addhex(bpp, blen, (char *) &index, sizeof(index)); - qword_addhex(bpp, blen, rsi->in_handle.data, rsi->in_handle.len); - qword_addhex(bpp, blen, rsi->in_token.data, rsi->in_token.len); - (*bpp)[-1] = '\n'; -} - -static int rsi_upcall(struct cache_detail *cd, struct cache_head *h) -{ - return sunrpc_cache_pipe_upcall(cd, h, rsi_request); -} - -static inline void __rsi_init(struct rsi *new, struct rsi *item) -{ - new->out_handle = RAWOBJ_EMPTY; - new->out_token = RAWOBJ_EMPTY; - - new->in_handle = item->in_handle; - item->in_handle = RAWOBJ_EMPTY; - new->in_token = item->in_token; - item->in_token = RAWOBJ_EMPTY; - - new->lustre_svc = item->lustre_svc; - new->nid = item->nid; - init_waitqueue_head(&new->waitq); -} - -static inline void __rsi_update(struct rsi *new, struct rsi *item) -{ - LASSERT(new->out_handle.len == 0); - LASSERT(new->out_token.len == 0); - - new->out_handle = item->out_handle; - item->out_handle = RAWOBJ_EMPTY; - new->out_token = item->out_token; - item->out_token = RAWOBJ_EMPTY; - - new->major_status = item->major_status; - new->minor_status = item->minor_status; -} - -static void rsi_put(struct kref *ref) -{ - struct rsi *rsi = container_of(ref, struct rsi, h.ref); - - LASSERT(rsi->h.next == NULL); - rsi_free(rsi); - OBD_FREE_PTR(rsi); -} - -static int rsi_match(struct cache_head *a, struct cache_head *b) -{ - struct rsi *item = container_of(a, struct rsi, h); - struct rsi *tmp = container_of(b, struct rsi, h); - - return __rsi_match(item, tmp); -} - -static void rsi_init(struct cache_head *cnew, struct cache_head *citem) -{ - struct rsi *new = container_of(cnew, struct rsi, h); - struct rsi *item = container_of(citem, struct rsi, h); - - __rsi_init(new, item); -} - -static void update_rsi(struct cache_head *cnew, struct cache_head *citem) -{ - struct rsi *new = container_of(cnew, struct rsi, h); - struct rsi *item = container_of(citem, struct rsi, h); - - __rsi_update(new, item); -} - -static struct cache_head *rsi_alloc(void) -{ - struct rsi *rsi; - - OBD_ALLOC_PTR(rsi); - if (rsi) - return &rsi->h; - else - return NULL; -} - -static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen) -{ - char *buf = mesg; - char *ep; - int len; - struct rsi rsii, *rsip = NULL; - time_t expiry; - int status = -EINVAL; - - memset(&rsii, 0, sizeof(rsii)); - - /* handle */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - if (rawobj_alloc(&rsii.in_handle, buf, len)) { - status = -ENOMEM; - goto out; - } - - /* token */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - if (rawobj_alloc(&rsii.in_token, buf, len)) { - status = -ENOMEM; - goto out; - } - - rsip = rsi_lookup(&rsii); - if (!rsip) - goto out; - - rsii.h.flags = 0; - /* expiry */ - expiry = get_expiry(&mesg); - if (expiry == 0) - goto out; - - len = qword_get(&mesg, buf, mlen); - if (len <= 0) - goto out; - - /* major */ - rsii.major_status = simple_strtol(buf, &ep, 10); - if (*ep) - goto out; - - /* minor */ - len = qword_get(&mesg, buf, mlen); - if (len <= 0) - goto out; - rsii.minor_status = simple_strtol(buf, &ep, 10); - if (*ep) - goto out; - - /* out_handle */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - if (rawobj_alloc(&rsii.out_handle, buf, len)) { - status = -ENOMEM; - goto out; - } - - /* out_token */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - if (rawobj_alloc(&rsii.out_token, buf, len)) { - status = -ENOMEM; - goto out; - } - - rsii.h.expiry_time = expiry; - rsip = rsi_update(&rsii, rsip); - status = 0; -out: - rsi_free(&rsii); - if (rsip) { - wake_up_all(&rsip->waitq); - cache_put(&rsip->h, &rsi_cache); - } else { - status = -ENOMEM; - } - - if (status) - CERROR("rsi parse error %d\n", status); - return status; -} - -static struct cache_detail rsi_cache = { - .hash_size = RSI_HASHMAX, - .hash_table = rsi_table, - .name = "auth.sptlrpc.init", - .cache_put = rsi_put, - .cache_upcall = rsi_upcall, - .cache_parse = rsi_parse, - .match = rsi_match, - .init = rsi_init, - .update = update_rsi, - .alloc = rsi_alloc, -}; - -static struct rsi *rsi_lookup(struct rsi *item) -{ - struct cache_head *ch; - int hash = rsi_hash(item); - - ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); - if (ch) - return container_of(ch, struct rsi, h); - else - return NULL; -} - -static struct rsi *rsi_update(struct rsi *new, struct rsi *old) -{ - struct cache_head *ch; - int hash = rsi_hash(new); - - ch = sunrpc_cache_update(&rsi_cache, &new->h, &old->h, hash); - if (ch) - return container_of(ch, struct rsi, h); - else - return NULL; -} - -/**************************************** - * rsc cache * - ****************************************/ - -#define RSC_HASHBITS (10) -#define RSC_HASHMAX (1 << RSC_HASHBITS) -#define RSC_HASHMASK (RSC_HASHMAX - 1) - -struct rsc { - struct cache_head h; - struct obd_device *target; - rawobj_t handle; - struct gss_svc_ctx ctx; -}; - -static struct cache_head *rsc_table[RSC_HASHMAX]; -static struct cache_detail rsc_cache; -static struct rsc *rsc_update(struct rsc *new, struct rsc *old); -static struct rsc *rsc_lookup(struct rsc *item); - -static void rsc_free(struct rsc *rsci) -{ - rawobj_free(&rsci->handle); - rawobj_free(&rsci->ctx.gsc_rvs_hdl); - lgss_delete_sec_context(&rsci->ctx.gsc_mechctx); -} - -static inline int rsc_hash(struct rsc *rsci) -{ - return hash_mem((char *)rsci->handle.data, - rsci->handle.len, RSC_HASHBITS); -} - -static inline int __rsc_match(struct rsc *new, struct rsc *tmp) -{ - return rawobj_equal(&new->handle, &tmp->handle); -} - -static inline void __rsc_init(struct rsc *new, struct rsc *tmp) -{ - new->handle = tmp->handle; - tmp->handle = RAWOBJ_EMPTY; - - new->target = NULL; - memset(&new->ctx, 0, sizeof(new->ctx)); - new->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY; -} - -static inline void __rsc_update(struct rsc *new, struct rsc *tmp) -{ - new->ctx = tmp->ctx; - tmp->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY; - tmp->ctx.gsc_mechctx = NULL; - - memset(&new->ctx.gsc_seqdata, 0, sizeof(new->ctx.gsc_seqdata)); - spin_lock_init(&new->ctx.gsc_seqdata.ssd_lock); -} - -static void rsc_put(struct kref *ref) -{ - struct rsc *rsci = container_of(ref, struct rsc, h.ref); - - LASSERT(rsci->h.next == NULL); - rsc_free(rsci); - OBD_FREE_PTR(rsci); -} - -static int rsc_match(struct cache_head *a, struct cache_head *b) -{ - struct rsc *new = container_of(a, struct rsc, h); - struct rsc *tmp = container_of(b, struct rsc, h); - - return __rsc_match(new, tmp); -} - -static void rsc_init(struct cache_head *cnew, struct cache_head *ctmp) -{ - struct rsc *new = container_of(cnew, struct rsc, h); - struct rsc *tmp = container_of(ctmp, struct rsc, h); - - __rsc_init(new, tmp); -} - -static void update_rsc(struct cache_head *cnew, struct cache_head *ctmp) -{ - struct rsc *new = container_of(cnew, struct rsc, h); - struct rsc *tmp = container_of(ctmp, struct rsc, h); - - __rsc_update(new, tmp); -} - -static struct cache_head * rsc_alloc(void) -{ - struct rsc *rsc; - - OBD_ALLOC_PTR(rsc); - if (rsc) - return &rsc->h; - else - return NULL; -} - -static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen) -{ - char *buf = mesg; - int len, rv, tmp_int; - struct rsc rsci, *rscp = NULL; - time_t expiry; - int status = -EINVAL; - struct gss_api_mech *gm = NULL; - - memset(&rsci, 0, sizeof(rsci)); - - /* context handle */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) goto out; - status = -ENOMEM; - if (rawobj_alloc(&rsci.handle, buf, len)) - goto out; - - rsci.h.flags = 0; - /* expiry */ - expiry = get_expiry(&mesg); - status = -EINVAL; - if (expiry == 0) - goto out; - - /* remote flag */ - rv = get_int(&mesg, &tmp_int); - if (rv) { - CERROR("fail to get remote flag\n"); - goto out; - } - rsci.ctx.gsc_remote = (tmp_int != 0); - - /* root user flag */ - rv = get_int(&mesg, &tmp_int); - if (rv) { - CERROR("fail to get oss user flag\n"); - goto out; - } - rsci.ctx.gsc_usr_root = (tmp_int != 0); - - /* mds user flag */ - rv = get_int(&mesg, &tmp_int); - if (rv) { - CERROR("fail to get mds user flag\n"); - goto out; - } - rsci.ctx.gsc_usr_mds = (tmp_int != 0); - - /* oss user flag */ - rv = get_int(&mesg, &tmp_int); - if (rv) { - CERROR("fail to get oss user flag\n"); - goto out; - } - rsci.ctx.gsc_usr_oss = (tmp_int != 0); - - /* mapped uid */ - rv = get_int(&mesg, (int *) &rsci.ctx.gsc_mapped_uid); - if (rv) { - CERROR("fail to get mapped uid\n"); - goto out; - } - - rscp = rsc_lookup(&rsci); - if (!rscp) - goto out; - - /* uid, or NEGATIVE */ - rv = get_int(&mesg, (int *) &rsci.ctx.gsc_uid); - if (rv == -EINVAL) - goto out; - if (rv == -ENOENT) { - CERROR("NOENT? set rsc entry negative\n"); - set_bit(CACHE_NEGATIVE, &rsci.h.flags); - } else { - rawobj_t tmp_buf; - unsigned long ctx_expiry; - - /* gid */ - if (get_int(&mesg, (int *) &rsci.ctx.gsc_gid)) - goto out; - - /* mech name */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - gm = lgss_name_to_mech(buf); - status = -EOPNOTSUPP; - if (!gm) - goto out; - - status = -EINVAL; - /* mech-specific data: */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - - tmp_buf.len = len; - tmp_buf.data = (unsigned char *)buf; - if (lgss_import_sec_context(&tmp_buf, gm, - &rsci.ctx.gsc_mechctx)) - goto out; - - /* currently the expiry time passed down from user-space - * is invalid, here we retrieve it from mech. */ - if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) { - CERROR("unable to get expire time, drop it\n"); - goto out; - } - expiry = (time_t) ctx_expiry; - } - - rsci.h.expiry_time = expiry; - rscp = rsc_update(&rsci, rscp); - status = 0; -out: - if (gm) - lgss_mech_put(gm); - rsc_free(&rsci); - if (rscp) - cache_put(&rscp->h, &rsc_cache); - else - status = -ENOMEM; - - if (status) - CERROR("parse rsc error %d\n", status); - return status; -} - -static struct cache_detail rsc_cache = { - .hash_size = RSC_HASHMAX, - .hash_table = rsc_table, - .name = "auth.sptlrpc.context", - .cache_put = rsc_put, - .cache_parse = rsc_parse, - .match = rsc_match, - .init = rsc_init, - .update = update_rsc, - .alloc = rsc_alloc, -}; - -static struct rsc *rsc_lookup(struct rsc *item) -{ - struct cache_head *ch; - int hash = rsc_hash(item); - - ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); - if (ch) - return container_of(ch, struct rsc, h); - else - return NULL; -} - -static struct rsc *rsc_update(struct rsc *new, struct rsc *old) -{ - struct cache_head *ch; - int hash = rsc_hash(new); - - ch = sunrpc_cache_update(&rsc_cache, &new->h, &old->h, hash); - if (ch) - return container_of(ch, struct rsc, h); - else - return NULL; -} - -#define COMPAT_RSC_PUT(item, cd) cache_put((item), (cd)) - -/**************************************** - * rsc cache flush * - ****************************************/ - -typedef int rsc_entry_match(struct rsc *rscp, long data); - -static void rsc_flush(rsc_entry_match *match, long data) -{ - struct cache_head **ch; - struct rsc *rscp; - int n; - - write_lock(&rsc_cache.hash_lock); - for (n = 0; n < RSC_HASHMAX; n++) { - for (ch = &rsc_cache.hash_table[n]; *ch;) { - rscp = container_of(*ch, struct rsc, h); - - if (!match(rscp, data)) { - ch = &((*ch)->next); - continue; - } - - /* it seems simply set NEGATIVE doesn't work */ - *ch = (*ch)->next; - rscp->h.next = NULL; - cache_get(&rscp->h); - set_bit(CACHE_NEGATIVE, &rscp->h.flags); - COMPAT_RSC_PUT(&rscp->h, &rsc_cache); - rsc_cache.entries--; - } - } - write_unlock(&rsc_cache.hash_lock); -} - -static int match_uid(struct rsc *rscp, long uid) -{ - if ((int) uid == -1) - return 1; - return ((int) rscp->ctx.gsc_uid == (int) uid); -} - -static int match_target(struct rsc *rscp, long target) -{ - return (rscp->target == (struct obd_device *) target); -} - -static inline void rsc_flush_uid(int uid) -{ - if (uid == -1) - CWARN("flush all gss contexts...\n"); - - rsc_flush(match_uid, (long) uid); -} - -static inline void rsc_flush_target(struct obd_device *target) -{ - rsc_flush(match_target, (long) target); -} - -void gss_secsvc_flush(struct obd_device *target) -{ - rsc_flush_target(target); -} -EXPORT_SYMBOL(gss_secsvc_flush); - -static struct rsc *gss_svc_searchbyctx(rawobj_t *handle) -{ - struct rsc rsci; - struct rsc *found; - - memset(&rsci, 0, sizeof(rsci)); - if (rawobj_dup(&rsci.handle, handle)) - return NULL; - - found = rsc_lookup(&rsci); - rsc_free(&rsci); - if (!found) - return NULL; - if (cache_check(&rsc_cache, &found->h, NULL)) - return NULL; - return found; -} - -int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, - struct gss_sec *gsec, - struct gss_cli_ctx *gctx) -{ - struct rsc rsci, *rscp = NULL; - unsigned long ctx_expiry; - __u32 major; - int rc; - - memset(&rsci, 0, sizeof(rsci)); - - if (rawobj_alloc(&rsci.handle, (char *) &gsec->gs_rvs_hdl, - sizeof(gsec->gs_rvs_hdl))) - GOTO(out, rc = -ENOMEM); - - rscp = rsc_lookup(&rsci); - if (rscp == NULL) - GOTO(out, rc = -ENOMEM); - - major = lgss_copy_reverse_context(gctx->gc_mechctx, - &rsci.ctx.gsc_mechctx); - if (major != GSS_S_COMPLETE) - GOTO(out, rc = -ENOMEM); - - if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) { - CERROR("unable to get expire time, drop it\n"); - GOTO(out, rc = -EINVAL); - } - rsci.h.expiry_time = (time_t) ctx_expiry; - - if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0) - rsci.ctx.gsc_usr_mds = 1; - else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0) - rsci.ctx.gsc_usr_oss = 1; - else - rsci.ctx.gsc_usr_root = 1; - - rscp = rsc_update(&rsci, rscp); - if (rscp == NULL) - GOTO(out, rc = -ENOMEM); - - rscp->target = imp->imp_obd; - rawobj_dup(&gctx->gc_svc_handle, &rscp->handle); - - CWARN("create reverse svc ctx %p to %s: idx "LPX64"\n", - &rscp->ctx, obd2cli_tgt(imp->imp_obd), gsec->gs_rvs_hdl); - rc = 0; -out: - if (rscp) - cache_put(&rscp->h, &rsc_cache); - rsc_free(&rsci); - - if (rc) - CERROR("create reverse svc ctx: idx "LPX64", rc %d\n", - gsec->gs_rvs_hdl, rc); - return rc; -} - -int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle) -{ - const cfs_time_t expire = 20; - struct rsc *rscp; - - rscp = gss_svc_searchbyctx(handle); - if (rscp) { - CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n", - &rscp->ctx, rscp); - - rscp->h.expiry_time = cfs_time_current_sec() + expire; - COMPAT_RSC_PUT(&rscp->h, &rsc_cache); - } - return 0; -} - -int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx) -{ - struct rsc *rscp = container_of(ctx, struct rsc, ctx); - - return rawobj_dup(handle, &rscp->handle); -} - -int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq) -{ - struct rsc *rscp; - - rscp = gss_svc_searchbyctx(handle); - if (rscp) { - CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n", - &rscp->ctx, rscp, seq + 1); - - rscp->ctx.gsc_rvs_seq = seq + 1; - COMPAT_RSC_PUT(&rscp->h, &rsc_cache); - } - return 0; -} - -static struct cache_deferred_req* cache_upcall_defer(struct cache_req *req) -{ - return NULL; -} -static struct cache_req cache_upcall_chandle = { cache_upcall_defer }; - -int gss_svc_upcall_handle_init(struct ptlrpc_request *req, - struct gss_svc_reqctx *grctx, - struct gss_wire_ctx *gw, - struct obd_device *target, - __u32 lustre_svc, - rawobj_t *rvs_hdl, - rawobj_t *in_token) -{ - struct ptlrpc_reply_state *rs; - struct rsc *rsci = NULL; - struct rsi *rsip = NULL, rsikey; - wait_queue_t wait; - int replen = sizeof(struct ptlrpc_body); - struct gss_rep_header *rephdr; - int first_check = 1; - int rc = SECSVC_DROP; - - memset(&rsikey, 0, sizeof(rsikey)); - rsikey.lustre_svc = lustre_svc; - rsikey.nid = (__u64) req->rq_peer.nid; - - /* duplicate context handle. for INIT it always 0 */ - if (rawobj_dup(&rsikey.in_handle, &gw->gw_handle)) { - CERROR("fail to dup context handle\n"); - GOTO(out, rc); - } - - if (rawobj_dup(&rsikey.in_token, in_token)) { - CERROR("can't duplicate token\n"); - rawobj_free(&rsikey.in_handle); - GOTO(out, rc); - } - - rsip = rsi_lookup(&rsikey); - rsi_free(&rsikey); - if (!rsip) { - CERROR("error in rsi_lookup.\n"); - - if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0)) - rc = SECSVC_COMPLETE; - - GOTO(out, rc); - } - - cache_get(&rsip->h); /* take an extra ref */ - init_waitqueue_head(&rsip->waitq); - init_waitqueue_entry(&wait, current); - add_wait_queue(&rsip->waitq, &wait); - -cache_check: - /* Note each time cache_check() will drop a reference if return - * non-zero. We hold an extra reference on initial rsip, but must - * take care of following calls. */ - rc = cache_check(&rsi_cache, &rsip->h, &cache_upcall_chandle); - switch (rc) { - case -EAGAIN: { - int valid; - - if (first_check) { - first_check = 0; - - read_lock(&rsi_cache.hash_lock); - valid = test_bit(CACHE_VALID, &rsip->h.flags); - if (valid == 0) - set_current_state(TASK_INTERRUPTIBLE); - read_unlock(&rsi_cache.hash_lock); - - if (valid == 0) - schedule_timeout(GSS_SVC_UPCALL_TIMEOUT * - HZ); - - cache_get(&rsip->h); - goto cache_check; - } - CWARN("waited %ds timeout, drop\n", GSS_SVC_UPCALL_TIMEOUT); - break; - } - case -ENOENT: - CWARN("cache_check return ENOENT, drop\n"); - break; - case 0: - /* if not the first check, we have to release the extra - * reference we just added on it. */ - if (!first_check) - cache_put(&rsip->h, &rsi_cache); - CDEBUG(D_SEC, "cache_check is good\n"); - break; - } - - remove_wait_queue(&rsip->waitq, &wait); - cache_put(&rsip->h, &rsi_cache); - - if (rc) - GOTO(out, rc = SECSVC_DROP); - - rc = SECSVC_DROP; - rsci = gss_svc_searchbyctx(&rsip->out_handle); - if (!rsci) { - CERROR("authentication failed\n"); - - if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0)) - rc = SECSVC_COMPLETE; - - GOTO(out, rc); - } else { - cache_get(&rsci->h); - grctx->src_ctx = &rsci->ctx; - } - - if (rawobj_dup(&rsci->ctx.gsc_rvs_hdl, rvs_hdl)) { - CERROR("failed duplicate reverse handle\n"); - GOTO(out, rc); - } - - rsci->target = target; - - CDEBUG(D_SEC, "server create rsc %p(%u->%s)\n", - rsci, rsci->ctx.gsc_uid, libcfs_nid2str(req->rq_peer.nid)); - - if (rsip->out_handle.len > PTLRPC_GSS_MAX_HANDLE_SIZE) { - CERROR("handle size %u too large\n", rsip->out_handle.len); - GOTO(out, rc = SECSVC_DROP); - } - - grctx->src_init = 1; - grctx->src_reserve_len = cfs_size_round4(rsip->out_token.len); - - rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0); - if (rc) { - CERROR("failed to pack reply: %d\n", rc); - GOTO(out, rc = SECSVC_DROP); - } - - rs = req->rq_reply_state; - LASSERT(rs->rs_repbuf->lm_bufcount == 3); - LASSERT(rs->rs_repbuf->lm_buflens[0] >= - sizeof(*rephdr) + rsip->out_handle.len); - LASSERT(rs->rs_repbuf->lm_buflens[2] >= rsip->out_token.len); - - rephdr = lustre_msg_buf(rs->rs_repbuf, 0, 0); - rephdr->gh_version = PTLRPC_GSS_VERSION; - rephdr->gh_flags = 0; - rephdr->gh_proc = PTLRPC_GSS_PROC_ERR; - rephdr->gh_major = rsip->major_status; - rephdr->gh_minor = rsip->minor_status; - rephdr->gh_seqwin = GSS_SEQ_WIN; - rephdr->gh_handle.len = rsip->out_handle.len; - memcpy(rephdr->gh_handle.data, rsip->out_handle.data, - rsip->out_handle.len); - - memcpy(lustre_msg_buf(rs->rs_repbuf, 2, 0), rsip->out_token.data, - rsip->out_token.len); - - rs->rs_repdata_len = lustre_shrink_msg(rs->rs_repbuf, 2, - rsip->out_token.len, 0); - - rc = SECSVC_OK; - -out: - /* it looks like here we should put rsip also, but this mess up - * with NFS cache mgmt code... FIXME */ -#if 0 - if (rsip) - rsi_put(&rsip->h, &rsi_cache); -#endif - - if (rsci) { - /* if anything went wrong, we don't keep the context too */ - if (rc != SECSVC_OK) - set_bit(CACHE_NEGATIVE, &rsci->h.flags); - else - CDEBUG(D_SEC, "create rsc with idx "LPX64"\n", - gss_handle_to_u64(&rsci->handle)); - - COMPAT_RSC_PUT(&rsci->h, &rsc_cache); - } - return rc; -} - -struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req, - struct gss_wire_ctx *gw) -{ - struct rsc *rsc; - - rsc = gss_svc_searchbyctx(&gw->gw_handle); - if (!rsc) { - CWARN("Invalid gss ctx idx "LPX64" from %s\n", - gss_handle_to_u64(&gw->gw_handle), - libcfs_nid2str(req->rq_peer.nid)); - return NULL; - } - - return &rsc->ctx; -} - -void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx) -{ - struct rsc *rsc = container_of(ctx, struct rsc, ctx); - - COMPAT_RSC_PUT(&rsc->h, &rsc_cache); -} - -void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx) -{ - struct rsc *rsc = container_of(ctx, struct rsc, ctx); - - /* can't be found */ - set_bit(CACHE_NEGATIVE, &rsc->h.flags); - /* to be removed at next scan */ - rsc->h.expiry_time = 1; -} - -int __init gss_init_svc_upcall(void) -{ - int i; - - spin_lock_init(&__ctx_index_lock); - /* - * this helps reducing context index confliction. after server reboot, - * conflicting request from clients might be filtered out by initial - * sequence number checking, thus no chance to sent error notification - * back to clients. - */ - cfs_get_random_bytes(&__ctx_index, sizeof(__ctx_index)); - - - cache_register(&rsi_cache); - cache_register(&rsc_cache); - - /* FIXME this looks stupid. we intend to give lsvcgssd a chance to open - * the init upcall channel, otherwise there's big chance that the first - * upcall issued before the channel be opened thus nfsv4 cache code will - * drop the request direclty, thus lead to unnecessary recovery time. - * here we wait at maximum 1.5 seconds. */ - for (i = 0; i < 6; i++) { - if (atomic_read(&rsi_cache.readers) > 0) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - LASSERT(HZ >= 4); - schedule_timeout(HZ / 4); - } - - if (atomic_read(&rsi_cache.readers) == 0) - CWARN("Init channel is not opened by lsvcgssd, following " - "request might be dropped until lsvcgssd is active\n"); - - return 0; -} - -void __exit gss_exit_svc_upcall(void) -{ - cache_purge(&rsi_cache); - cache_unregister(&rsi_cache); - - cache_purge(&rsc_cache); - cache_unregister(&rsc_cache); -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c deleted file mode 100644 index a0a74e5542ed..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/mutex.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lprocfs_status.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -static struct proc_dir_entry *gss_proc_root = NULL; -static struct proc_dir_entry *gss_proc_lk = NULL; - -/* - * statistic of "out-of-sequence-window" - */ -static struct { - spinlock_t oos_lock; - atomic_t oos_cli_count; /* client occurrence */ - int oos_cli_behind; /* client max seqs behind */ - atomic_t oos_svc_replay[3]; /* server replay detected */ - atomic_t oos_svc_pass[3]; /* server verified ok */ -} gss_stat_oos = { - .oos_cli_count = ATOMIC_INIT(0), - .oos_cli_behind = 0, - .oos_svc_replay = { ATOMIC_INIT(0), }, - .oos_svc_pass = { ATOMIC_INIT(0), }, -}; - -void gss_stat_oos_record_cli(int behind) -{ - atomic_inc(&gss_stat_oos.oos_cli_count); - - spin_lock(&gss_stat_oos.oos_lock); - if (behind > gss_stat_oos.oos_cli_behind) - gss_stat_oos.oos_cli_behind = behind; - spin_unlock(&gss_stat_oos.oos_lock); -} - -void gss_stat_oos_record_svc(int phase, int replay) -{ - LASSERT(phase >= 0 && phase <= 2); - - if (replay) - atomic_inc(&gss_stat_oos.oos_svc_replay[phase]); - else - atomic_inc(&gss_stat_oos.oos_svc_pass[phase]); -} - -static int gss_proc_oos_seq_show(struct seq_file *m, void *v) -{ - return seq_printf(m, - "seqwin: %u\n" - "backwin: %u\n" - "client fall behind seqwin\n" - " occurrence: %d\n" - " max seq behind: %d\n" - "server replay detected:\n" - " phase 0: %d\n" - " phase 1: %d\n" - " phase 2: %d\n" - "server verify ok:\n" - " phase 2: %d\n", - GSS_SEQ_WIN_MAIN, - GSS_SEQ_WIN_BACK, - atomic_read(&gss_stat_oos.oos_cli_count), - gss_stat_oos.oos_cli_behind, - atomic_read(&gss_stat_oos.oos_svc_replay[0]), - atomic_read(&gss_stat_oos.oos_svc_replay[1]), - atomic_read(&gss_stat_oos.oos_svc_replay[2]), - atomic_read(&gss_stat_oos.oos_svc_pass[2])); -} -LPROC_SEQ_FOPS_RO(gss_proc_oos); - -static int gss_proc_write_secinit(struct file *file, const char *buffer, - size_t count, off_t *off) -{ - int rc; - - rc = gss_do_ctx_init_rpc((char *) buffer, count); - if (rc) { - LASSERT(rc < 0); - return rc; - } - - return count; -} - -static const struct file_operations gss_proc_secinit = { - .write = gss_proc_write_secinit, -}; - -static struct lprocfs_vars gss_lprocfs_vars[] = { - { "replays", &gss_proc_oos_fops }, - { "init_channel", &gss_proc_secinit, NULL, 0222 }, - { NULL } -}; - -/* - * for userspace helper lgss_keyring. - * - * debug_level: [0, 4], defined in utils/gss/lgss_utils.h - */ -static int gss_lk_debug_level = 1; - -static int gss_lk_proc_dl_seq_show(struct seq_file *m, void *v) -{ - return seq_printf(m, "%u\n", gss_lk_debug_level); -} - -static int gss_lk_proc_dl_seq_write(struct file *file, const char *buffer, - size_t count, off_t *off) -{ - int val, rc; - - rc = lprocfs_write_helper(buffer, count, &val); - if (rc < 0) - return rc; - - if (val < 0 || val > 4) - return -ERANGE; - - gss_lk_debug_level = val; - return count; -} -LPROC_SEQ_FOPS(gss_lk_proc_dl); - -static struct lprocfs_vars gss_lk_lprocfs_vars[] = { - { "debug_level", &gss_lk_proc_dl_fops }, - { NULL } -}; - -void gss_exit_lproc(void) -{ - if (gss_proc_lk) { - lprocfs_remove(&gss_proc_lk); - gss_proc_lk = NULL; - } - - if (gss_proc_root) { - lprocfs_remove(&gss_proc_root); - gss_proc_root = NULL; - } -} - -int gss_init_lproc(void) -{ - int rc; - - spin_lock_init(&gss_stat_oos.oos_lock); - - gss_proc_root = lprocfs_register("gss", sptlrpc_proc_root, - gss_lprocfs_vars, NULL); - if (IS_ERR(gss_proc_root)) { - rc = PTR_ERR(gss_proc_root); - gss_proc_root = NULL; - GOTO(err_out, rc); - } - - gss_proc_lk = lprocfs_register("lgss_keyring", gss_proc_root, - gss_lk_lprocfs_vars, NULL); - if (IS_ERR(gss_proc_lk)) { - rc = PTR_ERR(gss_proc_lk); - gss_proc_lk = NULL; - GOTO(err_out, rc); - } - - return 0; - -err_out: - CERROR("failed to initialize gss lproc entries: %d\n", rc); - gss_exit_lproc(); - return rc; -} diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c deleted file mode 100644 index 383601cdd4e6..000000000000 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c +++ /dev/null @@ -1,2889 +0,0 @@ -/* - * Modifications for Lustre - * - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Copyright (c) 2011, 2012, Intel Corporation. - * - * Author: Eric Mei <ericm@clusterfs.com> - */ - -/* - * linux/net/sunrpc/auth_gss.c - * - * RPCSEC_GSS client authentication. - * - * Copyright (c) 2000 The Regents of the University of Michigan. - * All rights reserved. - * - * Dug Song <dugsong@monkey.org> - * Andy Adamson <andros@umich.edu> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#define DEBUG_SUBSYSTEM S_SEC -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/dcache.h> -#include <linux/fs.h> -#include <linux/mutex.h> -#include <asm/atomic.h> - -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <obd_cksum.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_sec.h> - -#include "gss_err.h" -#include "gss_internal.h" -#include "gss_api.h" - -#include <linux/crypto.h> -#include <linux/crc32.h> - -/* - * early reply have fixed size, respectively in privacy and integrity mode. - * so we calculate them only once. - */ -static int gss_at_reply_off_integ; -static int gss_at_reply_off_priv; - - -static inline int msg_last_segidx(struct lustre_msg *msg) -{ - LASSERT(msg->lm_bufcount > 0); - return msg->lm_bufcount - 1; -} -static inline int msg_last_seglen(struct lustre_msg *msg) -{ - return msg->lm_buflens[msg_last_segidx(msg)]; -} - -/******************************************** - * wire data swabber * - ********************************************/ - -static -void gss_header_swabber(struct gss_header *ghdr) -{ - __swab32s(&ghdr->gh_flags); - __swab32s(&ghdr->gh_proc); - __swab32s(&ghdr->gh_seq); - __swab32s(&ghdr->gh_svc); - __swab32s(&ghdr->gh_pad1); - __swab32s(&ghdr->gh_handle.len); -} - -struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment, - int swabbed) -{ - struct gss_header *ghdr; - - ghdr = lustre_msg_buf(msg, segment, sizeof(*ghdr)); - if (ghdr == NULL) - return NULL; - - if (swabbed) - gss_header_swabber(ghdr); - - if (sizeof(*ghdr) + ghdr->gh_handle.len > msg->lm_buflens[segment]) { - CERROR("gss header has length %d, now %u received\n", - (int) sizeof(*ghdr) + ghdr->gh_handle.len, - msg->lm_buflens[segment]); - return NULL; - } - - return ghdr; -} - -#if 0 -static -void gss_netobj_swabber(netobj_t *obj) -{ - __swab32s(&obj->len); -} - -netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment) -{ - netobj_t *obj; - - obj = lustre_swab_buf(msg, segment, sizeof(*obj), gss_netobj_swabber); - if (obj && sizeof(*obj) + obj->len > msg->lm_buflens[segment]) { - CERROR("netobj require length %u but only %u received\n", - (unsigned int) sizeof(*obj) + obj->len, - msg->lm_buflens[segment]); - return NULL; - } - - return obj; -} -#endif - -/* - * payload should be obtained from mechanism. but currently since we - * only support kerberos, we could simply use fixed value. - * krb5 "meta" data: - * - krb5 header: 16 - * - krb5 checksum: 20 - * - * for privacy mode, payload also include the cipher text which has the same - * size as plain text, plus possible confounder, padding both at maximum cipher - * block size. - */ -#define GSS_KRB5_INTEG_MAX_PAYLOAD (40) - -static inline -int gss_mech_payload(struct gss_ctx *mechctx, int msgsize, int privacy) -{ - if (privacy) - return GSS_KRB5_INTEG_MAX_PAYLOAD + 16 + 16 + 16 + msgsize; - else - return GSS_KRB5_INTEG_MAX_PAYLOAD; -} - -/* - * return signature size, otherwise < 0 to indicate error - */ -static int gss_sign_msg(struct lustre_msg *msg, - struct gss_ctx *mechctx, - enum lustre_sec_part sp, - __u32 flags, __u32 proc, __u32 seq, __u32 svc, - rawobj_t *handle) -{ - struct gss_header *ghdr; - rawobj_t text[4], mic; - int textcnt, max_textcnt, mic_idx; - __u32 major; - - LASSERT(msg->lm_bufcount >= 2); - - /* gss hdr */ - LASSERT(msg->lm_buflens[0] >= - sizeof(*ghdr) + (handle ? handle->len : 0)); - ghdr = lustre_msg_buf(msg, 0, 0); - - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_sp = (__u8) sp; - ghdr->gh_flags = flags; - ghdr->gh_proc = proc; - ghdr->gh_seq = seq; - ghdr->gh_svc = svc; - if (!handle) { - /* fill in a fake one */ - ghdr->gh_handle.len = 0; - } else { - ghdr->gh_handle.len = handle->len; - memcpy(ghdr->gh_handle.data, handle->data, handle->len); - } - - /* no actual signature for null mode */ - if (svc == SPTLRPC_SVC_NULL) - return lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens); - - /* MIC */ - mic_idx = msg_last_segidx(msg); - max_textcnt = (svc == SPTLRPC_SVC_AUTH) ? 1 : mic_idx; - - for (textcnt = 0; textcnt < max_textcnt; textcnt++) { - text[textcnt].len = msg->lm_buflens[textcnt]; - text[textcnt].data = lustre_msg_buf(msg, textcnt, 0); - } - - mic.len = msg->lm_buflens[mic_idx]; - mic.data = lustre_msg_buf(msg, mic_idx, 0); - - major = lgss_get_mic(mechctx, textcnt, text, 0, NULL, &mic); - if (major != GSS_S_COMPLETE) { - CERROR("fail to generate MIC: %08x\n", major); - return -EPERM; - } - LASSERT(mic.len <= msg->lm_buflens[mic_idx]); - - return lustre_shrink_msg(msg, mic_idx, mic.len, 0); -} - -/* - * return gss error - */ -static -__u32 gss_verify_msg(struct lustre_msg *msg, - struct gss_ctx *mechctx, - __u32 svc) -{ - rawobj_t text[4], mic; - int textcnt, max_textcnt; - int mic_idx; - __u32 major; - - LASSERT(msg->lm_bufcount >= 2); - - if (svc == SPTLRPC_SVC_NULL) - return GSS_S_COMPLETE; - - mic_idx = msg_last_segidx(msg); - max_textcnt = (svc == SPTLRPC_SVC_AUTH) ? 1 : mic_idx; - - for (textcnt = 0; textcnt < max_textcnt; textcnt++) { - text[textcnt].len = msg->lm_buflens[textcnt]; - text[textcnt].data = lustre_msg_buf(msg, textcnt, 0); - } - - mic.len = msg->lm_buflens[mic_idx]; - mic.data = lustre_msg_buf(msg, mic_idx, 0); - - major = lgss_verify_mic(mechctx, textcnt, text, 0, NULL, &mic); - if (major != GSS_S_COMPLETE) - CERROR("mic verify error: %08x\n", major); - - return major; -} - -/* - * return gss error code - */ -static -__u32 gss_unseal_msg(struct gss_ctx *mechctx, - struct lustre_msg *msgbuf, - int *msg_len, int msgbuf_len) -{ - rawobj_t clear_obj, hdrobj, token; - __u8 *clear_buf; - int clear_buflen; - __u32 major; - - if (msgbuf->lm_bufcount != 2) { - CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount); - return GSS_S_FAILURE; - } - - /* allocate a temporary clear text buffer, same sized as token, - * we assume the final clear text size <= token size */ - clear_buflen = lustre_msg_buflen(msgbuf, 1); - OBD_ALLOC_LARGE(clear_buf, clear_buflen); - if (!clear_buf) - return GSS_S_FAILURE; - - /* buffer objects */ - hdrobj.len = lustre_msg_buflen(msgbuf, 0); - hdrobj.data = lustre_msg_buf(msgbuf, 0, 0); - token.len = lustre_msg_buflen(msgbuf, 1); - token.data = lustre_msg_buf(msgbuf, 1, 0); - clear_obj.len = clear_buflen; - clear_obj.data = clear_buf; - - major = lgss_unwrap(mechctx, &hdrobj, &token, &clear_obj); - if (major != GSS_S_COMPLETE) { - CERROR("unwrap message error: %08x\n", major); - GOTO(out_free, major = GSS_S_FAILURE); - } - LASSERT(clear_obj.len <= clear_buflen); - LASSERT(clear_obj.len <= msgbuf_len); - - /* now the decrypted message */ - memcpy(msgbuf, clear_obj.data, clear_obj.len); - *msg_len = clear_obj.len; - - major = GSS_S_COMPLETE; -out_free: - OBD_FREE_LARGE(clear_buf, clear_buflen); - return major; -} - -/******************************************** - * gss client context manipulation helpers * - ********************************************/ - -int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx) -{ - LASSERT(atomic_read(&ctx->cc_refcount)); - - if (!test_and_set_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags)) { - if (!ctx->cc_early_expire) - clear_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags); - - CWARN("ctx %p(%u->%s) get expired: %lu(%+lds)\n", - ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), - ctx->cc_expire, - ctx->cc_expire == 0 ? 0 : - cfs_time_sub(ctx->cc_expire, cfs_time_current_sec())); - - sptlrpc_cli_ctx_wakeup(ctx); - return 1; - } - - return 0; -} - -/* - * return 1 if the context is dead. - */ -int cli_ctx_check_death(struct ptlrpc_cli_ctx *ctx) -{ - if (unlikely(cli_ctx_is_dead(ctx))) - return 1; - - /* expire is 0 means never expire. a newly created gss context - * which during upcall may has 0 expiration */ - if (ctx->cc_expire == 0) - return 0; - - /* check real expiration */ - if (cfs_time_after(ctx->cc_expire, cfs_time_current_sec())) - return 0; - - cli_ctx_expire(ctx); - return 1; -} - -void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx) -{ - struct ptlrpc_cli_ctx *ctx = &gctx->gc_base; - unsigned long ctx_expiry; - - if (lgss_inquire_context(gctx->gc_mechctx, &ctx_expiry)) { - CERROR("ctx %p(%u): unable to inquire, expire it now\n", - gctx, ctx->cc_vcred.vc_uid); - ctx_expiry = 1; /* make it expired now */ - } - - ctx->cc_expire = gss_round_ctx_expiry(ctx_expiry, - ctx->cc_sec->ps_flvr.sf_flags); - - /* At this point this ctx might have been marked as dead by - * someone else, in which case nobody will make further use - * of it. we don't care, and mark it UPTODATE will help - * destroying server side context when it be destroyed. */ - set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags); - - if (sec_is_reverse(ctx->cc_sec)) { - CWARN("server installed reverse ctx %p idx "LPX64", " - "expiry %lu(%+lds)\n", ctx, - gss_handle_to_u64(&gctx->gc_handle), - ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec()); - } else { - CWARN("client refreshed ctx %p idx "LPX64" (%u->%s), " - "expiry %lu(%+lds)\n", ctx, - gss_handle_to_u64(&gctx->gc_handle), - ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), - ctx->cc_expire, ctx->cc_expire - cfs_time_current_sec()); - - /* install reverse svc ctx for root context */ - if (ctx->cc_vcred.vc_uid == 0) - gss_sec_install_rctx(ctx->cc_sec->ps_import, - ctx->cc_sec, ctx); - } - - sptlrpc_cli_ctx_wakeup(ctx); -} - -static void gss_cli_ctx_finalize(struct gss_cli_ctx *gctx) -{ - LASSERT(gctx->gc_base.cc_sec); - - if (gctx->gc_mechctx) { - lgss_delete_sec_context(&gctx->gc_mechctx); - gctx->gc_mechctx = NULL; - } - - if (!rawobj_empty(&gctx->gc_svc_handle)) { - /* forward ctx: mark buddy reverse svcctx soon-expire. */ - if (!sec_is_reverse(gctx->gc_base.cc_sec) && - !rawobj_empty(&gctx->gc_svc_handle)) - gss_svc_upcall_expire_rvs_ctx(&gctx->gc_svc_handle); - - rawobj_free(&gctx->gc_svc_handle); - } - - rawobj_free(&gctx->gc_handle); -} - -/* - * Based on sequence number algorithm as specified in RFC 2203. - * - * modified for our own problem: arriving request has valid sequence number, - * but unwrapping request might cost a long time, after that its sequence - * are not valid anymore (fall behind the window). It rarely happen, mostly - * under extreme load. - * - * note we should not check sequence before verify the integrity of incoming - * request, because just one attacking request with high sequence number might - * cause all following request be dropped. - * - * so here we use a multi-phase approach: prepare 2 sequence windows, - * "main window" for normal sequence and "back window" for fall behind sequence. - * and 3-phase checking mechanism: - * 0 - before integrity verification, perform a initial sequence checking in - * main window, which only try and don't actually set any bits. if the - * sequence is high above the window or fit in the window and the bit - * is 0, then accept and proceed to integrity verification. otherwise - * reject this sequence. - * 1 - after integrity verification, check in main window again. if this - * sequence is high above the window or fit in the window and the bit - * is 0, then set the bit and accept; if it fit in the window but bit - * already set, then reject; if it fall behind the window, then proceed - * to phase 2. - * 2 - check in back window. if it is high above the window or fit in the - * window and the bit is 0, then set the bit and accept. otherwise reject. - * - * return value: - * 1: looks like a replay - * 0: is ok - * -1: is a replay - * - * note phase 0 is necessary, because otherwise replay attacking request of - * sequence which between the 2 windows can't be detected. - * - * this mechanism can't totally solve the problem, but could help much less - * number of valid requests be dropped. - */ -static -int gss_do_check_seq(unsigned long *window, __u32 win_size, __u32 *max_seq, - __u32 seq_num, int phase) -{ - LASSERT(phase >= 0 && phase <= 2); - - if (seq_num > *max_seq) { - /* - * 1. high above the window - */ - if (phase == 0) - return 0; - - if (seq_num >= *max_seq + win_size) { - memset(window, 0, win_size / 8); - *max_seq = seq_num; - } else { - while (*max_seq < seq_num) { - (*max_seq)++; - __clear_bit((*max_seq) % win_size, window); - } - } - __set_bit(seq_num % win_size, window); - } else if (seq_num + win_size <= *max_seq) { - /* - * 2. low behind the window - */ - if (phase == 0 || phase == 2) - goto replay; - - CWARN("seq %u is %u behind (size %d), check backup window\n", - seq_num, *max_seq - win_size - seq_num, win_size); - return 1; - } else { - /* - * 3. fit into the window - */ - switch (phase) { - case 0: - if (test_bit(seq_num % win_size, window)) - goto replay; - break; - case 1: - case 2: - if (__test_and_set_bit(seq_num % win_size, window)) - goto replay; - break; - } - } - - return 0; - -replay: - CERROR("seq %u (%s %s window) is a replay: max %u, winsize %d\n", - seq_num, - seq_num + win_size > *max_seq ? "in" : "behind", - phase == 2 ? "backup " : "main", - *max_seq, win_size); - return -1; -} - -/* - * Based on sequence number algorithm as specified in RFC 2203. - * - * if @set == 0: initial check, don't set any bit in window - * if @sec == 1: final check, set bit in window - */ -int gss_check_seq_num(struct gss_svc_seq_data *ssd, __u32 seq_num, int set) -{ - int rc = 0; - - spin_lock(&ssd->ssd_lock); - - if (set == 0) { - /* - * phase 0 testing - */ - rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN, - &ssd->ssd_max_main, seq_num, 0); - if (unlikely(rc)) - gss_stat_oos_record_svc(0, 1); - } else { - /* - * phase 1 checking main window - */ - rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN, - &ssd->ssd_max_main, seq_num, 1); - switch (rc) { - case -1: - gss_stat_oos_record_svc(1, 1); - /* fall through */ - case 0: - goto exit; - } - /* - * phase 2 checking back window - */ - rc = gss_do_check_seq(ssd->ssd_win_back, GSS_SEQ_WIN_BACK, - &ssd->ssd_max_back, seq_num, 2); - if (rc) - gss_stat_oos_record_svc(2, 1); - else - gss_stat_oos_record_svc(2, 0); - } -exit: - spin_unlock(&ssd->ssd_lock); - return rc; -} - -/*************************************** - * cred APIs * - ***************************************/ - -static inline int gss_cli_payload(struct ptlrpc_cli_ctx *ctx, - int msgsize, int privacy) -{ - return gss_mech_payload(NULL, msgsize, privacy); -} - -static int gss_cli_bulk_payload(struct ptlrpc_cli_ctx *ctx, - struct sptlrpc_flavor *flvr, - int reply, int read) -{ - int payload = sizeof(struct ptlrpc_bulk_sec_desc); - - LASSERT(SPTLRPC_FLVR_BULK_TYPE(flvr->sf_rpc) == SPTLRPC_BULK_DEFAULT); - - if ((!reply && !read) || (reply && read)) { - switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) { - case SPTLRPC_BULK_SVC_NULL: - break; - case SPTLRPC_BULK_SVC_INTG: - payload += gss_cli_payload(ctx, 0, 0); - break; - case SPTLRPC_BULK_SVC_PRIV: - payload += gss_cli_payload(ctx, 0, 1); - break; - case SPTLRPC_BULK_SVC_AUTH: - default: - LBUG(); - } - } - - return payload; -} - -int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred) -{ - return (ctx->cc_vcred.vc_uid == vcred->vc_uid); -} - -void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize) -{ - buf[0] = '\0'; - - if (flags & PTLRPC_CTX_NEW) - strncat(buf, "new,", bufsize); - if (flags & PTLRPC_CTX_UPTODATE) - strncat(buf, "uptodate,", bufsize); - if (flags & PTLRPC_CTX_DEAD) - strncat(buf, "dead,", bufsize); - if (flags & PTLRPC_CTX_ERROR) - strncat(buf, "error,", bufsize); - if (flags & PTLRPC_CTX_CACHED) - strncat(buf, "cached,", bufsize); - if (flags & PTLRPC_CTX_ETERNAL) - strncat(buf, "eternal,", bufsize); - if (buf[0] == '\0') - strncat(buf, "-,", bufsize); - - buf[strlen(buf) - 1] = '\0'; -} - -int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req) -{ - struct gss_cli_ctx *gctx = ctx2gctx(ctx); - __u32 flags = 0, seq, svc; - int rc; - - LASSERT(req->rq_reqbuf); - LASSERT(req->rq_reqbuf->lm_bufcount >= 2); - LASSERT(req->rq_cli_ctx == ctx); - - /* nothing to do for context negotiation RPCs */ - if (req->rq_ctx_init) - return 0; - - svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - if (req->rq_pack_bulk) - flags |= LUSTRE_GSS_PACK_BULK; - if (req->rq_pack_udesc) - flags |= LUSTRE_GSS_PACK_USER; - -redo: - seq = atomic_inc_return(&gctx->gc_seq); - - rc = gss_sign_msg(req->rq_reqbuf, gctx->gc_mechctx, - ctx->cc_sec->ps_part, - flags, gctx->gc_proc, seq, svc, - &gctx->gc_handle); - if (rc < 0) - return rc; - - /* gss_sign_msg() msg might take long time to finish, in which period - * more rpcs could be wrapped up and sent out. if we found too many - * of them we should repack this rpc, because sent it too late might - * lead to the sequence number fall behind the window on server and - * be dropped. also applies to gss_cli_ctx_seal(). - * - * Note: null mode doesn't check sequence number. */ - if (svc != SPTLRPC_SVC_NULL && - atomic_read(&gctx->gc_seq) - seq > GSS_SEQ_REPACK_THRESHOLD) { - int behind = atomic_read(&gctx->gc_seq) - seq; - - gss_stat_oos_record_cli(behind); - CWARN("req %p: %u behind, retry signing\n", req, behind); - goto redo; - } - - req->rq_reqdata_len = rc; - return 0; -} - -static -int gss_cli_ctx_handle_err_notify(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req, - struct gss_header *ghdr) -{ - struct gss_err_header *errhdr; - int rc; - - LASSERT(ghdr->gh_proc == PTLRPC_GSS_PROC_ERR); - - errhdr = (struct gss_err_header *) ghdr; - - CWARN("req x"LPU64"/t"LPU64", ctx %p idx "LPX64"(%u->%s): " - "%sserver respond (%08x/%08x)\n", - req->rq_xid, req->rq_transno, ctx, - gss_handle_to_u64(&ctx2gctx(ctx)->gc_handle), - ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec), - sec_is_reverse(ctx->cc_sec) ? "reverse" : "", - errhdr->gh_major, errhdr->gh_minor); - - /* context fini rpc, let it failed */ - if (req->rq_ctx_fini) { - CWARN("context fini rpc failed\n"); - return -EINVAL; - } - - /* reverse sec, just return error, don't expire this ctx because it's - * crucial to callback rpcs. note if the callback rpc failed because - * of bit flip during network transfer, the client will be evicted - * directly. so more gracefully we probably want let it retry for - * number of times. */ - if (sec_is_reverse(ctx->cc_sec)) - return -EINVAL; - - if (errhdr->gh_major != GSS_S_NO_CONTEXT && - errhdr->gh_major != GSS_S_BAD_SIG) - return -EACCES; - - /* server return NO_CONTEXT might be caused by context expire - * or server reboot/failover. we try to refresh a new ctx which - * be transparent to upper layer. - * - * In some cases, our gss handle is possible to be incidentally - * identical to another handle since the handle itself is not - * fully random. In krb5 case, the GSS_S_BAD_SIG will be - * returned, maybe other gss error for other mechanism. - * - * if we add new mechanism, make sure the correct error are - * returned in this case. */ - CWARN("%s: server might lost the context, retrying\n", - errhdr->gh_major == GSS_S_NO_CONTEXT ? "NO_CONTEXT" : "BAD_SIG"); - - sptlrpc_cli_ctx_expire(ctx); - - /* we need replace the ctx right here, otherwise during - * resent we'll hit the logic in sptlrpc_req_refresh_ctx() - * which keep the ctx with RESEND flag, thus we'll never - * get rid of this ctx. */ - rc = sptlrpc_req_replace_dead_ctx(req); - if (rc == 0) - req->rq_resend = 1; - - return rc; -} - -int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req) -{ - struct gss_cli_ctx *gctx; - struct gss_header *ghdr, *reqhdr; - struct lustre_msg *msg = req->rq_repdata; - __u32 major; - int pack_bulk, swabbed, rc = 0; - - LASSERT(req->rq_cli_ctx == ctx); - LASSERT(msg); - - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - - /* special case for context negotiation, rq_repmsg/rq_replen actually - * are not used currently. but early reply always be treated normally */ - if (req->rq_ctx_init && !req->rq_early) { - req->rq_repmsg = lustre_msg_buf(msg, 1, 0); - req->rq_replen = msg->lm_buflens[1]; - return 0; - } - - if (msg->lm_bufcount < 2 || msg->lm_bufcount > 4) { - CERROR("unexpected bufcount %u\n", msg->lm_bufcount); - return -EPROTO; - } - - swabbed = ptlrpc_rep_need_swab(req); - - ghdr = gss_swab_header(msg, 0, swabbed); - if (ghdr == NULL) { - CERROR("can't decode gss header\n"); - return -EPROTO; - } - - /* sanity checks */ - reqhdr = lustre_msg_buf(msg, 0, sizeof(*reqhdr)); - LASSERT(reqhdr); - - if (ghdr->gh_version != reqhdr->gh_version) { - CERROR("gss version %u mismatch, expect %u\n", - ghdr->gh_version, reqhdr->gh_version); - return -EPROTO; - } - - switch (ghdr->gh_proc) { - case PTLRPC_GSS_PROC_DATA: - pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK; - - if (!req->rq_early && - !equi(req->rq_pack_bulk == 1, pack_bulk)) { - CERROR("%s bulk flag in reply\n", - req->rq_pack_bulk ? "missing" : "unexpected"); - return -EPROTO; - } - - if (ghdr->gh_seq != reqhdr->gh_seq) { - CERROR("seqnum %u mismatch, expect %u\n", - ghdr->gh_seq, reqhdr->gh_seq); - return -EPROTO; - } - - if (ghdr->gh_svc != reqhdr->gh_svc) { - CERROR("svc %u mismatch, expect %u\n", - ghdr->gh_svc, reqhdr->gh_svc); - return -EPROTO; - } - - if (swabbed) - gss_header_swabber(ghdr); - - major = gss_verify_msg(msg, gctx->gc_mechctx, reqhdr->gh_svc); - if (major != GSS_S_COMPLETE) { - CERROR("failed to verify reply: %x\n", major); - return -EPERM; - } - - if (req->rq_early && reqhdr->gh_svc == SPTLRPC_SVC_NULL) { - __u32 cksum; - - cksum = crc32_le(!(__u32) 0, - lustre_msg_buf(msg, 1, 0), - lustre_msg_buflen(msg, 1)); - if (cksum != msg->lm_cksum) { - CWARN("early reply checksum mismatch: " - "%08x != %08x\n", cksum, msg->lm_cksum); - return -EPROTO; - } - } - - if (pack_bulk) { - /* bulk checksum is right after the lustre msg */ - if (msg->lm_bufcount < 3) { - CERROR("Invalid reply bufcount %u\n", - msg->lm_bufcount); - return -EPROTO; - } - - rc = bulk_sec_desc_unpack(msg, 2, swabbed); - if (rc) { - CERROR("unpack bulk desc: %d\n", rc); - return rc; - } - } - - req->rq_repmsg = lustre_msg_buf(msg, 1, 0); - req->rq_replen = msg->lm_buflens[1]; - break; - case PTLRPC_GSS_PROC_ERR: - if (req->rq_early) { - CERROR("server return error with early reply\n"); - rc = -EPROTO; - } else { - rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr); - } - break; - default: - CERROR("unknown gss proc %d\n", ghdr->gh_proc); - rc = -EPROTO; - } - - return rc; -} - -int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req) -{ - struct gss_cli_ctx *gctx; - rawobj_t hdrobj, msgobj, token; - struct gss_header *ghdr; - __u32 buflens[2], major; - int wiresize, rc; - - LASSERT(req->rq_clrbuf); - LASSERT(req->rq_cli_ctx == ctx); - LASSERT(req->rq_reqlen); - - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - - /* final clear data length */ - req->rq_clrdata_len = lustre_msg_size_v2(req->rq_clrbuf->lm_bufcount, - req->rq_clrbuf->lm_buflens); - - /* calculate wire data length */ - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(&gctx->gc_base, req->rq_clrdata_len, 1); - wiresize = lustre_msg_size_v2(2, buflens); - - /* allocate wire buffer */ - if (req->rq_pool) { - /* pre-allocated */ - LASSERT(req->rq_reqbuf); - LASSERT(req->rq_reqbuf != req->rq_clrbuf); - LASSERT(req->rq_reqbuf_len >= wiresize); - } else { - OBD_ALLOC_LARGE(req->rq_reqbuf, wiresize); - if (!req->rq_reqbuf) - return -ENOMEM; - req->rq_reqbuf_len = wiresize; - } - - lustre_init_msg_v2(req->rq_reqbuf, 2, buflens, NULL); - req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc; - - /* gss header */ - ghdr = lustre_msg_buf(req->rq_reqbuf, 0, 0); - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_sp = (__u8) ctx->cc_sec->ps_part; - ghdr->gh_flags = 0; - ghdr->gh_proc = gctx->gc_proc; - ghdr->gh_svc = SPTLRPC_SVC_PRIV; - ghdr->gh_handle.len = gctx->gc_handle.len; - memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len); - if (req->rq_pack_bulk) - ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK; - if (req->rq_pack_udesc) - ghdr->gh_flags |= LUSTRE_GSS_PACK_USER; - -redo: - ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq); - - /* buffer objects */ - hdrobj.len = PTLRPC_GSS_HEADER_SIZE; - hdrobj.data = (__u8 *) ghdr; - msgobj.len = req->rq_clrdata_len; - msgobj.data = (__u8 *) req->rq_clrbuf; - token.len = lustre_msg_buflen(req->rq_reqbuf, 1); - token.data = lustre_msg_buf(req->rq_reqbuf, 1, 0); - - major = lgss_wrap(gctx->gc_mechctx, &hdrobj, &msgobj, - req->rq_clrbuf_len, &token); - if (major != GSS_S_COMPLETE) { - CERROR("priv: wrap message error: %08x\n", major); - GOTO(err_free, rc = -EPERM); - } - LASSERT(token.len <= buflens[1]); - - /* see explain in gss_cli_ctx_sign() */ - if (unlikely(atomic_read(&gctx->gc_seq) - ghdr->gh_seq > - GSS_SEQ_REPACK_THRESHOLD)) { - int behind = atomic_read(&gctx->gc_seq) - ghdr->gh_seq; - - gss_stat_oos_record_cli(behind); - CWARN("req %p: %u behind, retry sealing\n", req, behind); - - ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq); - goto redo; - } - - /* now set the final wire data length */ - req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 1, token.len,0); - return 0; - -err_free: - if (!req->rq_pool) { - OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); - req->rq_reqbuf = NULL; - req->rq_reqbuf_len = 0; - } - return rc; -} - -int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_request *req) -{ - struct gss_cli_ctx *gctx; - struct gss_header *ghdr; - struct lustre_msg *msg = req->rq_repdata; - int msglen, pack_bulk, swabbed, rc; - __u32 major; - - LASSERT(req->rq_cli_ctx == ctx); - LASSERT(req->rq_ctx_init == 0); - LASSERT(msg); - - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - swabbed = ptlrpc_rep_need_swab(req); - - ghdr = gss_swab_header(msg, 0, swabbed); - if (ghdr == NULL) { - CERROR("can't decode gss header\n"); - return -EPROTO; - } - - /* sanity checks */ - if (ghdr->gh_version != PTLRPC_GSS_VERSION) { - CERROR("gss version %u mismatch, expect %u\n", - ghdr->gh_version, PTLRPC_GSS_VERSION); - return -EPROTO; - } - - switch (ghdr->gh_proc) { - case PTLRPC_GSS_PROC_DATA: - pack_bulk = ghdr->gh_flags & LUSTRE_GSS_PACK_BULK; - - if (!req->rq_early && - !equi(req->rq_pack_bulk == 1, pack_bulk)) { - CERROR("%s bulk flag in reply\n", - req->rq_pack_bulk ? "missing" : "unexpected"); - return -EPROTO; - } - - if (swabbed) - gss_header_swabber(ghdr); - - /* use rq_repdata_len as buffer size, which assume unseal - * doesn't need extra memory space. for precise control, we'd - * better calculate out actual buffer size as - * (repbuf_len - offset - repdata_len) */ - major = gss_unseal_msg(gctx->gc_mechctx, msg, - &msglen, req->rq_repdata_len); - if (major != GSS_S_COMPLETE) { - CERROR("failed to unwrap reply: %x\n", major); - rc = -EPERM; - break; - } - - swabbed = __lustre_unpack_msg(msg, msglen); - if (swabbed < 0) { - CERROR("Failed to unpack after decryption\n"); - return -EPROTO; - } - - if (msg->lm_bufcount < 1) { - CERROR("Invalid reply buffer: empty\n"); - return -EPROTO; - } - - if (pack_bulk) { - if (msg->lm_bufcount < 2) { - CERROR("bufcount %u: missing bulk sec desc\n", - msg->lm_bufcount); - return -EPROTO; - } - - /* bulk checksum is the last segment */ - if (bulk_sec_desc_unpack(msg, msg->lm_bufcount - 1, - swabbed)) - return -EPROTO; - } - - req->rq_repmsg = lustre_msg_buf(msg, 0, 0); - req->rq_replen = msg->lm_buflens[0]; - - rc = 0; - break; - case PTLRPC_GSS_PROC_ERR: - if (req->rq_early) { - CERROR("server return error with early reply\n"); - rc = -EPROTO; - } else { - rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr); - } - break; - default: - CERROR("unexpected proc %d\n", ghdr->gh_proc); - rc = -EPERM; - } - - return rc; -} - -/********************************************* - * reverse context installation * - *********************************************/ - -static inline -int gss_install_rvs_svc_ctx(struct obd_import *imp, - struct gss_sec *gsec, - struct gss_cli_ctx *gctx) -{ - return gss_svc_upcall_install_rvs_ctx(imp, gsec, gctx); -} - -/********************************************* - * GSS security APIs * - *********************************************/ -int gss_sec_create_common(struct gss_sec *gsec, - struct ptlrpc_sec_policy *policy, - struct obd_import *imp, - struct ptlrpc_svc_ctx *svcctx, - struct sptlrpc_flavor *sf) -{ - struct ptlrpc_sec *sec; - - LASSERT(imp); - LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_GSS); - - gsec->gs_mech = lgss_subflavor_to_mech( - SPTLRPC_FLVR_BASE_SUB(sf->sf_rpc)); - if (!gsec->gs_mech) { - CERROR("gss backend 0x%x not found\n", - SPTLRPC_FLVR_BASE_SUB(sf->sf_rpc)); - return -EOPNOTSUPP; - } - - spin_lock_init(&gsec->gs_lock); - gsec->gs_rvs_hdl = 0ULL; - - /* initialize upper ptlrpc_sec */ - sec = &gsec->gs_base; - sec->ps_policy = policy; - atomic_set(&sec->ps_refcount, 0); - atomic_set(&sec->ps_nctx, 0); - sec->ps_id = sptlrpc_get_next_secid(); - sec->ps_flvr = *sf; - sec->ps_import = class_import_get(imp); - spin_lock_init(&sec->ps_lock); - INIT_LIST_HEAD(&sec->ps_gc_list); - - if (!svcctx) { - sec->ps_gc_interval = GSS_GC_INTERVAL; - } else { - LASSERT(sec_is_reverse(sec)); - - /* never do gc on reverse sec */ - sec->ps_gc_interval = 0; - } - - if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV) - sptlrpc_enc_pool_add_user(); - - CDEBUG(D_SEC, "create %s%s@%p\n", (svcctx ? "reverse " : ""), - policy->sp_name, gsec); - return 0; -} - -void gss_sec_destroy_common(struct gss_sec *gsec) -{ - struct ptlrpc_sec *sec = &gsec->gs_base; - - LASSERT(sec->ps_import); - LASSERT(atomic_read(&sec->ps_refcount) == 0); - LASSERT(atomic_read(&sec->ps_nctx) == 0); - - if (gsec->gs_mech) { - lgss_mech_put(gsec->gs_mech); - gsec->gs_mech = NULL; - } - - class_import_put(sec->ps_import); - - if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV) - sptlrpc_enc_pool_del_user(); -} - -void gss_sec_kill(struct ptlrpc_sec *sec) -{ - sec->ps_dying = 1; -} - -int gss_cli_ctx_init_common(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx, - struct ptlrpc_ctx_ops *ctxops, - struct vfs_cred *vcred) -{ - struct gss_cli_ctx *gctx = ctx2gctx(ctx); - - gctx->gc_win = 0; - atomic_set(&gctx->gc_seq, 0); - - INIT_HLIST_NODE(&ctx->cc_cache); - atomic_set(&ctx->cc_refcount, 0); - ctx->cc_sec = sec; - ctx->cc_ops = ctxops; - ctx->cc_expire = 0; - ctx->cc_flags = PTLRPC_CTX_NEW; - ctx->cc_vcred = *vcred; - spin_lock_init(&ctx->cc_lock); - INIT_LIST_HEAD(&ctx->cc_req_list); - INIT_LIST_HEAD(&ctx->cc_gc_chain); - - /* take a ref on belonging sec, balanced in ctx destroying */ - atomic_inc(&sec->ps_refcount); - /* statistic only */ - atomic_inc(&sec->ps_nctx); - - CDEBUG(D_SEC, "%s@%p: create ctx %p(%u->%s)\n", - sec->ps_policy->sp_name, ctx->cc_sec, - ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec)); - return 0; -} - -/* - * return value: - * 1: the context has been taken care of by someone else - * 0: proceed to really destroy the context locally - */ -int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx) -{ - struct gss_cli_ctx *gctx = ctx2gctx(ctx); - - LASSERT(atomic_read(&sec->ps_nctx) > 0); - LASSERT(atomic_read(&ctx->cc_refcount) == 0); - LASSERT(ctx->cc_sec == sec); - - /* - * remove UPTODATE flag of reverse ctx thus we won't send fini rpc, - * this is to avoid potential problems of client side reverse svc ctx - * be mis-destroyed in various recovery scenarios. anyway client can - * manage its reverse ctx well by associating it with its buddy ctx. - */ - if (sec_is_reverse(sec)) - ctx->cc_flags &= ~PTLRPC_CTX_UPTODATE; - - if (gctx->gc_mechctx) { - /* the final context fini rpc will use this ctx too, and it's - * asynchronous which finished by request_out_callback(). so - * we add refcount, whoever drop finally drop the refcount to - * 0 should responsible for the rest of destroy. */ - atomic_inc(&ctx->cc_refcount); - - gss_do_ctx_fini_rpc(gctx); - gss_cli_ctx_finalize(gctx); - - if (!atomic_dec_and_test(&ctx->cc_refcount)) - return 1; - } - - if (sec_is_reverse(sec)) - CWARN("reverse sec %p: destroy ctx %p\n", - ctx->cc_sec, ctx); - else - CWARN("%s@%p: destroy ctx %p(%u->%s)\n", - sec->ps_policy->sp_name, ctx->cc_sec, - ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec)); - - return 0; -} - -static -int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int svc, int msgsize) -{ - int bufsize, txtsize; - int bufcnt = 2; - __u32 buflens[5]; - - /* - * on-wire data layout: - * - gss header - * - lustre message - * - user descriptor (optional) - * - bulk sec descriptor (optional) - * - signature (optional) - * - svc == NULL: NULL - * - svc == AUTH: signature of gss header - * - svc == INTG: signature of all above - * - * if this is context negotiation, reserver fixed space - * at the last (signature) segment regardless of svc mode. - */ - - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - txtsize = buflens[0]; - - buflens[1] = msgsize; - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[1]; - - if (req->rq_pack_udesc) { - buflens[bufcnt] = sptlrpc_current_user_desc_size(); - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[bufcnt]; - bufcnt++; - } - - if (req->rq_pack_bulk) { - buflens[bufcnt] = gss_cli_bulk_payload(req->rq_cli_ctx, - &req->rq_flvr, - 0, req->rq_bulk_read); - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[bufcnt]; - bufcnt++; - } - - if (req->rq_ctx_init) - buflens[bufcnt++] = GSS_CTX_INIT_MAX_LEN; - else if (svc != SPTLRPC_SVC_NULL) - buflens[bufcnt++] = gss_cli_payload(req->rq_cli_ctx, txtsize,0); - - bufsize = lustre_msg_size_v2(bufcnt, buflens); - - if (!req->rq_reqbuf) { - bufsize = size_roundup_power2(bufsize); - - OBD_ALLOC_LARGE(req->rq_reqbuf, bufsize); - if (!req->rq_reqbuf) - return -ENOMEM; - - req->rq_reqbuf_len = bufsize; - } else { - LASSERT(req->rq_pool); - LASSERT(req->rq_reqbuf_len >= bufsize); - memset(req->rq_reqbuf, 0, bufsize); - } - - lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL); - req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc; - - req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, msgsize); - LASSERT(req->rq_reqmsg); - - /* pack user desc here, later we might leave current user's process */ - if (req->rq_pack_udesc) - sptlrpc_pack_user_desc(req->rq_reqbuf, 2); - - return 0; -} - -static -int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int msgsize) -{ - __u32 ibuflens[3], wbuflens[2]; - int ibufcnt; - int clearsize, wiresize; - - LASSERT(req->rq_clrbuf == NULL); - LASSERT(req->rq_clrbuf_len == 0); - - /* Inner (clear) buffers - * - lustre message - * - user descriptor (optional) - * - bulk checksum (optional) - */ - ibufcnt = 1; - ibuflens[0] = msgsize; - - if (req->rq_pack_udesc) - ibuflens[ibufcnt++] = sptlrpc_current_user_desc_size(); - if (req->rq_pack_bulk) - ibuflens[ibufcnt++] = gss_cli_bulk_payload(req->rq_cli_ctx, - &req->rq_flvr, 0, - req->rq_bulk_read); - - clearsize = lustre_msg_size_v2(ibufcnt, ibuflens); - /* to allow append padding during encryption */ - clearsize += GSS_MAX_CIPHER_BLOCK; - - /* Wrapper (wire) buffers - * - gss header - * - cipher text - */ - wbuflens[0] = PTLRPC_GSS_HEADER_SIZE; - wbuflens[1] = gss_cli_payload(req->rq_cli_ctx, clearsize, 1); - wiresize = lustre_msg_size_v2(2, wbuflens); - - if (req->rq_pool) { - /* rq_reqbuf is preallocated */ - LASSERT(req->rq_reqbuf); - LASSERT(req->rq_reqbuf_len >= wiresize); - - memset(req->rq_reqbuf, 0, req->rq_reqbuf_len); - - /* if the pre-allocated buffer is big enough, we just pack - * both clear buf & request buf in it, to avoid more alloc. */ - if (clearsize + wiresize <= req->rq_reqbuf_len) { - req->rq_clrbuf = - (void *) (((char *) req->rq_reqbuf) + wiresize); - } else { - CWARN("pre-allocated buf size %d is not enough for " - "both clear (%d) and cipher (%d) text, proceed " - "with extra allocation\n", req->rq_reqbuf_len, - clearsize, wiresize); - } - } - - if (!req->rq_clrbuf) { - clearsize = size_roundup_power2(clearsize); - - OBD_ALLOC_LARGE(req->rq_clrbuf, clearsize); - if (!req->rq_clrbuf) - return -ENOMEM; - } - req->rq_clrbuf_len = clearsize; - - lustre_init_msg_v2(req->rq_clrbuf, ibufcnt, ibuflens, NULL); - req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, msgsize); - - if (req->rq_pack_udesc) - sptlrpc_pack_user_desc(req->rq_clrbuf, 1); - - return 0; -} - -/* - * NOTE: any change of request buffer allocation should also consider - * changing enlarge_reqbuf() series functions. - */ -int gss_alloc_reqbuf(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int msgsize) -{ - int svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - - LASSERT(!req->rq_pack_bulk || - (req->rq_bulk_read || req->rq_bulk_write)); - - switch (svc) { - case SPTLRPC_SVC_NULL: - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - return gss_alloc_reqbuf_intg(sec, req, svc, msgsize); - case SPTLRPC_SVC_PRIV: - return gss_alloc_reqbuf_priv(sec, req, msgsize); - default: - LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc); - return 0; - } -} - -void gss_free_reqbuf(struct ptlrpc_sec *sec, - struct ptlrpc_request *req) -{ - int privacy; - - LASSERT(!req->rq_pool || req->rq_reqbuf); - privacy = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc) == SPTLRPC_SVC_PRIV; - - if (!req->rq_clrbuf) - goto release_reqbuf; - - /* release clear buffer */ - LASSERT(privacy); - LASSERT(req->rq_clrbuf_len); - - if (req->rq_pool == NULL || - req->rq_clrbuf < req->rq_reqbuf || - (char *) req->rq_clrbuf >= - (char *) req->rq_reqbuf + req->rq_reqbuf_len) - OBD_FREE_LARGE(req->rq_clrbuf, req->rq_clrbuf_len); - - req->rq_clrbuf = NULL; - req->rq_clrbuf_len = 0; - -release_reqbuf: - if (!req->rq_pool && req->rq_reqbuf) { - LASSERT(req->rq_reqbuf_len); - - OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); - req->rq_reqbuf = NULL; - req->rq_reqbuf_len = 0; - } -} - -static int do_alloc_repbuf(struct ptlrpc_request *req, int bufsize) -{ - bufsize = size_roundup_power2(bufsize); - - OBD_ALLOC_LARGE(req->rq_repbuf, bufsize); - if (!req->rq_repbuf) - return -ENOMEM; - - req->rq_repbuf_len = bufsize; - return 0; -} - -static -int gss_alloc_repbuf_intg(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int svc, int msgsize) -{ - int txtsize; - __u32 buflens[4]; - int bufcnt = 2; - int alloc_size; - - /* - * on-wire data layout: - * - gss header - * - lustre message - * - bulk sec descriptor (optional) - * - signature (optional) - * - svc == NULL: NULL - * - svc == AUTH: signature of gss header - * - svc == INTG: signature of all above - * - * if this is context negotiation, reserver fixed space - * at the last (signature) segment regardless of svc mode. - */ - - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - txtsize = buflens[0]; - - buflens[1] = msgsize; - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[1]; - - if (req->rq_pack_bulk) { - buflens[bufcnt] = gss_cli_bulk_payload(req->rq_cli_ctx, - &req->rq_flvr, - 1, req->rq_bulk_read); - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[bufcnt]; - bufcnt++; - } - - if (req->rq_ctx_init) - buflens[bufcnt++] = GSS_CTX_INIT_MAX_LEN; - else if (svc != SPTLRPC_SVC_NULL) - buflens[bufcnt++] = gss_cli_payload(req->rq_cli_ctx, txtsize,0); - - alloc_size = lustre_msg_size_v2(bufcnt, buflens); - - /* add space for early reply */ - alloc_size += gss_at_reply_off_integ; - - return do_alloc_repbuf(req, alloc_size); -} - -static -int gss_alloc_repbuf_priv(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int msgsize) -{ - int txtsize; - __u32 buflens[2]; - int bufcnt; - int alloc_size; - - /* inner buffers */ - bufcnt = 1; - buflens[0] = msgsize; - - if (req->rq_pack_bulk) - buflens[bufcnt++] = gss_cli_bulk_payload(req->rq_cli_ctx, - &req->rq_flvr, - 1, req->rq_bulk_read); - txtsize = lustre_msg_size_v2(bufcnt, buflens); - txtsize += GSS_MAX_CIPHER_BLOCK; - - /* wrapper buffers */ - bufcnt = 2; - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(req->rq_cli_ctx, txtsize, 1); - - alloc_size = lustre_msg_size_v2(bufcnt, buflens); - /* add space for early reply */ - alloc_size += gss_at_reply_off_priv; - - return do_alloc_repbuf(req, alloc_size); -} - -int gss_alloc_repbuf(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int msgsize) -{ - int svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - - LASSERT(!req->rq_pack_bulk || - (req->rq_bulk_read || req->rq_bulk_write)); - - switch (svc) { - case SPTLRPC_SVC_NULL: - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - return gss_alloc_repbuf_intg(sec, req, svc, msgsize); - case SPTLRPC_SVC_PRIV: - return gss_alloc_repbuf_priv(sec, req, msgsize); - default: - LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc); - return 0; - } -} - -void gss_free_repbuf(struct ptlrpc_sec *sec, - struct ptlrpc_request *req) -{ - OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len); - req->rq_repbuf = NULL; - req->rq_repbuf_len = 0; - req->rq_repdata = NULL; - req->rq_repdata_len = 0; -} - -static int get_enlarged_msgsize(struct lustre_msg *msg, - int segment, int newsize) -{ - int save, newmsg_size; - - LASSERT(newsize >= msg->lm_buflens[segment]); - - save = msg->lm_buflens[segment]; - msg->lm_buflens[segment] = newsize; - newmsg_size = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens); - msg->lm_buflens[segment] = save; - - return newmsg_size; -} - -static int get_enlarged_msgsize2(struct lustre_msg *msg, - int segment1, int newsize1, - int segment2, int newsize2) -{ - int save1, save2, newmsg_size; - - LASSERT(newsize1 >= msg->lm_buflens[segment1]); - LASSERT(newsize2 >= msg->lm_buflens[segment2]); - - save1 = msg->lm_buflens[segment1]; - save2 = msg->lm_buflens[segment2]; - msg->lm_buflens[segment1] = newsize1; - msg->lm_buflens[segment2] = newsize2; - newmsg_size = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens); - msg->lm_buflens[segment1] = save1; - msg->lm_buflens[segment2] = save2; - - return newmsg_size; -} - -static -int gss_enlarge_reqbuf_intg(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int svc, - int segment, int newsize) -{ - struct lustre_msg *newbuf; - int txtsize, sigsize = 0, i; - int newmsg_size, newbuf_size; - - /* - * gss header is at seg 0; - * embedded msg is at seg 1; - * signature (if any) is at the last seg - */ - LASSERT(req->rq_reqbuf); - LASSERT(req->rq_reqbuf_len > req->rq_reqlen); - LASSERT(req->rq_reqbuf->lm_bufcount >= 2); - LASSERT(lustre_msg_buf(req->rq_reqbuf, 1, 0) == req->rq_reqmsg); - - /* 1. compute new embedded msg size */ - newmsg_size = get_enlarged_msgsize(req->rq_reqmsg, segment, newsize); - LASSERT(newmsg_size >= req->rq_reqbuf->lm_buflens[1]); - - /* 2. compute new wrapper msg size */ - if (svc == SPTLRPC_SVC_NULL) { - /* no signature, get size directly */ - newbuf_size = get_enlarged_msgsize(req->rq_reqbuf, - 1, newmsg_size); - } else { - txtsize = req->rq_reqbuf->lm_buflens[0]; - - if (svc == SPTLRPC_SVC_INTG) { - for (i = 1; i < req->rq_reqbuf->lm_bufcount; i++) - txtsize += req->rq_reqbuf->lm_buflens[i]; - txtsize += newmsg_size - req->rq_reqbuf->lm_buflens[1]; - } - - sigsize = gss_cli_payload(req->rq_cli_ctx, txtsize, 0); - LASSERT(sigsize >= msg_last_seglen(req->rq_reqbuf)); - - newbuf_size = get_enlarged_msgsize2( - req->rq_reqbuf, - 1, newmsg_size, - msg_last_segidx(req->rq_reqbuf), - sigsize); - } - - /* request from pool should always have enough buffer */ - LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size); - - if (req->rq_reqbuf_len < newbuf_size) { - newbuf_size = size_roundup_power2(newbuf_size); - - OBD_ALLOC_LARGE(newbuf, newbuf_size); - if (newbuf == NULL) - return -ENOMEM; - - memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len); - - OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); - req->rq_reqbuf = newbuf; - req->rq_reqbuf_len = newbuf_size; - req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, 0); - } - - /* do enlargement, from wrapper to embedded, from end to begin */ - if (svc != SPTLRPC_SVC_NULL) - _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, - msg_last_segidx(req->rq_reqbuf), - sigsize); - - _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 1, newmsg_size); - _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize); - - req->rq_reqlen = newmsg_size; - return 0; -} - -static -int gss_enlarge_reqbuf_priv(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int segment, int newsize) -{ - struct lustre_msg *newclrbuf; - int newmsg_size, newclrbuf_size, newcipbuf_size; - __u32 buflens[3]; - - /* - * embedded msg is at seg 0 of clear buffer; - * cipher text is at seg 2 of cipher buffer; - */ - LASSERT(req->rq_pool || - (req->rq_reqbuf == NULL && req->rq_reqbuf_len == 0)); - LASSERT(req->rq_reqbuf == NULL || - (req->rq_pool && req->rq_reqbuf->lm_bufcount == 3)); - LASSERT(req->rq_clrbuf); - LASSERT(req->rq_clrbuf_len > req->rq_reqlen); - LASSERT(lustre_msg_buf(req->rq_clrbuf, 0, 0) == req->rq_reqmsg); - - /* compute new embedded msg size */ - newmsg_size = get_enlarged_msgsize(req->rq_reqmsg, segment, newsize); - - /* compute new clear buffer size */ - newclrbuf_size = get_enlarged_msgsize(req->rq_clrbuf, 0, newmsg_size); - newclrbuf_size += GSS_MAX_CIPHER_BLOCK; - - /* compute new cipher buffer size */ - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0); - buflens[2] = gss_cli_payload(req->rq_cli_ctx, newclrbuf_size, 1); - newcipbuf_size = lustre_msg_size_v2(3, buflens); - - /* handle the case that we put both clear buf and cipher buf into - * pre-allocated single buffer. */ - if (unlikely(req->rq_pool) && - req->rq_clrbuf >= req->rq_reqbuf && - (char *) req->rq_clrbuf < - (char *) req->rq_reqbuf + req->rq_reqbuf_len) { - /* it couldn't be better we still fit into the - * pre-allocated buffer. */ - if (newclrbuf_size + newcipbuf_size <= req->rq_reqbuf_len) { - void *src, *dst; - - /* move clear text backward. */ - src = req->rq_clrbuf; - dst = (char *) req->rq_reqbuf + newcipbuf_size; - - memmove(dst, src, req->rq_clrbuf_len); - - req->rq_clrbuf = (struct lustre_msg *) dst; - req->rq_clrbuf_len = newclrbuf_size; - req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, 0); - } else { - /* sadly we have to split out the clear buffer */ - LASSERT(req->rq_reqbuf_len >= newcipbuf_size); - LASSERT(req->rq_clrbuf_len < newclrbuf_size); - } - } - - if (req->rq_clrbuf_len < newclrbuf_size) { - newclrbuf_size = size_roundup_power2(newclrbuf_size); - - OBD_ALLOC_LARGE(newclrbuf, newclrbuf_size); - if (newclrbuf == NULL) - return -ENOMEM; - - memcpy(newclrbuf, req->rq_clrbuf, req->rq_clrbuf_len); - - if (req->rq_reqbuf == NULL || - req->rq_clrbuf < req->rq_reqbuf || - (char *) req->rq_clrbuf >= - (char *) req->rq_reqbuf + req->rq_reqbuf_len) { - OBD_FREE_LARGE(req->rq_clrbuf, req->rq_clrbuf_len); - } - - req->rq_clrbuf = newclrbuf; - req->rq_clrbuf_len = newclrbuf_size; - req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, 0); - } - - _sptlrpc_enlarge_msg_inplace(req->rq_clrbuf, 0, newmsg_size); - _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize); - req->rq_reqlen = newmsg_size; - - return 0; -} - -int gss_enlarge_reqbuf(struct ptlrpc_sec *sec, - struct ptlrpc_request *req, - int segment, int newsize) -{ - int svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - - LASSERT(!req->rq_ctx_init && !req->rq_ctx_fini); - - switch (svc) { - case SPTLRPC_SVC_NULL: - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - return gss_enlarge_reqbuf_intg(sec, req, svc, segment, newsize); - case SPTLRPC_SVC_PRIV: - return gss_enlarge_reqbuf_priv(sec, req, segment, newsize); - default: - LASSERTF(0, "bad rpc flavor %x\n", req->rq_flvr.sf_rpc); - return 0; - } -} - -int gss_sec_install_rctx(struct obd_import *imp, - struct ptlrpc_sec *sec, - struct ptlrpc_cli_ctx *ctx) -{ - struct gss_sec *gsec; - struct gss_cli_ctx *gctx; - int rc; - - gsec = container_of(sec, struct gss_sec, gs_base); - gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - - rc = gss_install_rvs_svc_ctx(imp, gsec, gctx); - return rc; -} - -/******************************************** - * server side API * - ********************************************/ - -static inline -int gss_svc_reqctx_is_special(struct gss_svc_reqctx *grctx) -{ - LASSERT(grctx); - return (grctx->src_init || grctx->src_init_continue || - grctx->src_err_notify); -} - -static -void gss_svc_reqctx_free(struct gss_svc_reqctx *grctx) -{ - if (grctx->src_ctx) - gss_svc_upcall_put_ctx(grctx->src_ctx); - - sptlrpc_policy_put(grctx->src_base.sc_policy); - OBD_FREE_PTR(grctx); -} - -static inline -void gss_svc_reqctx_addref(struct gss_svc_reqctx *grctx) -{ - LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0); - atomic_inc(&grctx->src_base.sc_refcount); -} - -static inline -void gss_svc_reqctx_decref(struct gss_svc_reqctx *grctx) -{ - LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0); - - if (atomic_dec_and_test(&grctx->src_base.sc_refcount)) - gss_svc_reqctx_free(grctx); -} - -static -int gss_svc_sign(struct ptlrpc_request *req, - struct ptlrpc_reply_state *rs, - struct gss_svc_reqctx *grctx, - __u32 svc) -{ - __u32 flags = 0; - int rc; - - LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0)); - - /* embedded lustre_msg might have been shrunk */ - if (req->rq_replen != rs->rs_repbuf->lm_buflens[1]) - lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1); - - if (req->rq_pack_bulk) - flags |= LUSTRE_GSS_PACK_BULK; - - rc = gss_sign_msg(rs->rs_repbuf, grctx->src_ctx->gsc_mechctx, - LUSTRE_SP_ANY, flags, PTLRPC_GSS_PROC_DATA, - grctx->src_wirectx.gw_seq, svc, NULL); - if (rc < 0) - return rc; - - rs->rs_repdata_len = rc; - - if (likely(req->rq_packed_final)) { - if (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT) - req->rq_reply_off = gss_at_reply_off_integ; - else - req->rq_reply_off = 0; - } else { - if (svc == SPTLRPC_SVC_NULL) - rs->rs_repbuf->lm_cksum = crc32_le(!(__u32) 0, - lustre_msg_buf(rs->rs_repbuf, 1, 0), - lustre_msg_buflen(rs->rs_repbuf, 1)); - req->rq_reply_off = 0; - } - - return 0; -} - -int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor) -{ - struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - struct ptlrpc_reply_state *rs; - struct gss_err_header *ghdr; - int replen = sizeof(struct ptlrpc_body); - int rc; - - //if (OBD_FAIL_CHECK_ORSET(OBD_FAIL_SVCGSS_ERR_NOTIFY, OBD_FAIL_ONCE)) - // return -EINVAL; - - grctx->src_err_notify = 1; - grctx->src_reserve_len = 0; - - rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0); - if (rc) { - CERROR("could not pack reply, err %d\n", rc); - return rc; - } - - /* gss hdr */ - rs = req->rq_reply_state; - LASSERT(rs->rs_repbuf->lm_buflens[1] >= sizeof(*ghdr)); - ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0); - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_flags = 0; - ghdr->gh_proc = PTLRPC_GSS_PROC_ERR; - ghdr->gh_major = major; - ghdr->gh_minor = minor; - ghdr->gh_handle.len = 0; /* fake context handle */ - - rs->rs_repdata_len = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount, - rs->rs_repbuf->lm_buflens); - - CDEBUG(D_SEC, "prepare gss error notify(0x%x/0x%x) to %s\n", - major, minor, libcfs_nid2str(req->rq_peer.nid)); - return 0; -} - -static -int gss_svc_handle_init(struct ptlrpc_request *req, - struct gss_wire_ctx *gw) -{ - struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - struct lustre_msg *reqbuf = req->rq_reqbuf; - struct obd_uuid *uuid; - struct obd_device *target; - rawobj_t uuid_obj, rvs_hdl, in_token; - __u32 lustre_svc; - __u32 *secdata, seclen; - int swabbed, rc; - - CDEBUG(D_SEC, "processing gss init(%d) request from %s\n", gw->gw_proc, - libcfs_nid2str(req->rq_peer.nid)); - - req->rq_ctx_init = 1; - - if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) { - CERROR("unexpected bulk flag\n"); - return SECSVC_DROP; - } - - if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) { - CERROR("proc %u: invalid handle length %u\n", - gw->gw_proc, gw->gw_handle.len); - return SECSVC_DROP; - } - - if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4) { - CERROR("Invalid bufcount %d\n", reqbuf->lm_bufcount); - return SECSVC_DROP; - } - - swabbed = ptlrpc_req_need_swab(req); - - /* ctx initiate payload is in last segment */ - secdata = lustre_msg_buf(reqbuf, reqbuf->lm_bufcount - 1, 0); - seclen = reqbuf->lm_buflens[reqbuf->lm_bufcount - 1]; - - if (seclen < 4 + 4) { - CERROR("sec size %d too small\n", seclen); - return SECSVC_DROP; - } - - /* lustre svc type */ - lustre_svc = le32_to_cpu(*secdata++); - seclen -= 4; - - /* extract target uuid, note this code is somewhat fragile - * because touched internal structure of obd_uuid */ - if (rawobj_extract(&uuid_obj, &secdata, &seclen)) { - CERROR("failed to extract target uuid\n"); - return SECSVC_DROP; - } - uuid_obj.data[uuid_obj.len - 1] = '\0'; - - uuid = (struct obd_uuid *) uuid_obj.data; - target = class_uuid2obd(uuid); - if (!target || target->obd_stopping || !target->obd_set_up) { - CERROR("target '%s' is not available for context init (%s)\n", - uuid->uuid, target == NULL ? "no target" : - (target->obd_stopping ? "stopping" : "not set up")); - return SECSVC_DROP; - } - - /* extract reverse handle */ - if (rawobj_extract(&rvs_hdl, &secdata, &seclen)) { - CERROR("failed extract reverse handle\n"); - return SECSVC_DROP; - } - - /* extract token */ - if (rawobj_extract(&in_token, &secdata, &seclen)) { - CERROR("can't extract token\n"); - return SECSVC_DROP; - } - - rc = gss_svc_upcall_handle_init(req, grctx, gw, target, lustre_svc, - &rvs_hdl, &in_token); - if (rc != SECSVC_OK) - return rc; - - if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_oss || - grctx->src_ctx->gsc_usr_root) - CWARN("create svc ctx %p: user from %s authenticated as %s\n", - grctx->src_ctx, libcfs_nid2str(req->rq_peer.nid), - grctx->src_ctx->gsc_usr_mds ? "mds" : - (grctx->src_ctx->gsc_usr_oss ? "oss" : "root")); - else - CWARN("create svc ctx %p: accept user %u from %s\n", - grctx->src_ctx, grctx->src_ctx->gsc_uid, - libcfs_nid2str(req->rq_peer.nid)); - - if (gw->gw_flags & LUSTRE_GSS_PACK_USER) { - if (reqbuf->lm_bufcount < 4) { - CERROR("missing user descriptor\n"); - return SECSVC_DROP; - } - if (sptlrpc_unpack_user_desc(reqbuf, 2, swabbed)) { - CERROR("Mal-formed user descriptor\n"); - return SECSVC_DROP; - } - - req->rq_pack_udesc = 1; - req->rq_user_desc = lustre_msg_buf(reqbuf, 2, 0); - } - - req->rq_reqmsg = lustre_msg_buf(reqbuf, 1, 0); - req->rq_reqlen = lustre_msg_buflen(reqbuf, 1); - - return rc; -} - -/* - * last segment must be the gss signature. - */ -static -int gss_svc_verify_request(struct ptlrpc_request *req, - struct gss_svc_reqctx *grctx, - struct gss_wire_ctx *gw, - __u32 *major) -{ - struct gss_svc_ctx *gctx = grctx->src_ctx; - struct lustre_msg *msg = req->rq_reqbuf; - int offset = 2; - int swabbed; - - *major = GSS_S_COMPLETE; - - if (msg->lm_bufcount < 2) { - CERROR("Too few segments (%u) in request\n", msg->lm_bufcount); - return -EINVAL; - } - - if (gw->gw_svc == SPTLRPC_SVC_NULL) - goto verified; - - if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) { - CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq); - *major = GSS_S_DUPLICATE_TOKEN; - return -EACCES; - } - - *major = gss_verify_msg(msg, gctx->gsc_mechctx, gw->gw_svc); - if (*major != GSS_S_COMPLETE) { - CERROR("failed to verify request: %x\n", *major); - return -EACCES; - } - - if (gctx->gsc_reverse == 0 && - gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) { - CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq); - *major = GSS_S_DUPLICATE_TOKEN; - return -EACCES; - } - -verified: - swabbed = ptlrpc_req_need_swab(req); - - /* user descriptor */ - if (gw->gw_flags & LUSTRE_GSS_PACK_USER) { - if (msg->lm_bufcount < (offset + 1)) { - CERROR("no user desc included\n"); - return -EINVAL; - } - - if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) { - CERROR("Mal-formed user descriptor\n"); - return -EINVAL; - } - - req->rq_pack_udesc = 1; - req->rq_user_desc = lustre_msg_buf(msg, offset, 0); - offset++; - } - - /* check bulk_sec_desc data */ - if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) { - if (msg->lm_bufcount < (offset + 1)) { - CERROR("missing bulk sec descriptor\n"); - return -EINVAL; - } - - if (bulk_sec_desc_unpack(msg, offset, swabbed)) - return -EINVAL; - - req->rq_pack_bulk = 1; - grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0); - grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset); - } - - req->rq_reqmsg = lustre_msg_buf(msg, 1, 0); - req->rq_reqlen = msg->lm_buflens[1]; - return 0; -} - -static -int gss_svc_unseal_request(struct ptlrpc_request *req, - struct gss_svc_reqctx *grctx, - struct gss_wire_ctx *gw, - __u32 *major) -{ - struct gss_svc_ctx *gctx = grctx->src_ctx; - struct lustre_msg *msg = req->rq_reqbuf; - int swabbed, msglen, offset = 1; - - if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) { - CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq); - *major = GSS_S_DUPLICATE_TOKEN; - return -EACCES; - } - - *major = gss_unseal_msg(gctx->gsc_mechctx, msg, - &msglen, req->rq_reqdata_len); - if (*major != GSS_S_COMPLETE) { - CERROR("failed to unwrap request: %x\n", *major); - return -EACCES; - } - - if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) { - CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq); - *major = GSS_S_DUPLICATE_TOKEN; - return -EACCES; - } - - swabbed = __lustre_unpack_msg(msg, msglen); - if (swabbed < 0) { - CERROR("Failed to unpack after decryption\n"); - return -EINVAL; - } - req->rq_reqdata_len = msglen; - - if (msg->lm_bufcount < 1) { - CERROR("Invalid buffer: is empty\n"); - return -EINVAL; - } - - if (gw->gw_flags & LUSTRE_GSS_PACK_USER) { - if (msg->lm_bufcount < offset + 1) { - CERROR("no user descriptor included\n"); - return -EINVAL; - } - - if (sptlrpc_unpack_user_desc(msg, offset, swabbed)) { - CERROR("Mal-formed user descriptor\n"); - return -EINVAL; - } - - req->rq_pack_udesc = 1; - req->rq_user_desc = lustre_msg_buf(msg, offset, 0); - offset++; - } - - if (gw->gw_flags & LUSTRE_GSS_PACK_BULK) { - if (msg->lm_bufcount < offset + 1) { - CERROR("no bulk checksum included\n"); - return -EINVAL; - } - - if (bulk_sec_desc_unpack(msg, offset, swabbed)) - return -EINVAL; - - req->rq_pack_bulk = 1; - grctx->src_reqbsd = lustre_msg_buf(msg, offset, 0); - grctx->src_reqbsd_size = lustre_msg_buflen(msg, offset); - } - - req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0); - req->rq_reqlen = req->rq_reqbuf->lm_buflens[0]; - return 0; -} - -static -int gss_svc_handle_data(struct ptlrpc_request *req, - struct gss_wire_ctx *gw) -{ - struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - __u32 major = 0; - int rc = 0; - - grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw); - if (!grctx->src_ctx) { - major = GSS_S_NO_CONTEXT; - goto error; - } - - switch (gw->gw_svc) { - case SPTLRPC_SVC_NULL: - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - rc = gss_svc_verify_request(req, grctx, gw, &major); - break; - case SPTLRPC_SVC_PRIV: - rc = gss_svc_unseal_request(req, grctx, gw, &major); - break; - default: - CERROR("unsupported gss service %d\n", gw->gw_svc); - rc = -EINVAL; - } - - if (rc == 0) - return SECSVC_OK; - - CERROR("svc %u failed: major 0x%08x: req xid "LPU64" ctx %p idx " - LPX64"(%u->%s)\n", gw->gw_svc, major, req->rq_xid, - grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle), - grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid)); -error: - /* we only notify client in case of NO_CONTEXT/BAD_SIG, which - * might happen after server reboot, to allow recovery. */ - if ((major == GSS_S_NO_CONTEXT || major == GSS_S_BAD_SIG) && - gss_pack_err_notify(req, major, 0) == 0) - return SECSVC_COMPLETE; - - return SECSVC_DROP; -} - -static -int gss_svc_handle_destroy(struct ptlrpc_request *req, - struct gss_wire_ctx *gw) -{ - struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - __u32 major; - - req->rq_ctx_fini = 1; - req->rq_no_reply = 1; - - grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw); - if (!grctx->src_ctx) { - CDEBUG(D_SEC, "invalid gss context handle for destroy.\n"); - return SECSVC_DROP; - } - - if (gw->gw_svc != SPTLRPC_SVC_INTG) { - CERROR("svc %u is not supported in destroy.\n", gw->gw_svc); - return SECSVC_DROP; - } - - if (gss_svc_verify_request(req, grctx, gw, &major)) - return SECSVC_DROP; - - CWARN("destroy svc ctx %p idx "LPX64" (%u->%s)\n", - grctx->src_ctx, gss_handle_to_u64(&gw->gw_handle), - grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid)); - - gss_svc_upcall_destroy_ctx(grctx->src_ctx); - - if (gw->gw_flags & LUSTRE_GSS_PACK_USER) { - if (req->rq_reqbuf->lm_bufcount < 4) { - CERROR("missing user descriptor, ignore it\n"); - return SECSVC_OK; - } - if (sptlrpc_unpack_user_desc(req->rq_reqbuf, 2, - ptlrpc_req_need_swab(req))) { - CERROR("Mal-formed user descriptor, ignore it\n"); - return SECSVC_OK; - } - - req->rq_pack_udesc = 1; - req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0); - } - - return SECSVC_OK; -} - -int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) -{ - struct gss_header *ghdr; - struct gss_svc_reqctx *grctx; - struct gss_wire_ctx *gw; - int swabbed, rc; - - LASSERT(req->rq_reqbuf); - LASSERT(req->rq_svc_ctx == NULL); - - if (req->rq_reqbuf->lm_bufcount < 2) { - CERROR("buf count only %d\n", req->rq_reqbuf->lm_bufcount); - return SECSVC_DROP; - } - - swabbed = ptlrpc_req_need_swab(req); - - ghdr = gss_swab_header(req->rq_reqbuf, 0, swabbed); - if (ghdr == NULL) { - CERROR("can't decode gss header\n"); - return SECSVC_DROP; - } - - /* sanity checks */ - if (ghdr->gh_version != PTLRPC_GSS_VERSION) { - CERROR("gss version %u, expect %u\n", ghdr->gh_version, - PTLRPC_GSS_VERSION); - return SECSVC_DROP; - } - - req->rq_sp_from = ghdr->gh_sp; - - /* alloc grctx data */ - OBD_ALLOC_PTR(grctx); - if (!grctx) - return SECSVC_DROP; - - grctx->src_base.sc_policy = sptlrpc_policy_get(policy); - atomic_set(&grctx->src_base.sc_refcount, 1); - req->rq_svc_ctx = &grctx->src_base; - gw = &grctx->src_wirectx; - - /* save wire context */ - gw->gw_flags = ghdr->gh_flags; - gw->gw_proc = ghdr->gh_proc; - gw->gw_seq = ghdr->gh_seq; - gw->gw_svc = ghdr->gh_svc; - rawobj_from_netobj(&gw->gw_handle, &ghdr->gh_handle); - - /* keep original wire header which subject to checksum verification */ - if (swabbed) - gss_header_swabber(ghdr); - - switch (ghdr->gh_proc) { - case PTLRPC_GSS_PROC_INIT: - case PTLRPC_GSS_PROC_CONTINUE_INIT: - rc = gss_svc_handle_init(req, gw); - break; - case PTLRPC_GSS_PROC_DATA: - rc = gss_svc_handle_data(req, gw); - break; - case PTLRPC_GSS_PROC_DESTROY: - rc = gss_svc_handle_destroy(req, gw); - break; - default: - CERROR("unknown proc %u\n", gw->gw_proc); - rc = SECSVC_DROP; - break; - } - - switch (rc) { - case SECSVC_OK: - LASSERT(grctx->src_ctx); - - req->rq_auth_gss = 1; - req->rq_auth_remote = grctx->src_ctx->gsc_remote; - req->rq_auth_usr_mdt = grctx->src_ctx->gsc_usr_mds; - req->rq_auth_usr_ost = grctx->src_ctx->gsc_usr_oss; - req->rq_auth_usr_root = grctx->src_ctx->gsc_usr_root; - req->rq_auth_uid = grctx->src_ctx->gsc_uid; - req->rq_auth_mapped_uid = grctx->src_ctx->gsc_mapped_uid; - break; - case SECSVC_COMPLETE: - break; - case SECSVC_DROP: - gss_svc_reqctx_free(grctx); - req->rq_svc_ctx = NULL; - break; - } - - return rc; -} - -void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx) -{ - struct gss_svc_reqctx *grctx; - - if (svc_ctx == NULL) { - return; - } - - grctx = gss_svc_ctx2reqctx(svc_ctx); - - CWARN("gss svc invalidate ctx %p(%u)\n", - grctx->src_ctx, grctx->src_ctx->gsc_uid); - gss_svc_upcall_destroy_ctx(grctx->src_ctx); -} - -static inline -int gss_svc_payload(struct gss_svc_reqctx *grctx, int early, - int msgsize, int privacy) -{ - /* we should treat early reply normally, but which is actually sharing - * the same ctx with original request, so in this case we should - * ignore the special ctx's special flags */ - if (early == 0 && gss_svc_reqctx_is_special(grctx)) - return grctx->src_reserve_len; - - return gss_mech_payload(NULL, msgsize, privacy); -} - -static int gss_svc_bulk_payload(struct gss_svc_ctx *gctx, - struct sptlrpc_flavor *flvr, - int read) -{ - int payload = sizeof(struct ptlrpc_bulk_sec_desc); - - if (read) { - switch (SPTLRPC_FLVR_BULK_SVC(flvr->sf_rpc)) { - case SPTLRPC_BULK_SVC_NULL: - break; - case SPTLRPC_BULK_SVC_INTG: - payload += gss_mech_payload(NULL, 0, 0); - break; - case SPTLRPC_BULK_SVC_PRIV: - payload += gss_mech_payload(NULL, 0, 1); - break; - case SPTLRPC_BULK_SVC_AUTH: - default: - LBUG(); - } - } - - return payload; -} - -int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen) -{ - struct gss_svc_reqctx *grctx; - struct ptlrpc_reply_state *rs; - int early, privacy, svc, bsd_off = 0; - __u32 ibuflens[2], buflens[4]; - int ibufcnt = 0, bufcnt; - int txtsize, wmsg_size, rs_size; - - LASSERT(msglen % 8 == 0); - - if (req->rq_pack_bulk && !req->rq_bulk_read && !req->rq_bulk_write) { - CERROR("client request bulk sec on non-bulk rpc\n"); - return -EPROTO; - } - - svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - early = (req->rq_packed_final == 0); - - grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - if (!early && gss_svc_reqctx_is_special(grctx)) - privacy = 0; - else - privacy = (svc == SPTLRPC_SVC_PRIV); - - if (privacy) { - /* inner clear buffers */ - ibufcnt = 1; - ibuflens[0] = msglen; - - if (req->rq_pack_bulk) { - LASSERT(grctx->src_reqbsd); - - bsd_off = ibufcnt; - ibuflens[ibufcnt++] = gss_svc_bulk_payload( - grctx->src_ctx, - &req->rq_flvr, - req->rq_bulk_read); - } - - txtsize = lustre_msg_size_v2(ibufcnt, ibuflens); - txtsize += GSS_MAX_CIPHER_BLOCK; - - /* wrapper buffer */ - bufcnt = 2; - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_svc_payload(grctx, early, txtsize, 1); - } else { - bufcnt = 2; - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = msglen; - - txtsize = buflens[0]; - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[1]; - - if (req->rq_pack_bulk) { - LASSERT(grctx->src_reqbsd); - - bsd_off = bufcnt; - buflens[bufcnt] = gss_svc_bulk_payload( - grctx->src_ctx, - &req->rq_flvr, - req->rq_bulk_read); - if (svc == SPTLRPC_SVC_INTG) - txtsize += buflens[bufcnt]; - bufcnt++; - } - - if ((!early && gss_svc_reqctx_is_special(grctx)) || - svc != SPTLRPC_SVC_NULL) - buflens[bufcnt++] = gss_svc_payload(grctx, early, - txtsize, 0); - } - - wmsg_size = lustre_msg_size_v2(bufcnt, buflens); - - rs_size = sizeof(*rs) + wmsg_size; - rs = req->rq_reply_state; - - if (rs) { - /* pre-allocated */ - LASSERT(rs->rs_size >= rs_size); - } else { - OBD_ALLOC_LARGE(rs, rs_size); - if (rs == NULL) - return -ENOMEM; - - rs->rs_size = rs_size; - } - - rs->rs_repbuf = (struct lustre_msg *) (rs + 1); - rs->rs_repbuf_len = wmsg_size; - - /* initialize the buffer */ - if (privacy) { - lustre_init_msg_v2(rs->rs_repbuf, ibufcnt, ibuflens, NULL); - rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 0, msglen); - } else { - lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL); - rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc; - - rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 1, 0); - } - - if (bsd_off) { - grctx->src_repbsd = lustre_msg_buf(rs->rs_repbuf, bsd_off, 0); - grctx->src_repbsd_size = lustre_msg_buflen(rs->rs_repbuf, - bsd_off); - } - - gss_svc_reqctx_addref(grctx); - rs->rs_svc_ctx = req->rq_svc_ctx; - - LASSERT(rs->rs_msg); - req->rq_reply_state = rs; - return 0; -} - -static int gss_svc_seal(struct ptlrpc_request *req, - struct ptlrpc_reply_state *rs, - struct gss_svc_reqctx *grctx) -{ - struct gss_svc_ctx *gctx = grctx->src_ctx; - rawobj_t hdrobj, msgobj, token; - struct gss_header *ghdr; - __u8 *token_buf; - int token_buflen; - __u32 buflens[2], major; - int msglen, rc; - - /* get clear data length. note embedded lustre_msg might - * have been shrunk */ - if (req->rq_replen != lustre_msg_buflen(rs->rs_repbuf, 0)) - msglen = lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1); - else - msglen = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount, - rs->rs_repbuf->lm_buflens); - - /* temporarily use tail of buffer to hold gss header data */ - LASSERT(msglen + PTLRPC_GSS_HEADER_SIZE <= rs->rs_repbuf_len); - ghdr = (struct gss_header *) ((char *) rs->rs_repbuf + - rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE); - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_sp = LUSTRE_SP_ANY; - ghdr->gh_flags = 0; - ghdr->gh_proc = PTLRPC_GSS_PROC_DATA; - ghdr->gh_seq = grctx->src_wirectx.gw_seq; - ghdr->gh_svc = SPTLRPC_SVC_PRIV; - ghdr->gh_handle.len = 0; - if (req->rq_pack_bulk) - ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK; - - /* allocate temporary cipher buffer */ - token_buflen = gss_mech_payload(gctx->gsc_mechctx, msglen, 1); - OBD_ALLOC_LARGE(token_buf, token_buflen); - if (token_buf == NULL) - return -ENOMEM; - - hdrobj.len = PTLRPC_GSS_HEADER_SIZE; - hdrobj.data = (__u8 *) ghdr; - msgobj.len = msglen; - msgobj.data = (__u8 *) rs->rs_repbuf; - token.len = token_buflen; - token.data = token_buf; - - major = lgss_wrap(gctx->gsc_mechctx, &hdrobj, &msgobj, - rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE, &token); - if (major != GSS_S_COMPLETE) { - CERROR("wrap message error: %08x\n", major); - GOTO(out_free, rc = -EPERM); - } - LASSERT(token.len <= token_buflen); - - /* we are about to override data at rs->rs_repbuf, nullify pointers - * to which to catch further illegal usage. */ - if (req->rq_pack_bulk) { - grctx->src_repbsd = NULL; - grctx->src_repbsd_size = 0; - } - - /* now fill the actual wire data - * - gss header - * - gss token - */ - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = token.len; - - rs->rs_repdata_len = lustre_msg_size_v2(2, buflens); - LASSERT(rs->rs_repdata_len <= rs->rs_repbuf_len); - - lustre_init_msg_v2(rs->rs_repbuf, 2, buflens, NULL); - rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc; - - memcpy(lustre_msg_buf(rs->rs_repbuf, 0, 0), ghdr, - PTLRPC_GSS_HEADER_SIZE); - memcpy(lustre_msg_buf(rs->rs_repbuf, 1, 0), token.data, token.len); - - /* reply offset */ - if (req->rq_packed_final && - (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT)) - req->rq_reply_off = gss_at_reply_off_priv; - else - req->rq_reply_off = 0; - - /* to catch upper layer's further access */ - rs->rs_msg = NULL; - req->rq_repmsg = NULL; - req->rq_replen = 0; - - rc = 0; -out_free: - OBD_FREE_LARGE(token_buf, token_buflen); - return rc; -} - -int gss_svc_authorize(struct ptlrpc_request *req) -{ - struct ptlrpc_reply_state *rs = req->rq_reply_state; - struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); - struct gss_wire_ctx *gw = &grctx->src_wirectx; - int early, rc; - - early = (req->rq_packed_final == 0); - - if (!early && gss_svc_reqctx_is_special(grctx)) { - LASSERT(rs->rs_repdata_len != 0); - - req->rq_reply_off = gss_at_reply_off_integ; - return 0; - } - - /* early reply could happen in many cases */ - if (!early && - gw->gw_proc != PTLRPC_GSS_PROC_DATA && - gw->gw_proc != PTLRPC_GSS_PROC_DESTROY) { - CERROR("proc %d not support\n", gw->gw_proc); - return -EINVAL; - } - - LASSERT(grctx->src_ctx); - - switch (gw->gw_svc) { - case SPTLRPC_SVC_NULL: - case SPTLRPC_SVC_AUTH: - case SPTLRPC_SVC_INTG: - rc = gss_svc_sign(req, rs, grctx, gw->gw_svc); - break; - case SPTLRPC_SVC_PRIV: - rc = gss_svc_seal(req, rs, grctx); - break; - default: - CERROR("Unknown service %d\n", gw->gw_svc); - GOTO(out, rc = -EINVAL); - } - rc = 0; - -out: - return rc; -} - -void gss_svc_free_rs(struct ptlrpc_reply_state *rs) -{ - struct gss_svc_reqctx *grctx; - - LASSERT(rs->rs_svc_ctx); - grctx = container_of(rs->rs_svc_ctx, struct gss_svc_reqctx, src_base); - - gss_svc_reqctx_decref(grctx); - rs->rs_svc_ctx = NULL; - - if (!rs->rs_prealloc) - OBD_FREE_LARGE(rs, rs->rs_size); -} - -void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx) -{ - LASSERT(atomic_read(&ctx->sc_refcount) == 0); - gss_svc_reqctx_free(gss_svc_ctx2reqctx(ctx)); -} - -int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx, - struct ptlrpc_svc_ctx *svc_ctx) -{ - struct gss_cli_ctx *cli_gctx = ctx2gctx(cli_ctx); - struct gss_svc_ctx *svc_gctx = gss_svc_ctx2gssctx(svc_ctx); - struct gss_ctx *mechctx = NULL; - - LASSERT(cli_gctx); - LASSERT(svc_gctx && svc_gctx->gsc_mechctx); - - cli_gctx->gc_proc = PTLRPC_GSS_PROC_DATA; - cli_gctx->gc_win = GSS_SEQ_WIN; - - /* The problem is the reverse ctx might get lost in some recovery - * situations, and the same svc_ctx will be used to re-create it. - * if there's callback be sentout before that, new reverse ctx start - * with sequence 0 will lead to future callback rpc be treated as - * replay. - * - * each reverse root ctx will record its latest sequence number on its - * buddy svcctx before be destroyed, so here we continue use it. - */ - atomic_set(&cli_gctx->gc_seq, svc_gctx->gsc_rvs_seq); - - if (gss_svc_upcall_dup_handle(&cli_gctx->gc_svc_handle, svc_gctx)) { - CERROR("failed to dup svc handle\n"); - goto err_out; - } - - if (lgss_copy_reverse_context(svc_gctx->gsc_mechctx, &mechctx) != - GSS_S_COMPLETE) { - CERROR("failed to copy mech context\n"); - goto err_svc_handle; - } - - if (rawobj_dup(&cli_gctx->gc_handle, &svc_gctx->gsc_rvs_hdl)) { - CERROR("failed to dup reverse handle\n"); - goto err_ctx; - } - - cli_gctx->gc_mechctx = mechctx; - gss_cli_ctx_uptodate(cli_gctx); - - return 0; - -err_ctx: - lgss_delete_sec_context(&mechctx); -err_svc_handle: - rawobj_free(&cli_gctx->gc_svc_handle); -err_out: - return -ENOMEM; -} - -static void gss_init_at_reply_offset(void) -{ - __u32 buflens[3]; - int clearsize; - - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = lustre_msg_early_size(); - buflens[2] = gss_cli_payload(NULL, buflens[1], 0); - gss_at_reply_off_integ = lustre_msg_size_v2(3, buflens); - - buflens[0] = lustre_msg_early_size(); - clearsize = lustre_msg_size_v2(1, buflens); - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(NULL, clearsize, 0); - buflens[2] = gss_cli_payload(NULL, clearsize, 1); - gss_at_reply_off_priv = lustre_msg_size_v2(3, buflens); -} - -int __init sptlrpc_gss_init(void) -{ - int rc; - - rc = gss_init_lproc(); - if (rc) - return rc; - - rc = gss_init_cli_upcall(); - if (rc) - goto out_lproc; - - rc = gss_init_svc_upcall(); - if (rc) - goto out_cli_upcall; - - rc = init_kerberos_module(); - if (rc) - goto out_svc_upcall; - - /* register policy after all other stuff be initialized, because it - * might be in used immediately after the registration. */ - - rc = gss_init_keyring(); - if (rc) - goto out_kerberos; - -#ifdef HAVE_GSS_PIPEFS - rc = gss_init_pipefs(); - if (rc) - goto out_keyring; -#endif - - gss_init_at_reply_offset(); - - return 0; - -#ifdef HAVE_GSS_PIPEFS -out_keyring: - gss_exit_keyring(); -#endif - -out_kerberos: - cleanup_kerberos_module(); -out_svc_upcall: - gss_exit_svc_upcall(); -out_cli_upcall: - gss_exit_cli_upcall(); -out_lproc: - gss_exit_lproc(); - return rc; -} - -static void __exit sptlrpc_gss_exit(void) -{ - gss_exit_keyring(); -#ifdef HAVE_GSS_PIPEFS - gss_exit_pipefs(); -#endif - cleanup_kerberos_module(); - gss_exit_svc_upcall(); - gss_exit_cli_upcall(); - gss_exit_lproc(); -} - -MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>"); -MODULE_DESCRIPTION("GSS security policy for Lustre"); -MODULE_LICENSE("GPL"); - -module_init(sptlrpc_gss_init); -module_exit(sptlrpc_gss_exit); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 8573f328bd2a..f522fc5d3a93 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -40,14 +40,14 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <lustre_ha.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_export.h> -#include <obd.h> -#include <obd_cksum.h> -#include <obd_class.h> +#include "../include/obd_support.h" +#include "../include/lustre_ha.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_export.h" +#include "../include/obd.h" +#include "../include/obd_cksum.h" +#include "../include/obd_class.h" #include "ptlrpc_internal.h" @@ -66,7 +66,7 @@ static void __import_set_state(struct obd_import *imp, imp->imp_state = state; imp->imp_state_hist[imp->imp_state_hist_idx].ish_state = state; imp->imp_state_hist[imp->imp_state_hist_idx].ish_time = - cfs_time_current_sec(); + get_seconds(); imp->imp_state_hist_idx = (imp->imp_state_hist_idx + 1) % IMP_STATE_HIST_LEN; } @@ -242,7 +242,7 @@ ptlrpc_inflight_deadline(struct ptlrpc_request *req, time_t now) static unsigned int ptlrpc_inflight_timeout(struct obd_import *imp) { - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); struct list_head *tmp, *n; struct ptlrpc_request *req; unsigned int timeout = 0; @@ -275,6 +275,7 @@ void ptlrpc_invalidate_import(struct obd_import *imp) if (!imp->imp_invalid || imp->imp_obd->obd_no_recov) ptlrpc_deactivate_import(imp); + CFS_FAIL_TIMEOUT(OBD_FAIL_MGS_CONNECT_NET, 3 * cfs_fail_val / 2); LASSERT(imp->imp_invalid); /* Wait forever until inflight == 0. We really can't do it another @@ -392,6 +393,19 @@ void ptlrpc_activate_import(struct obd_import *imp) } EXPORT_SYMBOL(ptlrpc_activate_import); +static void ptlrpc_pinger_force(struct obd_import *imp) +{ + CDEBUG(D_HA, "%s: waking up pinger s:%s\n", obd2cli_tgt(imp->imp_obd), + ptlrpc_import_state_name(imp->imp_state)); + + spin_lock(&imp->imp_lock); + imp->imp_force_verify = 1; + spin_unlock(&imp->imp_lock); + + if (imp->imp_state != LUSTRE_IMP_CONNECTING) + ptlrpc_pinger_wake_up(); +} + void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) { LASSERT(!imp->imp_dlm_fake); @@ -406,20 +420,30 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) ptlrpc_deactivate_import(imp); } - CDEBUG(D_HA, "%s: waking up pinger\n", - obd2cli_tgt(imp->imp_obd)); - - spin_lock(&imp->imp_lock); - imp->imp_force_verify = 1; - spin_unlock(&imp->imp_lock); - - ptlrpc_pinger_wake_up(); + ptlrpc_pinger_force(imp); } } EXPORT_SYMBOL(ptlrpc_fail_import); int ptlrpc_reconnect_import(struct obd_import *imp) { +#ifdef ENABLE_PINGER + struct l_wait_info lwi; + int secs = cfs_time_seconds(obd_timeout); + int rc; + + ptlrpc_pinger_force(imp); + + CDEBUG(D_HA, "%s: recovery started, waiting %u seconds\n", + obd2cli_tgt(imp->imp_obd), secs); + + lwi = LWI_TIMEOUT(secs, NULL, NULL); + rc = l_wait_event(imp->imp_recovery_waitq, + !ptlrpc_import_in_recovery(imp), &lwi); + CDEBUG(D_HA, "%s: recovery finished s:%s\n", obd2cli_tgt(imp->imp_obd), + ptlrpc_import_state_name(imp->imp_state)); + return rc; +#else ptlrpc_set_import_discon(imp, 0); /* Force a new connect attempt */ ptlrpc_invalidate_import(imp); @@ -444,6 +468,7 @@ int ptlrpc_reconnect_import(struct obd_import *imp) /* Attempt a new connect */ ptlrpc_recover_import(imp, NULL, 0); return 0; +#endif } EXPORT_SYMBOL(ptlrpc_reconnect_import); @@ -469,7 +494,7 @@ static int import_select_connection(struct obd_import *imp) } list_for_each_entry(conn, &imp->imp_conn_list, oic_item) { - CDEBUG(D_HA, "%s: connect to NID %s last attempt "LPU64"\n", + CDEBUG(D_HA, "%s: connect to NID %s last attempt %llu\n", imp->imp_obd->obd_name, libcfs_nid2str(conn->oic_conn->c_peer.nid), conn->oic_last_attempt); @@ -817,8 +842,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, /* check that server granted subset of flags we asked for. */ if ((ocd->ocd_connect_flags & imp->imp_connect_flags_orig) != ocd->ocd_connect_flags) { - CERROR("%s: Server didn't granted asked subset of flags: " - "asked="LPX64" grranted="LPX64"\n", + CERROR("%s: Server didn't granted asked subset of flags: asked=%#llx grranted=%#llx\n", imp->imp_obd->obd_name,imp->imp_connect_flags_orig, ocd->ocd_connect_flags); GOTO(out, rc = -EPROTO); @@ -876,8 +900,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, memset(&old_hdl, 0, sizeof(old_hdl)); if (!memcmp(&old_hdl, lustre_msg_get_handle(request->rq_repmsg), sizeof(old_hdl))) { - LCONSOLE_WARN("Reconnect to %s (at @%s) failed due " - "bad handle "LPX64"\n", + LCONSOLE_WARN("Reconnect to %s (at @%s) failed due bad handle %#llx\n", obd2cli_tgt(imp->imp_obd), imp->imp_connection->c_remote_uuid.uuid, imp->imp_dlm_handle.cookie); @@ -898,9 +921,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, * participate since we can reestablish all of our state * with server again */ if ((MSG_CONNECT_RECOVERING & msg_flags)) { - CDEBUG(level,"%s@%s changed server handle from " - LPX64" to "LPX64 - " but is still in recovery\n", + CDEBUG(level,"%s@%s changed server handle from %#llx to %#llx but is still in recovery\n", obd2cli_tgt(imp->imp_obd), imp->imp_connection->c_remote_uuid.uuid, imp->imp_remote_handle.cookie, @@ -908,8 +929,7 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, request->rq_repmsg)->cookie); } else { LCONSOLE_WARN("Evicted from %s (at %s) " - "after server handle changed from " - LPX64" to "LPX64"\n", + "after server handle changed from %#llx to %#llx\n", obd2cli_tgt(imp->imp_obd), imp->imp_connection-> \ c_remote_uuid.uuid, @@ -973,8 +993,8 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, if (lustre_msg_get_last_committed(request->rq_repmsg) > 0 && lustre_msg_get_last_committed(request->rq_repmsg) < aa->pcaa_peer_committed) { - CERROR("%s went back in time (transno "LPD64 - " was previously committed, server now claims "LPD64 + CERROR("%s went back in time (transno %lld" + " was previously committed, server now claims %lld" ")! See https://bugzilla.lustre.org/show_bug.cgi?" "id=9646\n", obd2cli_tgt(imp->imp_obd), aa->pcaa_peer_committed, @@ -1092,9 +1112,8 @@ finish: * disable lru_resize, etc. */ if (old_connect_flags != exp_connect_flags(exp) || aa->pcaa_initial_connect) { - CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server " - "flags: "LPX64"\n", imp->imp_obd->obd_name, - ocd->ocd_connect_flags); + CDEBUG(D_HA, "%s: Resetting ns_connect_flags to server flags: %#llx\n", + imp->imp_obd->obd_name, ocd->ocd_connect_flags); imp->imp_obd->obd_namespace->ns_connect_flags = ocd->ocd_connect_flags; imp->imp_obd->obd_namespace->ns_orig_connect_flags = @@ -1429,7 +1448,7 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) if (ptlrpc_import_in_recovery(imp)) { struct l_wait_info lwi; - cfs_duration_t timeout; + long timeout; if (AT_OFF) { if (imp->imp_server_timeout) @@ -1512,7 +1531,7 @@ extern unsigned int at_min, at_max, at_history; int at_measured(struct adaptive_timeout *at, unsigned int val) { unsigned int old = at->at_current; - time_t now = cfs_time_current_sec(); + time_t now = get_seconds(); time_t binlimit = max_t(time_t, at_history / AT_BINS, 1); LASSERT(at); diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 41c12e00129f..511cb9cbf0d4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -53,21 +53,21 @@ #include <linux/module.h> /* LUSTRE_VERSION_CODE */ -#include <lustre_ver.h> +#include "../include/lustre_ver.h" -#include <obd_support.h> +#include "../include/obd_support.h" /* lustre_swab_mdt_body */ -#include <lustre/lustre_idl.h> +#include "../include/lustre/lustre_idl.h" /* obd2cli_tgt() (required by DEBUG_REQ()) */ -#include <obd.h> +#include "../include/obd.h" /* __REQ_LAYOUT_USER__ */ #endif /* struct ptlrpc_request, lustre_msg* */ -#include <lustre_req_layout.h> -#include <lustre_update.h> -#include <lustre_acl.h> -#include <lustre_debug.h> +#include "../include/lustre_req_layout.h" +#include "../include/lustre_update.h" +#include "../include/lustre_acl.h" +#include "../include/lustre_debug.h" /* * RQFs (see below) refer to two struct req_msg_field arrays describing the diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c index ab084541fddb..6a1ab5c98bc6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c @@ -42,11 +42,11 @@ #define DEBUG_SUBSYSTEM S_LOG -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" -#include <obd_class.h> -#include <lustre_log.h> -#include <lustre_net.h> +#include "../include/obd_class.h" +#include "../include/lustre_log.h" +#include "../include/lustre_net.h" #include <linux/list.h> #define LLOG_CLIENT_ENTRY(ctxt, imp) do { \ diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c index 17c06a32df62..e9052bba6692 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c @@ -46,13 +46,13 @@ #define DEBUG_SUBSYSTEM S_LOG -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" -#include <obd_class.h> -#include <lustre_log.h> +#include "../include/obd_class.h" +#include "../include/lustre_log.h" #include <linux/list.h> -#include <lvfs.h> -#include <lustre_fsfilt.h> +#include "../include/lvfs.h" +#include "../include/lustre_fsfilt.h" int llog_initiator_connect(struct llog_ctxt *ctxt) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 6b9c6db1f2df..bc220308e7d7 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -36,12 +36,12 @@ #define DEBUG_SUBSYSTEM S_CLASS -#include <obd_support.h> -#include <obd.h> -#include <lprocfs_status.h> -#include <lustre/lustre_idl.h> -#include <lustre_net.h> -#include <obd_class.h> +#include "../include/obd_support.h" +#include "../include/obd.h" +#include "../include/lprocfs_status.h" +#include "../include/lustre/lustre_idl.h" +#include "../include/lustre_net.h" +#include "../include/obd_class.h" #include "ptlrpc_internal.h" @@ -180,7 +180,7 @@ const char* ll_eopcode2str(__u32 opcode) LASSERT(ll_eopcode_table[opcode].opcode == opcode); return ll_eopcode_table[opcode].opname; } -#ifdef LPROCFS +#if defined (CONFIG_PROC_FS) void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, char *name, struct proc_dir_entry **procroot_ret, struct lprocfs_stats **stats_ret) @@ -628,7 +628,8 @@ out: * if the optional token is omitted, the operation is performed on both the * regular and high-priority (if the service has one) NRS head. */ -static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, const char *buffer, +static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, + const char __user *buffer, size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; @@ -726,12 +727,12 @@ ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt, * be near the head), we shouldn't have to do long * re-scans */ LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq, - "%s:%d: seek seq "LPU64", request seq "LPU64"\n", + "%s:%d: seek seq %llu, request seq %llu\n", svcpt->scp_service->srv_name, svcpt->scp_cpt, srhi->srhi_seq, srhi->srhi_req->rq_history_seq); LASSERTF(!list_empty(&svcpt->scp_hist_reqs), - "%s:%d: seek offset "LPU64", request seq "LPU64", " - "last culled "LPU64"\n", + "%s:%d: seek offset %llu, request seq %llu, " + "last culled %llu\n", svcpt->scp_service->srv_name, svcpt->scp_cpt, seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled); e = &srhi->srhi_req->rq_history_list; @@ -932,7 +933,7 @@ static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter) * must be just as careful as the service's request * parser. Currently I only print stuff here I know is OK * to look at coz it was set up in request_in_callback()!!! */ - seq_printf(s, LPD64":%s:%s:x"LPU64":%d:%s:%ld:%lds(%+lds) ", + seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%ld:%lds(%+lds) ", req->rq_history_seq, libcfs_nid2str(req->rq_self), libcfs_id2str(req->rq_peer), req->rq_xid, req->rq_reqlen, ptlrpc_rqphase2str(req), @@ -991,7 +992,7 @@ static int ptlrpc_lprocfs_timeouts_seq_show(struct seq_file *m, void *n) cur = at_get(&svcpt->scp_at_estimate); worst = svcpt->scp_at_estimate.at_worst_ever; worstt = svcpt->scp_at_estimate.at_worst_time; - s2dhms(&ts, cfs_time_current_sec() - worstt); + s2dhms(&ts, get_seconds() - worstt); seq_printf(m, "%10s : cur %3u worst %3u (at %ld, " DHMS_FMT" ago) ", "service", @@ -1339,4 +1340,4 @@ int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, } EXPORT_SYMBOL(lprocfs_wr_pinger_recov); -#endif /* LPROCFS */ +#endif /* CONFIG_PROC_FS */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index a47a8d807d5b..89fc7f77b498 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -35,11 +35,11 @@ */ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <lustre_net.h> -#include <lustre_lib.h> -#include <obd.h> -#include <obd_class.h> +#include "../include/obd_support.h" +#include "../include/lustre_net.h" +#include "../include/lustre_lib.h" +#include "../include/obd.h" +#include "../include/obd_class.h" #include "ptlrpc_internal.h" /** @@ -79,7 +79,7 @@ static int ptl_send_buf(lnet_handle_md_t *mdh, void *base, int len, return -ENOMEM; } - CDEBUG(D_NET, "Sending %d bytes to portal %d, xid "LPD64", offset %u\n", + CDEBUG(D_NET, "Sending %d bytes to portal %d, xid %lld, offset %u\n", len, portal, xid, offset); rc = LNetPut(conn->c_self, *mdh, ack, @@ -89,7 +89,7 @@ static int ptl_send_buf(lnet_handle_md_t *mdh, void *base, int len, /* We're going to get an UNLINK event when I unlink below, * which will complete just like any other failed send, so * I fall through and return success here! */ - CERROR("LNetPut(%s, %d, "LPD64") failed: %d\n", + CERROR("LNetPut(%s, %d, %lld) failed: %d\n", libcfs_id2str(conn->c_peer), portal, xid, rc); rc2 = LNetMDUnlink(*mdh); LASSERTF(rc2 == 0, "rc2 = %d\n", rc2); @@ -159,7 +159,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) LASSERTF(!(desc->bd_registered && req->rq_send_state != LUSTRE_IMP_REPLAY) || xid != desc->bd_last_xid, - "registered: %d rq_xid: "LPU64" bd_last_xid: "LPU64"\n", + "registered: %d rq_xid: %llu bd_last_xid: %llu\n", desc->bd_registered, xid, desc->bd_last_xid); total_md = (desc->bd_iov_count + LNET_MAX_IOV - 1) / LNET_MAX_IOV; @@ -179,7 +179,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) rc = LNetMEAttach(desc->bd_portal, peer, xid, 0, LNET_UNLINK, LNET_INS_AFTER, &me_h); if (rc != 0) { - CERROR("%s: LNetMEAttach failed x"LPU64"/%d: rc = %d\n", + CERROR("%s: LNetMEAttach failed x%llu/%d: rc = %d\n", desc->bd_import->imp_obd->obd_name, xid, posted_md, rc); break; @@ -189,7 +189,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) rc = LNetMDAttach(me_h, md, LNET_UNLINK, &desc->bd_mds[posted_md]); if (rc != 0) { - CERROR("%s: LNetMDAttach failed x"LPU64"/%d: rc = %d\n", + CERROR("%s: LNetMDAttach failed x%llu/%d: rc = %d\n", desc->bd_import->imp_obd->obd_name, xid, posted_md, rc); rc2 = LNetMEUnlink(me_h); @@ -213,7 +213,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) * infer the number of bulks that were prepared */ req->rq_xid = --xid; LASSERTF(desc->bd_last_xid == (req->rq_xid & PTLRPC_BULK_OPS_MASK), - "bd_last_xid = x"LPU64", rq_xid = x"LPU64"\n", + "bd_last_xid = x%llu, rq_xid = x%llu\n", desc->bd_last_xid, req->rq_xid); spin_lock(&desc->bd_lock); @@ -225,7 +225,7 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) spin_unlock(&desc->bd_lock); CDEBUG(D_NET, "Setup %u bulk %s buffers: %u pages %u bytes, " - "xid x"LPX64"-"LPX64", portal %u\n", desc->bd_md_count, + "xid x%#llx-%#llx, portal %u\n", desc->bd_md_count, desc->bd_type == BULK_GET_SOURCE ? "get-source" : "put-sink", desc->bd_iov_count, desc->bd_nob, desc->bd_last_xid, req->rq_xid, desc->bd_portal); @@ -252,7 +252,7 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) /* Let's setup deadline for reply unlink. */ if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_BULK_UNLINK) && async && req->rq_bulk_deadline == 0) - req->rq_bulk_deadline = cfs_time_current_sec() + LONG_UNLINK; + req->rq_bulk_deadline = get_seconds() + LONG_UNLINK; if (ptlrpc_client_bulk_active(req) == 0) /* completed or */ return 1; /* never registered */ @@ -303,7 +303,7 @@ static void ptlrpc_at_set_reply(struct ptlrpc_request *req, int flags) { struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt; struct ptlrpc_service *svc = svcpt->scp_service; - int service_time = max_t(int, cfs_time_current_sec() - + int service_time = max_t(int, get_seconds() - req->rq_arrival_time.tv_sec, 1); if (!(flags & PTLRPC_REPLY_EARLY) && @@ -422,7 +422,7 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) if (unlikely(rc)) goto out; - req->rq_sent = cfs_time_current_sec(); + req->rq_sent = get_seconds(); rc = ptl_send_buf(&rs->rs_md_h, rs->rs_repbuf, rs->rs_repdata_len, (rs->rs_difficult && !rs->rs_no_ack) ? @@ -505,11 +505,12 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) /* If this is a re-transmit, we're required to have disengaged * cleanly from the previous attempt */ LASSERT(!request->rq_receiving_reply); + LASSERT(!((lustre_msg_get_flags(request->rq_reqmsg) & MSG_REPLAY) && + (request->rq_import->imp_state == LUSTRE_IMP_FULL))); - if (request->rq_import->imp_obd && - request->rq_import->imp_obd->obd_fail) { + if (unlikely(obd != NULL && obd->obd_fail)) { CDEBUG(D_HA, "muting rpc for failed imp obd %s\n", - request->rq_import->imp_obd->obd_name); + obd->obd_name); /* this prevents us from waiting in ptlrpc_queue_wait */ spin_lock(&request->rq_lock); request->rq_err = 1; @@ -579,8 +580,9 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) spin_lock(&request->rq_lock); /* If the MD attach succeeds, there _will_ be a reply_in callback */ request->rq_receiving_reply = !noreply; + request->rq_req_unlink = 1; /* We are responsible for unlinking the reply buffer */ - request->rq_must_unlink = !noreply; + request->rq_reply_unlink = !noreply; /* Clear any flags that may be present from previous sends. */ request->rq_replied = 0; request->rq_err = 0; @@ -603,7 +605,7 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) reply_md.user_ptr = &request->rq_reply_cbid; reply_md.eq_handle = ptlrpc_eq_h; - /* We must see the unlink callback to unset rq_must_unlink, + /* We must see the unlink callback to unset rq_reply_unlink, so we can't auto-unlink */ rc = LNetMDAttach(reply_me_h, reply_md, LNET_RETAIN, &request->rq_reply_md_h); @@ -617,22 +619,21 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) GOTO(cleanup_me, rc = -ENOMEM); } - CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid "LPU64 - ", portal %u\n", + CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid %llu, portal %u\n", request->rq_repbuf_len, request->rq_xid, request->rq_reply_portal); } /* add references on request for request_out_callback */ ptlrpc_request_addref(request); - if (obd->obd_svc_stats != NULL) + if (obd != NULL && obd->obd_svc_stats != NULL) lprocfs_counter_add(obd->obd_svc_stats, PTLRPC_REQACTIVE_CNTR, atomic_read(&request->rq_import->imp_inflight)); OBD_FAIL_TIMEOUT(OBD_FAIL_PTLRPC_DELAY_SEND, request->rq_timeout + 5); do_gettimeofday(&request->rq_arrival_time); - request->rq_sent = cfs_time_current_sec(); + request->rq_sent = get_seconds(); /* We give the server rq_timeout secs to process the req, and add the network latency for our local timeout. */ request->rq_deadline = request->rq_sent + request->rq_timeout + diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 12151aa2a1e5..9ea24f8d9865 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -40,11 +40,11 @@ */ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lprocfs_status.h> -#include <linux/libcfs/libcfs.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lprocfs_status.h" +#include "../../include/linux/libcfs/libcfs.h" #include "ptlrpc_internal.h" /* XXX: This is just for liblustre. Remove the #if defined directive when the diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c b/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c index 7d3ee9706c9b..28363307ee35 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c @@ -47,9 +47,9 @@ */ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <linux/libcfs/libcfs.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../../include/linux/libcfs/libcfs.h" #include "ptlrpc_internal.h" /** @@ -174,9 +174,9 @@ struct ptlrpc_nrs_request * nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy, list_del_init(&nrq->nr_u.fifo.fr_list); - CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: "LPU64 - "\n", policy->pol_desc->pd_name, - libcfs_id2str(req->rq_peer), nrq->nr_u.fifo.fr_sequence); + CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: %llu\n", + policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer), + nrq->nr_u.fifo.fr_sequence); } return nrq; @@ -236,7 +236,7 @@ static void nrs_fifo_req_stop(struct ptlrpc_nrs_policy *policy, struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request, rq_nrq); - CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: "LPU64"\n", + CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n", policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer), nrq->nr_u.fifo.fr_sequence); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index cddeeb6bb23d..ac562932ccdf 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -44,13 +44,13 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <obd_cksum.h> -#include <lustre/ll_fiemap.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/obd_cksum.h" +#include "../include/lustre/ll_fiemap.h" static inline int lustre_msg_hdr_size_v2(int count) { @@ -2140,8 +2140,8 @@ static void print_lum(struct lov_user_md *lum) CDEBUG(D_OTHER, "lov_user_md %p:\n", lum); CDEBUG(D_OTHER, "\tlmm_magic: %#x\n", lum->lmm_magic); CDEBUG(D_OTHER, "\tlmm_pattern: %#x\n", lum->lmm_pattern); - CDEBUG(D_OTHER, "\tlmm_object_id: "LPU64"\n", lmm_oi_id(&lum->lmm_oi)); - CDEBUG(D_OTHER, "\tlmm_object_gr: "LPU64"\n", lmm_oi_seq(&lum->lmm_oi)); + CDEBUG(D_OTHER, "\tlmm_object_id: %llu\n", lmm_oi_id(&lum->lmm_oi)); + CDEBUG(D_OTHER, "\tlmm_object_gr: %llu\n", lmm_oi_seq(&lum->lmm_oi)); CDEBUG(D_OTHER, "\tlmm_stripe_size: %#x\n", lum->lmm_stripe_size); CDEBUG(D_OTHER, "\tlmm_stripe_count: %#x\n", lum->lmm_stripe_count); CDEBUG(D_OTHER, "\tlmm_stripe_offset/lmm_layout_gen: %#x\n", @@ -2292,7 +2292,7 @@ EXPORT_SYMBOL(dump_ioo); void dump_rniobuf(struct niobuf_remote *nb) { - CDEBUG(D_RPCTRACE, "niobuf_remote: offset="LPU64", len=%d, flags=%x\n", + CDEBUG(D_RPCTRACE, "niobuf_remote: offset=%llu, len=%d, flags=%x\n", nb->offset, nb->len, nb->flags); } EXPORT_SYMBOL(dump_rniobuf); @@ -2305,20 +2305,20 @@ void dump_obdo(struct obdo *oa) if (valid & OBD_MD_FLID) CDEBUG(D_RPCTRACE, "obdo: id = "DOSTID"\n", POSTID(&oa->o_oi)); if (valid & OBD_MD_FLFID) - CDEBUG(D_RPCTRACE, "obdo: o_parent_seq = "LPX64"\n", + CDEBUG(D_RPCTRACE, "obdo: o_parent_seq = %#llx\n", oa->o_parent_seq); if (valid & OBD_MD_FLSIZE) - CDEBUG(D_RPCTRACE, "obdo: o_size = "LPD64"\n", oa->o_size); + CDEBUG(D_RPCTRACE, "obdo: o_size = %lld\n", oa->o_size); if (valid & OBD_MD_FLMTIME) - CDEBUG(D_RPCTRACE, "obdo: o_mtime = "LPD64"\n", oa->o_mtime); + CDEBUG(D_RPCTRACE, "obdo: o_mtime = %lld\n", oa->o_mtime); if (valid & OBD_MD_FLATIME) - CDEBUG(D_RPCTRACE, "obdo: o_atime = "LPD64"\n", oa->o_atime); + CDEBUG(D_RPCTRACE, "obdo: o_atime = %lld\n", oa->o_atime); if (valid & OBD_MD_FLCTIME) - CDEBUG(D_RPCTRACE, "obdo: o_ctime = "LPD64"\n", oa->o_ctime); + CDEBUG(D_RPCTRACE, "obdo: o_ctime = %lld\n", oa->o_ctime); if (valid & OBD_MD_FLBLOCKS) /* allocation of space */ - CDEBUG(D_RPCTRACE, "obdo: o_blocks = "LPD64"\n", oa->o_blocks); + CDEBUG(D_RPCTRACE, "obdo: o_blocks = %lld\n", oa->o_blocks); if (valid & OBD_MD_FLGRANT) - CDEBUG(D_RPCTRACE, "obdo: o_grant = "LPD64"\n", oa->o_grant); + CDEBUG(D_RPCTRACE, "obdo: o_grant = %lld\n", oa->o_grant); if (valid & OBD_MD_FLBLKSZ) CDEBUG(D_RPCTRACE, "obdo: o_blksize = %d\n", oa->o_blksize); if (valid & (OBD_MD_FLTYPE | OBD_MD_FLMODE)) @@ -2344,7 +2344,7 @@ void dump_obdo(struct obdo *oa) CDEBUG(D_RPCTRACE, "obdo: o_parent_oid = %x\n", oa->o_parent_oid); if (valid & OBD_MD_FLEPOCH) - CDEBUG(D_RPCTRACE, "obdo: o_ioepoch = "LPD64"\n", + CDEBUG(D_RPCTRACE, "obdo: o_ioepoch = %lld\n", oa->o_ioepoch); if (valid & OBD_MD_FLFID) { CDEBUG(D_RPCTRACE, "obdo: o_stripe_idx = %u\n", @@ -2353,7 +2353,7 @@ void dump_obdo(struct obdo *oa) oa->o_parent_ver); } if (valid & OBD_MD_FLHANDLE) - CDEBUG(D_RPCTRACE, "obdo: o_handle = "LPD64"\n", + CDEBUG(D_RPCTRACE, "obdo: o_handle = %lld\n", oa->o_handle.cookie); if (valid & OBD_MD_FLCOOKIE) CDEBUG(D_RPCTRACE, "obdo: o_lcookie = " @@ -2421,7 +2421,7 @@ void _debug_req(struct ptlrpc_request *req, va_start(args, fmt); libcfs_debug_vmsg2(msgdata, fmt, args, - " req@%p x"LPU64"/t"LPD64"("LPD64") o%d->%s@%s:%d/%d" + " req@%p x%llu/t%lld(%lld) o%d->%s@%s:%d/%d" " lens %d/%d e %d to %d dl "CFS_TIME_T" ref %d " "fl "REQ_FLAGS_FMT"/%x/%x rc %d/%d\n", req, req->rq_xid, req->rq_transno, diff --git a/drivers/staging/lustre/lustre/ptlrpc/pers.c b/drivers/staging/lustre/lustre/ptlrpc/pers.c index d926d2b36fb4..e1334c24ebe3 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pers.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pers.c @@ -34,11 +34,11 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_lib.h> -#include <lustre_ha.h> -#include <lustre_import.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_lib.h" +#include "../include/lustre_ha.h" +#include "../include/lustre_import.h" #include "ptlrpc_internal.h" diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 38099d9dfdae..5e4e49fab63c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -40,8 +40,8 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" #include "ptlrpc_internal.h" static int suppress_pings; @@ -141,10 +141,10 @@ static inline int ptlrpc_next_reconnect(struct obd_import *imp) return cfs_time_shift(obd_timeout); } -cfs_duration_t pinger_check_timeout(cfs_time_t time) +long pinger_check_timeout(unsigned long time) { struct timeout_item *item; - cfs_time_t timeout = PING_INTERVAL; + unsigned long timeout = PING_INTERVAL; /* The timeout list is a increase order sorted list */ mutex_lock(&pinger_mutex); @@ -224,6 +224,11 @@ static void ptlrpc_pinger_process_import(struct obd_import *imp, "or recovery disabled: %s)\n", imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd), ptlrpc_import_state_name(level)); + if (force) { + spin_lock(&imp->imp_lock); + imp->imp_force_verify = 1; + spin_unlock(&imp->imp_lock); + } } else if ((imp->imp_pingable && !suppress) || force_next || force) { ptlrpc_ping(imp); } @@ -239,9 +244,9 @@ static int ptlrpc_pinger_main(void *arg) /* And now, loop forever, pinging as needed. */ while (1) { - cfs_time_t this_ping = cfs_time_current(); + unsigned long this_ping = cfs_time_current(); struct l_wait_info lwi; - cfs_duration_t time_to_next_wake; + long time_to_next_wake; struct timeout_item *item; struct list_head *iter; @@ -278,8 +283,7 @@ static int ptlrpc_pinger_main(void *arg) CFS_TIME_T")\n", time_to_next_wake, cfs_time_add(this_ping,cfs_time_seconds(PING_INTERVAL))); if (time_to_next_wake > 0) { - lwi = LWI_TIMEOUT(max_t(cfs_duration_t, - time_to_next_wake, + lwi = LWI_TIMEOUT(max_t(long, time_to_next_wake, cfs_time_seconds(1)), NULL, NULL); l_wait_event(thread->t_ctl_waitq, @@ -601,7 +605,7 @@ static int ping_evictor_main(void *arg) obd_evict_list); spin_unlock(&pet_lock); - expire_time = cfs_time_current_sec() - PING_EVICT_TIMEOUT; + expire_time = get_seconds() - PING_EVICT_TIMEOUT; CDEBUG(D_HA, "evicting all exports of obd %s older than %ld\n", obd->obd_name, expire_time); @@ -626,9 +630,9 @@ static int ping_evictor_main(void *arg) obd->obd_name, obd_uuid2str(&exp->exp_client_uuid), obd_export_nid2str(exp), - (long)(cfs_time_current_sec() - + (long)(get_seconds() - exp->exp_last_request_time), - exp, (long)cfs_time_current_sec(), + exp, (long)get_seconds(), (long)expire_time, (long)exp->exp_last_request_time); CDEBUG(D_HA, "Last request was at %ld\n", diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index 7c9405530596..f7be007c88cb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -76,7 +76,7 @@ void ptlrpc_initiate_recovery(struct obd_import *imp); int lustre_unpack_req_ptlrpc_body(struct ptlrpc_request *req, int offset); int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset); -#ifdef LPROCFS +#if defined (CONFIG_PROC_FS) void ptlrpc_lprocfs_register_service(struct proc_dir_entry *proc_entry, struct ptlrpc_service *svc); void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc); @@ -88,7 +88,7 @@ void ptlrpc_lprocfs_do_request_stat(struct ptlrpc_request *req, #define ptlrpc_lprocfs_unregister_service(params...) do {} while (0) #define ptlrpc_lprocfs_rpc_sent(params...) do {} while (0) #define ptlrpc_lprocfs_do_request_stat(params...) do {} while (0) -#endif /* LPROCFS */ +#endif /* CONFIG_PROC_FS */ /* NRS */ @@ -263,7 +263,7 @@ void sptlrpc_enc_pool_fini(void); int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v); /* sec_lproc.c */ -#ifdef LPROCFS +#if defined (CONFIG_PROC_FS) int sptlrpc_lproc_init(void); void sptlrpc_lproc_fini(void); #else diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c index 251ae75c2dd9..6d92a56da620 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c @@ -37,10 +37,10 @@ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_req_layout.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_req_layout.h" #include "ptlrpc_internal.h" diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index ca734ce079c1..9c60e2af43bf 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -55,16 +55,15 @@ #define DEBUG_SUBSYSTEM S_RPC -# include <linux/libcfs/libcfs.h> - -#include <lustre_net.h> -# include <lustre_lib.h> - -#include <lustre_ha.h> -#include <obd_class.h> /* for obd_zombie */ -#include <obd_support.h> /* for OBD_FAIL_CHECK */ -#include <cl_object.h> /* cl_env_{get,put}() */ -#include <lprocfs_status.h> +#include "../../include/linux/libcfs/libcfs.h" + +#include "../include/lustre_net.h" +#include "../include/lustre_lib.h" +#include "../include/lustre_ha.h" +#include "../include/obd_class.h" /* for obd_zombie */ +#include "../include/obd_support.h" /* for OBD_FAIL_CHECK */ +#include "../include/cl_object.h" /* cl_env_{get,put}() */ +#include "../include/lprocfs_status.h" #include "ptlrpc_internal.h" diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 9cec8a649dc3..5e4a1a52e0da 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -39,16 +39,16 @@ */ #define DEBUG_SUBSYSTEM S_RPC -# include <linux/libcfs/libcfs.h> - -#include <obd_support.h> -#include <lustre_ha.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_export.h> -#include <obd.h> -#include <obd_ost.h> -#include <obd_class.h> +#include "../../include/linux/libcfs/libcfs.h" + +#include "../include/obd_support.h" +#include "../include/lustre_ha.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_export.h" +#include "../include/obd.h" +#include "../include/obd_ost.h" +#include "../include/obd_class.h" #include <linux/list.h> #include "ptlrpc_internal.h" @@ -85,7 +85,7 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight) last_transno = imp->imp_last_replay_transno; spin_unlock(&imp->imp_lock); - CDEBUG(D_HA, "import %p from %s committed "LPU64" last "LPU64"\n", + CDEBUG(D_HA, "import %p from %s committed %llu last %llu\n", imp, obd2cli_tgt(imp->imp_obd), imp->imp_peer_committed_transno, last_transno); @@ -164,8 +164,8 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight) if (req != NULL) { rc = ptlrpc_replay_req(req); if (rc) { - CERROR("recovery replay error %d for req " - LPU64"\n", rc, req->rq_xid); + CERROR("recovery replay error %d for req %llu\n", + rc, req->rq_xid); return rc; } *inflight = 1; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 28ac824a73fb..5cff7ee6ee7b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -40,17 +40,17 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" #include <linux/crypto.h> #include <linux/key.h> -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_dlm.h> -#include <lustre_sec.h> +#include "../include/obd.h" +#include "../include/obd_class.h" +#include "../include/obd_support.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_dlm.h" +#include "../include/lustre_sec.h" #include "ptlrpc_internal.h" @@ -305,8 +305,8 @@ EXPORT_SYMBOL(sptlrpc_cli_ctx_put); */ void sptlrpc_cli_ctx_expire(struct ptlrpc_cli_ctx *ctx) { - LASSERT(ctx->cc_ops->die); - ctx->cc_ops->die(ctx, 0); + LASSERT(ctx->cc_ops->force_die); + ctx->cc_ops->force_die(ctx, 0); } EXPORT_SYMBOL(sptlrpc_cli_ctx_expire); @@ -344,7 +344,7 @@ static int import_sec_check_expire(struct obd_import *imp) spin_lock(&imp->imp_lock); if (imp->imp_sec_expire && - imp->imp_sec_expire < cfs_time_current_sec()) { + imp->imp_sec_expire < get_seconds()) { adapt = 1; imp->imp_sec_expire = 0; } @@ -591,7 +591,7 @@ int ctx_refresh_timeout(void *data) * later than the context refresh expire time. */ if (rc == 0) - req->rq_cli_ctx->cc_ops->die(req->rq_cli_ctx, 0); + req->rq_cli_ctx->cc_ops->force_die(req->rq_cli_ctx, 0); return rc; } @@ -992,7 +992,7 @@ static int do_cli_unwrap_reply(struct ptlrpc_request *req) case 0: break; default: - CERROR("failed unpack reply: x"LPU64"\n", req->rq_xid); + CERROR("failed unpack reply: x%llu\n", req->rq_xid); return -EPROTO; } @@ -1774,7 +1774,7 @@ int sptlrpc_target_export_check(struct obd_export *exp, exp->exp_flvr_old[1] = exp->exp_flvr_old[0]; exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0]; exp->exp_flvr_old[0] = exp->exp_flvr; - exp->exp_flvr_expire[0] = cfs_time_current_sec() + + exp->exp_flvr_expire[0] = get_seconds() + EXP_FLVR_UPDATE_EXPIRE; exp->exp_flvr = flavor; @@ -1848,7 +1848,7 @@ int sptlrpc_target_export_check(struct obd_export *exp, } if (exp->exp_flvr_expire[0]) { - if (exp->exp_flvr_expire[0] >= cfs_time_current_sec()) { + if (exp->exp_flvr_expire[0] >= get_seconds()) { if (flavor_allowed(&exp->exp_flvr_old[0], req)) { CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the " "middle one ("CFS_DURATION_T")\n", exp, @@ -1856,7 +1856,7 @@ int sptlrpc_target_export_check(struct obd_export *exp, exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc, exp->exp_flvr_expire[0] - - cfs_time_current_sec()); + get_seconds()); spin_unlock(&exp->exp_lock); return 0; } @@ -1873,7 +1873,7 @@ int sptlrpc_target_export_check(struct obd_export *exp, /* now it doesn't match the current flavor, the only chance we can * accept it is match the old flavors which is not expired. */ if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) { - if (exp->exp_flvr_expire[1] >= cfs_time_current_sec()) { + if (exp->exp_flvr_expire[1] >= get_seconds()) { if (flavor_allowed(&exp->exp_flvr_old[1], req)) { CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the " "oldest one ("CFS_DURATION_T")\n", exp, @@ -1881,7 +1881,7 @@ int sptlrpc_target_export_check(struct obd_export *exp, exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc, exp->exp_flvr_expire[1] - - cfs_time_current_sec()); + get_seconds()); spin_unlock(&exp->exp_lock); return 0; } @@ -1911,11 +1911,11 @@ int sptlrpc_target_export_check(struct obd_export *exp, exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_expire[0] ? (unsigned long) (exp->exp_flvr_expire[0] - - cfs_time_current_sec()) : 0, + get_seconds()) : 0, exp->exp_flvr_old[1].sf_rpc, exp->exp_flvr_expire[1] ? (unsigned long) (exp->exp_flvr_expire[1] - - cfs_time_current_sec()) : 0); + get_seconds()) : 0); return -EACCES; } EXPORT_SYMBOL(sptlrpc_target_export_check); @@ -2033,7 +2033,7 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req) case 0: break; default: - CERROR("error unpacking request from %s x"LPU64"\n", + CERROR("error unpacking request from %s x%llu\n", libcfs_id2str(req->rq_peer), req->rq_xid); return SECSVC_DROP; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 9d51badea73d..874789b200a3 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -40,17 +40,17 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" #include <linux/crypto.h> -#include <obd.h> -#include <obd_cksum.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_dlm.h> -#include <lustre_sec.h> +#include "../include/obd.h" +#include "../include/obd_cksum.h" +#include "../include/obd_class.h" +#include "../include/obd_support.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_dlm.h" +#include "../include/lustre_sec.h" #include "ptlrpc_internal.h" @@ -113,7 +113,7 @@ static struct ptlrpc_enc_page_pool { unsigned long epp_st_missings; /* # of cache missing */ unsigned long epp_st_lowfree; /* lowest free pages reached */ unsigned int epp_st_max_wqlen; /* highest waitqueue length */ - cfs_time_t epp_st_max_wait; /* in jiffies */ + unsigned long epp_st_max_wait; /* in jiffies */ /* * pointers to pools */ @@ -156,8 +156,8 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) page_pools.epp_total_pages, page_pools.epp_free_pages, page_pools.epp_idle_idx, - cfs_time_current_sec() - page_pools.epp_last_shrink, - cfs_time_current_sec() - page_pools.epp_last_access, + get_seconds() - page_pools.epp_last_shrink, + get_seconds() - page_pools.epp_last_access, page_pools.epp_st_max_pages, page_pools.epp_st_grows, page_pools.epp_st_grow_fails, @@ -228,7 +228,7 @@ static unsigned long enc_pools_shrink_count(struct shrinker *s, * if no pool access for a long time, we consider it's fully idle. * a little race here is fine. */ - if (unlikely(cfs_time_current_sec() - page_pools.epp_last_access > + if (unlikely(get_seconds() - page_pools.epp_last_access > CACHE_QUIESCENT_PERIOD)) { spin_lock(&page_pools.epp_lock); page_pools.epp_idle_idx = IDLE_IDX_MAX; @@ -255,7 +255,7 @@ static unsigned long enc_pools_shrink_scan(struct shrinker *s, (long)sc->nr_to_scan, page_pools.epp_free_pages); page_pools.epp_st_shrinks++; - page_pools.epp_last_shrink = cfs_time_current_sec(); + page_pools.epp_last_shrink = get_seconds(); } spin_unlock(&page_pools.epp_lock); @@ -263,7 +263,7 @@ static unsigned long enc_pools_shrink_scan(struct shrinker *s, * if no pool access for a long time, we consider it's fully idle. * a little race here is fine. */ - if (unlikely(cfs_time_current_sec() - page_pools.epp_last_access > + if (unlikely(get_seconds() - page_pools.epp_last_access > CACHE_QUIESCENT_PERIOD)) { spin_lock(&page_pools.epp_lock); page_pools.epp_idle_idx = IDLE_IDX_MAX; @@ -498,7 +498,7 @@ int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc) { wait_queue_t waitlink; unsigned long this_idle = -1; - cfs_time_t tick = 0; + unsigned long tick = 0; long now; int p_idx, g_idx; int i; @@ -523,7 +523,7 @@ again: if (tick == 0) tick = cfs_time_current(); - now = cfs_time_current_sec(); + now = get_seconds(); page_pools.epp_st_missings++; page_pools.epp_pages_short += desc->bd_iov_count; @@ -602,7 +602,7 @@ again: this_idle) / (IDLE_IDX_WEIGHT + 1); - page_pools.epp_last_access = cfs_time_current_sec(); + page_pools.epp_last_access = get_seconds(); spin_unlock(&page_pools.epp_lock); return 0; @@ -729,8 +729,8 @@ int sptlrpc_enc_pool_init(void) page_pools.epp_growing = 0; page_pools.epp_idle_idx = 0; - page_pools.epp_last_shrink = cfs_time_current_sec(); - page_pools.epp_last_access = cfs_time_current_sec(); + page_pools.epp_last_shrink = get_seconds(); + page_pools.epp_last_access = get_seconds(); spin_lock_init(&page_pools.epp_lock); page_pools.epp_total_pages = 0; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c index 231656ed7660..01f8b0d6660e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c @@ -36,20 +36,20 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" #include <linux/crypto.h> #include <linux/key.h> -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_log.h> -#include <lustre_disk.h> -#include <lustre_dlm.h> -#include <lustre_param.h> -#include <lustre_sec.h> +#include "../include/obd.h" +#include "../include/obd_class.h" +#include "../include/obd_support.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_log.h" +#include "../include/lustre_disk.h" +#include "../include/lustre_dlm.h" +#include "../include/lustre_param.h" +#include "../include/lustre_sec.h" #include "ptlrpc_internal.h" @@ -918,7 +918,7 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd) if (imp) { spin_lock(&imp->imp_lock); if (imp->imp_sec) - imp->imp_sec_expire = cfs_time_current_sec() + + imp->imp_sec_expire = get_seconds() + SEC_ADAPT_DELAY; spin_unlock(&imp->imp_lock); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index d2eb20eb56db..c500aff66193 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -40,12 +40,12 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_sec.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_sec.h" #define SEC_GC_INTERVAL (30 * 60) @@ -67,7 +67,7 @@ void sptlrpc_gc_add_sec(struct ptlrpc_sec *sec) LASSERT(sec->ps_gc_interval > 0); LASSERT(list_empty(&sec->ps_gc_list)); - sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval; + sec->ps_gc_next = get_seconds() + sec->ps_gc_interval; spin_lock(&sec_gc_list_lock); list_add_tail(&sec_gc_list, &sec->ps_gc_list); @@ -152,11 +152,11 @@ static void sec_do_gc(struct ptlrpc_sec *sec) CDEBUG(D_SEC, "check on sec %p(%s)\n", sec, sec->ps_policy->sp_name); - if (cfs_time_after(sec->ps_gc_next, cfs_time_current_sec())) + if (cfs_time_after(sec->ps_gc_next, get_seconds())) return; sec->ps_policy->sp_cops->gc_ctx(sec); - sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval; + sec->ps_gc_next = get_seconds() + sec->ps_gc_interval; } static int sec_gc_main(void *arg) diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c index 1213621ca5aa..0d08145a6c7e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_lproc.c @@ -38,16 +38,16 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <linux/libcfs/libcfs.h> +#include "../../include/linux/libcfs/libcfs.h" #include <linux/crypto.h> -#include <obd.h> -#include <obd_class.h> -#include <obd_support.h> -#include <lustre_net.h> -#include <lustre_import.h> -#include <lustre_dlm.h> -#include <lustre_sec.h> +#include "../include/obd.h" +#include "../include/obd_class.h" +#include "../include/obd_support.h" +#include "../include/lustre_net.h" +#include "../include/lustre_import.h" +#include "../include/lustre_dlm.h" +#include "../include/lustre_sec.h" #include "ptlrpc_internal.h" @@ -55,7 +55,7 @@ struct proc_dir_entry *sptlrpc_proc_root = NULL; EXPORT_SYMBOL(sptlrpc_proc_root); -char *sec_flags2str(unsigned long flags, char *buf, int bufsize) +static char *sec_flags2str(unsigned long flags, char *buf, int bufsize) { buf[0] = '\0'; @@ -104,7 +104,7 @@ static int sptlrpc_info_lprocfs_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "gc internal %ld\n", sec->ps_gc_interval); seq_printf(seq, "gc next %ld\n", sec->ps_gc_interval ? - sec->ps_gc_next - cfs_time_current_sec() : 0); + sec->ps_gc_next - get_seconds() : 0); sptlrpc_sec_put(sec); out: diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_null.c b/drivers/staging/lustre/lustre/ptlrpc/sec_null.c index ff1137fe4dd6..a47791411149 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_null.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_null.c @@ -41,11 +41,11 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <obd_support.h> -#include <obd_cksum.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_sec.h> +#include "../include/obd_support.h" +#include "../include/obd_cksum.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_sec.h" static struct ptlrpc_sec_policy null_policy; static struct ptlrpc_sec null_sec; @@ -260,11 +260,22 @@ int null_enlarge_reqbuf(struct ptlrpc_sec *sec, if (newbuf == NULL) return -ENOMEM; + /* Must lock this, so that otherwise unprotected change of + * rq_reqmsg is not racing with parallel processing of + * imp_replay_list traversing threads. See LU-3333 + * This is a bandaid at best, we really need to deal with this + * in request enlarging code before unpacking that's already + * there */ + if (req->rq_import) + spin_lock(&req->rq_import->imp_lock); memcpy(newbuf, req->rq_reqbuf, req->rq_reqlen); OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); req->rq_reqbuf = req->rq_reqmsg = newbuf; req->rq_reqbuf_len = alloc_size; + + if (req->rq_import) + spin_unlock(&req->rq_import->imp_lock); } _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index 416401be6d4f..3d72b810c45c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -41,11 +41,11 @@ #define DEBUG_SUBSYSTEM S_SEC -#include <obd_support.h> -#include <obd_cksum.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_sec.h> +#include "../include/obd_support.h" +#include "../include/obd_cksum.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_sec.h" struct plain_sec { struct ptlrpc_sec pls_base; @@ -669,6 +669,15 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec, if (newbuf == NULL) return -ENOMEM; + /* Must lock this, so that otherwise unprotected change of + * rq_reqmsg is not racing with parallel processing of + * imp_replay_list traversing threads. See LU-3333 + * This is a bandaid at best, we really need to deal with this + * in request enlarging code before unpacking that's already + * there */ + if (req->rq_import) + spin_lock(&req->rq_import->imp_lock); + memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len); OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); @@ -676,6 +685,9 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec, req->rq_reqbuf_len = newbuf_size; req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, PLAIN_PACK_MSG_OFF, 0); + + if (req->rq_import) + spin_unlock(&req->rq_import->imp_lock); } _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, PLAIN_PACK_MSG_OFF, diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index d278f2e21803..c88eae27bbf4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -35,11 +35,11 @@ */ #define DEBUG_SUBSYSTEM S_RPC -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lu_object.h> -#include <linux/lnet/types.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lu_object.h" +#include "../../include/linux/lnet/types.h" #include "ptlrpc_internal.h" /* The following are visible and mutable through /sys/module/ptlrpc */ @@ -1037,7 +1037,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) will make it to the top of the list. */ /* Do not pay attention on 1sec or smaller renewals. */ - new_time = cfs_time_current_sec() + extra_delay; + new_time = get_seconds() + extra_delay; if (exp->exp_last_request_time + 1 /*second */ >= new_time) return; @@ -1070,20 +1070,20 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) /* Note - racing to start/reset the obd_eviction timer is safe */ if (exp->exp_obd->obd_eviction_timer == 0) { /* Check if the oldest entry is expired. */ - if (cfs_time_current_sec() > (oldest_time + PING_EVICT_TIMEOUT + + if (get_seconds() > (oldest_time + PING_EVICT_TIMEOUT + extra_delay)) { /* We need a second timer, in case the net was down and * it just came back. Since the pinger may skip every * other PING_INTERVAL (see note in ptlrpc_pinger_main), * we better wait for 3. */ exp->exp_obd->obd_eviction_timer = - cfs_time_current_sec() + 3 * PING_INTERVAL; + get_seconds() + 3 * PING_INTERVAL; CDEBUG(D_HA, "%s: Think about evicting %s from "CFS_TIME_T"\n", exp->exp_obd->obd_name, obd_export_nid2str(oldest_exp), oldest_time); } } else { - if (cfs_time_current_sec() > + if (get_seconds() > (exp->exp_obd->obd_eviction_timer + extra_delay)) { /* The evictor won't evict anyone who we've heard from * recently, so we don't have to check before we start @@ -1100,6 +1100,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) */ static int ptlrpc_check_req(struct ptlrpc_request *req) { + struct obd_device *obd = req->rq_export->exp_obd; int rc = 0; if (unlikely(lustre_msg_get_conn_cnt(req->rq_reqmsg) < @@ -1110,26 +1111,24 @@ static int ptlrpc_check_req(struct ptlrpc_request *req) req->rq_export->exp_conn_cnt); return -EEXIST; } - if (unlikely(req->rq_export->exp_obd && - req->rq_export->exp_obd->obd_fail)) { + if (unlikely(obd == NULL || obd->obd_fail)) { /* * Failing over, don't handle any more reqs, send * error response instead. */ CDEBUG(D_RPCTRACE, "Dropping req %p for failed obd %s\n", - req, req->rq_export->exp_obd->obd_name); + req, (obd != NULL) ? obd->obd_name : "unknown"); rc = -ENODEV; } else if (lustre_msg_get_flags(req->rq_reqmsg) & (MSG_REPLAY | MSG_REQ_REPLAY_DONE) && - !(req->rq_export->exp_obd->obd_recovering)) { + !obd->obd_recovering) { DEBUG_REQ(D_ERROR, req, "Invalid replay without recovery"); class_fail_export(req->rq_export); rc = -ENODEV; } else if (lustre_msg_get_transno(req->rq_reqmsg) != 0 && - !(req->rq_export->exp_obd->obd_recovering)) { - DEBUG_REQ(D_ERROR, req, "Invalid req with transno " - LPU64" without recovery", + !obd->obd_recovering) { + DEBUG_REQ(D_ERROR, req, "Invalid req with transno %llu without recovery", lustre_msg_get_transno(req->rq_reqmsg)); class_fail_export(req->rq_export); rc = -ENODEV; @@ -1153,7 +1152,7 @@ static void ptlrpc_at_set_timer(struct ptlrpc_service_part *svcpt) } /* Set timer for closest deadline */ - next = (__s32)(array->paa_deadline - cfs_time_current_sec() - + next = (__s32)(array->paa_deadline - get_seconds() - at_early_margin); if (next <= 0) { ptlrpc_at_timer((unsigned long)svcpt); @@ -1243,7 +1242,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt; struct ptlrpc_request *reqcopy; struct lustre_msg *reqmsg; - cfs_duration_t olddl = req->rq_deadline - cfs_time_current_sec(); + long olddl = req->rq_deadline - get_seconds(); time_t newdl; int rc; @@ -1288,7 +1287,7 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) /* Fake our processing time into the future to ask the clients * for some extra amount of time */ at_measured(&svcpt->scp_at_estimate, at_extra + - cfs_time_current_sec() - + get_seconds() - req->rq_arrival_time.tv_sec); /* Check to see if we've actually increased the deadline - @@ -1299,11 +1298,11 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) "(%ld/%ld), not sending early reply\n", olddl, req->rq_arrival_time.tv_sec + at_get(&svcpt->scp_at_estimate) - - cfs_time_current_sec()); + get_seconds()); return -ETIMEDOUT; } } - newdl = cfs_time_current_sec() + at_get(&svcpt->scp_at_estimate); + newdl = get_seconds() + at_get(&svcpt->scp_at_estimate); reqcopy = ptlrpc_request_cache_alloc(GFP_NOFS); if (reqcopy == NULL) @@ -1381,8 +1380,8 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt) struct list_head work_list; __u32 index, count; time_t deadline; - time_t now = cfs_time_current_sec(); - cfs_duration_t delay; + time_t now = get_seconds(); + long delay; int first, counter = 0; spin_lock(&svcpt->scp_at_lock); @@ -1766,24 +1765,24 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, if (SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) != SPTLRPC_POLICY_NULL) { rc = ptlrpc_unpack_req_msg(req, req->rq_reqlen); if (rc != 0) { - CERROR("error unpacking request: ptl %d from %s " - "x"LPU64"\n", svc->srv_req_portal, - libcfs_id2str(req->rq_peer), req->rq_xid); + CERROR("error unpacking request: ptl %d from %s x%llu\n", + svc->srv_req_portal, libcfs_id2str(req->rq_peer), + req->rq_xid); goto err_req; } } rc = lustre_unpack_req_ptlrpc_body(req, MSG_PTLRPC_BODY_OFF); if (rc) { - CERROR("error unpacking ptlrpc body: ptl %d from %s x" - LPU64"\n", svc->srv_req_portal, - libcfs_id2str(req->rq_peer), req->rq_xid); + CERROR("error unpacking ptlrpc body: ptl %d from %s x%llu\n", + svc->srv_req_portal, libcfs_id2str(req->rq_peer), + req->rq_xid); goto err_req; } if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_REQ_OPC) && lustre_msg_get_opc(req->rq_reqmsg) == cfs_fail_val) { - CERROR("drop incoming rpc opc %u, x"LPU64"\n", + CERROR("drop incoming rpc opc %u, x%llu\n", cfs_fail_val, req->rq_xid); goto err_req; } @@ -1808,7 +1807,7 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, break; } - CDEBUG(D_RPCTRACE, "got req x"LPU64"\n", req->rq_xid); + CDEBUG(D_RPCTRACE, "got req x%llu\n", req->rq_xid); req->rq_export = class_conn2export( lustre_msg_get_handle(req->rq_reqmsg)); @@ -1827,9 +1826,9 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, } /* req_in handling should/must be fast */ - if (cfs_time_current_sec() - req->rq_arrival_time.tv_sec > 5) + if (get_seconds() - req->rq_arrival_time.tv_sec > 5) DEBUG_REQ(D_WARNING, req, "Slow req_in handling "CFS_DURATION_T"s", - cfs_time_sub(cfs_time_current_sec(), + cfs_time_sub(get_seconds(), req->rq_arrival_time.tv_sec)); /* Set rpc server deadline and add it to the timed list */ @@ -1918,7 +1917,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt, request->rq_session.lc_cookie = 0x5; lu_context_enter(&request->rq_session); - CDEBUG(D_NET, "got req "LPU64"\n", request->rq_xid); + CDEBUG(D_NET, "got req %llu\n", request->rq_xid); request->rq_svc_thread = thread; if (thread) @@ -1932,19 +1931,19 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt, /* Discard requests queued for longer than the deadline. The deadline is increased if we send an early reply. */ - if (cfs_time_current_sec() > request->rq_deadline) { + if (get_seconds() > request->rq_deadline) { DEBUG_REQ(D_ERROR, request, "Dropping timed-out request from %s" ": deadline "CFS_DURATION_T":"CFS_DURATION_T"s ago\n", libcfs_id2str(request->rq_peer), cfs_time_sub(request->rq_deadline, request->rq_arrival_time.tv_sec), - cfs_time_sub(cfs_time_current_sec(), + cfs_time_sub(get_seconds(), request->rq_deadline)); goto put_conn; } CDEBUG(D_RPCTRACE, "Handling RPC pname:cluuid+ref:pid:xid:nid:opc " - "%s:%s+%d:%d:x"LPU64":%s:%d\n", current_comm(), + "%s:%s+%d:%d:x%llu:%s:%d\n", current_comm(), (request->rq_export ? (char *)request->rq_export->exp_client_uuid.uuid : "0"), (request->rq_export ? @@ -1964,22 +1963,22 @@ put_conn: lu_context_exit(&request->rq_session); lu_context_fini(&request->rq_session); - if (unlikely(cfs_time_current_sec() > request->rq_deadline)) { + if (unlikely(get_seconds() > request->rq_deadline)) { DEBUG_REQ(D_WARNING, request, "Request took longer than estimated (" CFS_DURATION_T":"CFS_DURATION_T "s); client may timeout.", cfs_time_sub(request->rq_deadline, request->rq_arrival_time.tv_sec), - cfs_time_sub(cfs_time_current_sec(), + cfs_time_sub(get_seconds(), request->rq_deadline)); } do_gettimeofday(&work_end); timediff = cfs_timeval_sub(&work_end, &work_start, NULL); CDEBUG(D_RPCTRACE, "Handled RPC pname:cluuid+ref:pid:xid:nid:opc " - "%s:%s+%d:%d:x"LPU64":%s:%d Request processed in " - "%ldus (%ldus total) trans "LPU64" rc %d/%d\n", + "%s:%s+%d:%d:x%llu:%s:%d Request processed in " + "%ldus (%ldus total) trans %llu rc %d/%d\n", current_comm(), (request->rq_export ? (char *)request->rq_export->exp_client_uuid.uuid : "0"), @@ -2084,8 +2083,7 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs) if (nlocks == 0 && !been_handled) { /* If we see this, we should already have seen the warning * in mds_steal_ack_locks() */ - CDEBUG(D_HA, "All locks stolen from rs %p x"LPD64".t"LPD64 - " o%d NID %s\n", + CDEBUG(D_HA, "All locks stolen from rs %p x%lld.t%lld o%d NID %s\n", rs, rs->rs_xid, rs->rs_transno, rs->rs_opc, libcfs_nid2str(exp->exp_connection->c_peer.nid)); diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 3c8846006a7b..0624420135c2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -39,10 +39,10 @@ #include <linux/fs.h> #include <linux/posix_acl_xattr.h> -#include <obd_support.h> -#include <obd_class.h> -#include <lustre_net.h> -#include <lustre_disk.h> +#include "../include/obd_support.h" +#include "../include/obd_class.h" +#include "../include/lustre_net.h" +#include "../include/lustre_disk.h" void lustre_assert_wire_constants(void) { /* Wire protocol assertions generated by 'wirecheck' |