X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsec%2Fgss%2Fsec_gss.c;h=33b4291e762c996590d9b78832d9fbd8432216a5;hb=e6e9b8baa8c2db4385bf2e2a692463ae41eb43ac;hp=96d93d0e395f071e66bbc317b1d9d670214df742;hpb=770725e676ad5c378705a3c678105523cc80a12c;p=fs%2Flustre-release.git diff --git a/lustre/sec/gss/sec_gss.c b/lustre/sec/gss/sec_gss.c index 96d93d0..33b4291 100644 --- a/lustre/sec/gss/sec_gss.c +++ b/lustre/sec/gss/sec_gss.c @@ -76,20 +76,14 @@ struct rpc_clnt; #include "gss_internal.h" #include "gss_api.h" -#define GSS_CREDCACHE_EXPIRE (60) /* 1 minute */ -#define GSS_CRED_EXPIRE (8 * 60 * 60) /* 8 hours */ -#define GSS_CRED_SIGN_SIZE (1024) -#define GSS_CRED_VERIFY_SIZE (56) - #define LUSTRE_PIPEDIR "/lustre" +#define GSS_CREDCACHE_EXPIRE (30 * 60) /* 30 minute */ + /********************************************** * gss security init/fini helper * **********************************************/ -#define SECINIT_RPC_TIMEOUT (30) -#define SECFINI_RPC_TIMEOUT (30) - static int secinit_compose_request(struct obd_import *imp, char *buf, int bufsize, int lustre_srv, @@ -113,8 +107,7 @@ static int secinit_compose_request(struct obd_import *imp, /* security wire hdr */ hdr = buf_to_sec_hdr(buf); - hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS); - hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_NONE); + hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_NONE); hdr->msg_len = cpu_to_le32(lmsg_size); hdr->sec_len = cpu_to_le32(8 * 4 + token_size); @@ -137,10 +130,10 @@ static int secinit_compose_request(struct obd_import *imp, /* gss hdr */ *p++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* gss version */ - *p++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */ - *p++ = cpu_to_le32(PTLRPC_GSS_PROC_INIT); /* proc */ + *p++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */ + *p++ = cpu_to_le32(PTLRPCS_GSS_PROC_INIT); /* proc */ *p++ = cpu_to_le32(0); /* seq */ - *p++ = cpu_to_le32(PTLRPC_GSS_SVC_NONE); /* service */ + *p++ = cpu_to_le32(PTLRPCS_GSS_SVC_NONE); /* service */ *p++ = cpu_to_le32(0); /* context handle */ /* plus lustre svc type */ @@ -175,7 +168,6 @@ static int secinit_parse_reply(char *repbuf, int replen, } hdr->flavor = le32_to_cpu(hdr->flavor); - hdr->sectype = le32_to_cpu(hdr->sectype); hdr->msg_len = le32_to_cpu(hdr->msg_len); hdr->sec_len = le32_to_cpu(hdr->sec_len); @@ -183,8 +175,7 @@ static int secinit_parse_reply(char *repbuf, int replen, sec_len = le32_to_cpu(p[3]); /* sanity checks */ - if (hdr->flavor != PTLRPC_SEC_GSS || - hdr->sectype != PTLRPC_SEC_TYPE_NONE) { + if (hdr->flavor != PTLRPCS_FLVR_GSS_NONE) { CERROR("unexpected reply\n"); return -EINVAL; } @@ -201,10 +192,12 @@ static int secinit_parse_reply(char *repbuf, int replen, p = (__u32 *) buf_to_sec_data(repbuf); effective = 0; - status = le32_to_cpu(*p++); + p += 2; /* skip the leading unused bytes */ + seq = le32_to_cpu(*p++); major = le32_to_cpu(*p++); minor = le32_to_cpu(*p++); - seq = le32_to_cpu(*p++); + status = 0; + effective += 4 * 4; if (copy_to_user(outbuf, &status, 4)) @@ -373,19 +366,14 @@ out_copy: struct gss_sec { struct ptlrpc_sec gs_base; struct gss_api_mech *gs_mech; -#ifdef __KERNEL__ spinlock_t gs_lock; struct list_head gs_upcalls; char *gs_pipepath; struct dentry *gs_depipe; -#endif }; -#ifdef __KERNEL__ - -static rwlock_t gss_ctx_lock = RW_LOCK_UNLOCKED; - struct gss_upcall_msg_data { + __u64 gum_pag; __u32 gum_uid; __u32 gum_svc; __u32 gum_nal; @@ -403,6 +391,8 @@ struct gss_upcall_msg { struct gss_upcall_msg_data gum_data; }; +#ifdef __KERNEL__ +static rwlock_t gss_ctx_lock = RW_LOCK_UNLOCKED; /********************************************** * rpc_pipe upcall helpers * **********************************************/ @@ -419,7 +409,20 @@ void gss_release_msg(struct gss_upcall_msg *gmsg) return; } LASSERT(list_empty(&gmsg->gum_list)); +#if 0 LASSERT(list_empty(&gmsg->gum_base.list)); +#else + /* XXX */ + if (!list_empty(&gmsg->gum_base.list)) { + int error = gmsg->gum_base.errno; + + CWARN("msg %p: list: %p/%p/%p, copied %d, err %d, wq %d\n", + gmsg, &gmsg->gum_base.list, gmsg->gum_base.list.prev, + gmsg->gum_base.list.next, gmsg->gum_base.copied, error, + list_empty(&gmsg->gum_waitq.task_list)); + LBUG(); + } +#endif OBD_FREE(gmsg, sizeof(*gmsg)); EXIT; } @@ -427,19 +430,15 @@ void gss_release_msg(struct gss_upcall_msg *gmsg) static void gss_unhash_msg_nolock(struct gss_upcall_msg *gmsg) { - ENTRY; - if (list_empty(&gmsg->gum_list)) { - EXIT; + LASSERT_SPIN_LOCKED(&gmsg->gum_gsec->gs_lock); + + if (list_empty(&gmsg->gum_list)) return; - } list_del_init(&gmsg->gum_list); wake_up(&gmsg->gum_waitq); + LASSERT(atomic_read(&gmsg->gum_refcount) > 1); atomic_dec(&gmsg->gum_refcount); - CDEBUG(D_SEC, "gmsg %p refcount now %d\n", - gmsg, atomic_read(&gmsg->gum_refcount)); - LASSERT(atomic_read(&gmsg->gum_refcount) > 0); - EXIT; } static void @@ -460,11 +459,14 @@ struct gss_upcall_msg * gss_find_upcall(struct gss_sec *gsec, struct gss_upcall_msg *gmsg; ENTRY; + LASSERT_SPIN_LOCKED(&gsec->gs_lock); + list_for_each_entry(gmsg, &gsec->gs_upcalls, gum_list) { if (memcmp(&gmsg->gum_data, gmd, sizeof(*gmd))) continue; if (strcmp(gmsg->gum_obdname, obdname)) continue; + LASSERT(atomic_read(&gmsg->gum_refcount) > 0); atomic_inc(&gmsg->gum_refcount); CDEBUG(D_SEC, "found gmsg at %p: obdname %s, uid %d, ref %d\n", gmsg, obdname, gmd->gum_uid, @@ -490,16 +492,20 @@ static void gss_init_upcall_msg(struct gss_upcall_msg *gmsg, memcpy(&gmsg->gum_data, gmd, sizeof(*gmd)); rpcmsg = &gmsg->gum_base; + INIT_LIST_HEAD(&rpcmsg->list); rpcmsg->data = &gmsg->gum_data; rpcmsg->len = sizeof(gmsg->gum_data); + rpcmsg->copied = 0; + rpcmsg->errno = 0; EXIT; } #endif /* __KERNEL__ */ +/* this seems to be used only from userspace code */ +#ifndef __KERNEL__ /******************************************** * gss cred manipulation helpers * ********************************************/ -#if 0 static int gss_cred_is_uptodate_ctx(struct ptlrpc_cred *cred) { @@ -517,7 +523,7 @@ int gss_cred_is_uptodate_ctx(struct ptlrpc_cred *cred) #endif static inline -struct gss_cl_ctx * gss_get_ctx(struct gss_cl_ctx *ctx) +struct gss_cl_ctx *gss_get_ctx(struct gss_cl_ctx *ctx) { atomic_inc(&ctx->gc_refcount); return ctx; @@ -577,7 +583,7 @@ void gss_cred_set_ctx(struct ptlrpc_cred *cred, struct gss_cl_ctx *ctx) write_lock(&gss_ctx_lock); old = gcred->gc_ctx; gcred->gc_ctx = ctx; - cred->pc_flags |= PTLRPC_CRED_UPTODATE; + set_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags); write_unlock(&gss_ctx_lock); if (old) gss_put_ctx(old); @@ -633,6 +639,8 @@ int gss_parse_init_downcall(struct gss_api_mech *gm, rawobj_t *buf, spin_lock_init(&ctx->gc_seq_lock); atomic_set(&ctx->gc_refcount,1); + if (simple_get_bytes(&p, &len, &gmd->gum_pag, sizeof(gmd->gum_pag))) + goto err_free_ctx; if (simple_get_bytes(&p, &len, &gmd->gum_uid, sizeof(gmd->gum_uid))) goto err_free_ctx; if (simple_get_bytes(&p, &len, &gmd->gum_svc, sizeof(gmd->gum_svc))) @@ -701,7 +709,6 @@ err_free_ctx: * cred APIs * ***************************************/ #ifdef __KERNEL__ -#define CRED_REFRESH_UPCALL_TIMEOUT (50) static int gss_cred_refresh(struct ptlrpc_cred *cred) { struct obd_import *import; @@ -711,10 +718,11 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) struct dentry *dentry; char *obdname, *obdtype; wait_queue_t wait; - uid_t uid = cred->pc_uid; int res; ENTRY; + might_sleep(); + /* any flags means it has been handled, do nothing */ if (cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) RETURN(0); @@ -729,15 +737,16 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) RETURN(-EINVAL); } - gmd.gum_uid = uid; + gmd.gum_pag = cred->pc_pag; + gmd.gum_uid = cred->pc_uid; gmd.gum_nal = import->imp_connection->c_peer.peer_ni->pni_number; gmd.gum_netid = 0; gmd.gum_nid = import->imp_connection->c_peer.peer_id.nid; obdtype = import->imp_obd->obd_type->typ_name; - if (!strcmp(obdtype, "mdc")) + if (!strcmp(obdtype, OBD_MDC_DEVICENAME)) gmd.gum_svc = LUSTRE_GSS_SVC_MDS; - else if (!strcmp(obdtype, "osc")) + else if (!strcmp(obdtype, OBD_OSC_DEVICENAME)) gmd.gum_svc = LUSTRE_GSS_SVC_OSS; else { CERROR("gss on %s?\n", obdtype); @@ -752,7 +761,7 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) CDEBUG(D_SEC, "Initiate gss context %p(%u@%s)\n", container_of(cred, struct gss_cred, gc_base), - uid, import->imp_target_uuid.uuid); + cred->pc_uid, import->imp_target_uuid.uuid); again: spin_lock(&gsec->gs_lock); @@ -780,7 +789,7 @@ again: * administrator via lctl etc. */ if (cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) { - CWARN("cred %p("LPU64"/%u) was set flags %x unexpectedly\n", + CWARN("cred %p("LPU64"/%u) was set flags %lx unexpectedly\n", cred, cred->pc_pag, cred->pc_uid, cred->pc_flags); cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR; gss_unhash_msg_nolock(gss_new); @@ -839,7 +848,7 @@ waiting: res = -EINTR; } else if (res == 0) { CERROR("cred %p: upcall timedout\n", cred); - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); res = -ETIMEDOUT; } else res = 0; @@ -851,8 +860,7 @@ out: } #else /* !__KERNEL__ */ extern int lgss_handle_krb5_upcall(uid_t uid, __u32 dest_ip, - char *obd_name, - char *buf, int bufsize, + char *obd_name, char *buf, int bufsize, int (*callback)(char*, unsigned long)); static int gss_cred_refresh(struct ptlrpc_cred *cred) @@ -863,11 +871,11 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) struct gss_sec *gsec; struct gss_api_mech *mech; struct gss_cl_ctx *ctx = NULL; - struct vfs_cred vcred = { 0 }; ptl_nid_t peer_nid; __u32 dest_ip; __u32 subflavor; int rc, gss_err; + struct gss_upcall_msg_data gmd = { 0 }; LASSERT(cred); LASSERT(cred->pc_sec); @@ -880,9 +888,9 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) imp = cred->pc_sec->ps_import; peer_nid = imp->imp_connection->c_peer.peer_id.nid; dest_ip = (__u32) (peer_nid & 0xFFFFFFFF); - subflavor = cred->pc_sec->ps_flavor.subflavor; + subflavor = cred->pc_sec->ps_flavor; - if (subflavor != PTLRPC_SEC_GSS_KRB5I) { + if (subflavor != PTLRPCS_SUBFLVR_KRB5I) { CERROR("unknown subflavor %u\n", subflavor); GOTO(err_out, rc = -EINVAL); } @@ -901,12 +909,13 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) gsec = container_of(cred->pc_sec, struct gss_sec, gs_base); mech = gsec->gs_mech; LASSERT(mech); - rc = gss_parse_init_downcall(mech, &obj, &ctx, &vcred, &dest_ip, + + rc = gss_parse_init_downcall(mech, &obj, &ctx, &gmd, &gss_err); if (rc || gss_err) { CERROR("parse init downcall: rpc %d, gss 0x%x\n", rc, gss_err); if (rc != -ERESTART || gss_err != 0) - cred->pc_flags |= PTLRPC_CRED_ERROR; + set_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags); if (rc == 0) rc = -EPERM; goto err_out; @@ -918,7 +927,7 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred) return 0; err_out: - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); return rc; } #endif @@ -970,10 +979,10 @@ static int gss_cred_sign(struct ptlrpc_cred *cred, spin_unlock(&ctx->gc_seq_lock); *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */ - *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */ + *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */ *vp++ = cpu_to_le32(ctx->gc_proc); /* proc */ *vp++ = cpu_to_le32(seqnum); /* seq */ - *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_INTEGRITY); /* service */ + *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_INTEGRITY); /* service */ vlen -= 5 * 4; if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) { @@ -1042,10 +1051,10 @@ static int gss_cred_verify(struct ptlrpc_cred *cred, vlen -= 3 * 4; switch (proc) { - case PTLRPC_GSS_PROC_DATA: + case PTLRPCS_GSS_PROC_DATA: seq = le32_to_cpu(*vp++); svc = le32_to_cpu(*vp++); - if (svc != PTLRPC_GSS_SVC_INTEGRITY) { + if (svc != PTLRPCS_GSS_SVC_INTEGRITY) { CERROR("Unknown svc %d\n", svc); RETURN(-EPROTO); } @@ -1095,7 +1104,7 @@ static int gss_cred_verify(struct ptlrpc_cred *cred, proc_data_out: gss_put_ctx(ctx); break; - case PTLRPC_GSS_PROC_ERR: + case PTLRPCS_GSS_PROC_ERR: major = le32_to_cpu(*vp++); minor = le32_to_cpu(*vp++); /* server return NO_CONTEXT might be caused by context expire @@ -1110,7 +1119,7 @@ proc_data_out: */ if (major == GSS_S_NO_CONTEXT || major == GSS_S_BAD_SIG) { - CWARN("req %p: server report cred %p %s, expired?\n", + CWARN("req %p: server report cred %p %s\n", req, cred, (major == GSS_S_NO_CONTEXT) ? "NO_CONTEXT" : "BAD_SIG"); @@ -1170,10 +1179,10 @@ static int gss_cred_seal(struct ptlrpc_cred *cred, spin_unlock(&ctx->gc_seq_lock); *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */ - *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5P); /* subflavor */ + *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5P); /* subflavor */ *vp++ = cpu_to_le32(ctx->gc_proc); /* proc */ *vp++ = cpu_to_le32(seqnum); /* seq */ - *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_PRIVACY); /* service */ + *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_PRIVACY); /* service */ vlen -= 5 * 4; if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) { @@ -1254,8 +1263,8 @@ static int gss_cred_unseal(struct ptlrpc_cred *cred, vlen -= 5 * 4; switch (proc) { - case PTLRPC_GSS_PROC_DATA: - if (svc != PTLRPC_GSS_SVC_PRIVACY) { + case PTLRPCS_GSS_PROC_DATA: + if (svc != PTLRPCS_GSS_SVC_PRIVACY) { CERROR("Unknown svc %d\n", svc); RETURN(-EPROTO); } @@ -1327,28 +1336,33 @@ static void destroy_gss_context(struct ptlrpc_cred *cred) int replen, rc; ENTRY; - /* cred's refcount is 0, steal one */ - atomic_inc(&cred->pc_refcount); - - gcred = container_of(cred, struct gss_cred, gc_base); - gcred->gc_ctx->gc_proc = PTLRPC_GSS_PROC_DESTROY; imp = cred->pc_sec->ps_import; LASSERT(imp); - if (!(cred->pc_flags & PTLRPC_CRED_UPTODATE)) { - CDEBUG(D_SEC, "Destroy a dead gss cred %p(%u@%s)\n", - gcred, cred->pc_uid, imp->imp_target_uuid.uuid); - atomic_dec(&cred->pc_refcount); + if (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags) || + !test_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags)) { + CDEBUG(D_SEC, "Destroy dead cred %p(%u@%s)\n", + cred, cred->pc_uid, imp->imp_target_uuid.uuid); EXIT; return; } + might_sleep(); + + /* cred's refcount is 0, steal one */ + atomic_inc(&cred->pc_refcount); + + gcred = container_of(cred, struct gss_cred, gc_base); + gcred->gc_ctx->gc_proc = PTLRPCS_GSS_PROC_DESTROY; + CDEBUG(D_SEC, "client destroy gss cred %p(%u@%s)\n", gcred, cred->pc_uid, imp->imp_target_uuid.uuid); lmsg_size = lustre_msg_size(0, NULL); + req.rq_req_secflvr = cred->pc_sec->ps_flavor; + req.rq_cred = cred; req.rq_reqbuf_len = sizeof(*hdr) + lmsg_size + - ptlrpcs_est_req_payload(cred->pc_sec, lmsg_size); + ptlrpcs_est_req_payload(&req, lmsg_size); OBD_ALLOC(req.rq_reqbuf, req.rq_reqbuf_len); if (!req.rq_reqbuf) { @@ -1360,8 +1374,7 @@ static void destroy_gss_context(struct ptlrpc_cred *cred) /* wire hdr */ hdr = buf_to_sec_hdr(req.rq_reqbuf); - hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS); - hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_AUTH); + hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_AUTH); hdr->msg_len = cpu_to_le32(lmsg_size); hdr->sec_len = cpu_to_le32(0); @@ -1423,7 +1436,7 @@ static void gss_cred_destroy(struct ptlrpc_cred *cred) gss_put_ctx(gcred->gc_ctx); } - CDEBUG(D_SEC, "GSS_SEC: destroy cred %p\n", gcred); + CDEBUG(D_SEC, "sec.gss %p: destroy cred %p\n", cred->pc_sec, gcred); OBD_FREE(gcred, sizeof(*gcred)); EXIT; @@ -1518,8 +1531,8 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) if (err) CERROR("parse init downcall err %d\n", err); + vcred.vc_pag = gmd.gum_pag; vcred.vc_uid = gmd.gum_uid; - vcred.vc_pag = vcred.vc_uid; /* FIXME */ cred = ptlrpcs_cred_lookup(sec, &vcred); if (!cred) { @@ -1528,12 +1541,12 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) } if (err || gss_err) { - cred->pc_flags |= PTLRPC_CRED_DEAD; + set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags); if (err != -ERESTART || gss_err != 0) - cred->pc_flags |= PTLRPC_CRED_ERROR; + set_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags); CERROR("cred %p: rpc err %d, gss err 0x%x, fatal %d\n", - cred, err, gss_err, - ((cred->pc_flags & PTLRPC_CRED_ERROR) != 0)); + cred, err, gss_err, + (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags) != 0)); } else { CDEBUG(D_SEC, "get initial ctx:\n"); gss_cred_set_ctx(cred, ctx); @@ -1569,6 +1582,8 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) static unsigned long ratelimit; ENTRY; + LASSERT(list_empty(&msg->list)); + if (msg->errno >= 0) { EXIT; return; @@ -1576,12 +1591,13 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) gmsg = container_of(msg, struct gss_upcall_msg, gum_base); CDEBUG(D_SEC, "destroy gmsg %p\n", gmsg); + LASSERT(atomic_read(&gmsg->gum_refcount) > 0); atomic_inc(&gmsg->gum_refcount); gss_unhash_msg(gmsg); if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) { unsigned long now = get_seconds(); if (time_after(now, ratelimit)) { - CWARN("GSS_SEC upcall timed out.\n" + CWARN("sec.gss upcall timed out.\n" "Please check user daemon is running!\n"); ratelimit = now + 15; } @@ -1606,6 +1622,7 @@ void gss_pipe_release(struct inode *inode) gmsg = list_entry(gsec->gs_upcalls.next, struct gss_upcall_msg, gum_list); + LASSERT(list_empty(&gmsg->gum_base.list)); gmsg->gum_base.errno = -EPIPE; atomic_inc(&gmsg->gum_refcount); gss_unhash_msg_nolock(gmsg); @@ -1628,19 +1645,21 @@ static struct rpc_pipe_ops gss_upcall_ops = { *********************************************/ static -struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, +struct ptlrpc_sec* gss_create_sec(__u32 flavor, const char *pipe_dir, void *pipe_data) { struct gss_sec *gsec; struct ptlrpc_sec *sec; + uid_t save_uid; + #ifdef __KERNEL__ char *pos; int pipepath_len; #endif ENTRY; - LASSERT(flavor->flavor == PTLRPC_SEC_GSS); + LASSERT(SEC_FLAVOR_MAJOR(flavor) == PTLRPCS_FLVR_MAJOR_GSS); OBD_ALLOC(gsec, sizeof(*gsec)); if (!gsec) { @@ -1648,9 +1667,9 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, RETURN(NULL); } - gsec->gs_mech = kgss_subflavor_to_mech(flavor->subflavor); + gsec->gs_mech = kgss_subflavor_to_mech(SEC_FLAVOR_SUB(flavor)); if (!gsec->gs_mech) { - CERROR("subflavor %d not found\n", flavor->subflavor); + CERROR("subflavor 0x%x not found\n", flavor); goto err_free; } @@ -1665,6 +1684,10 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, if (!gsec->gs_pipepath) goto err_mech_put; + /* pipe rpc require root permission */ + save_uid = current->fsuid; + current->fsuid = 0; + sprintf(gsec->gs_pipepath, LUSTRE_PIPEDIR"/%s", pipe_dir); if (IS_ERR(rpc_mkdir(gsec->gs_pipepath, NULL))) { CERROR("can't make pipedir %s\n", gsec->gs_pipepath); @@ -1684,24 +1707,13 @@ struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor, #endif sec = &gsec->gs_base; - - switch (flavor->subflavor) { - case PTLRPC_SEC_GSS_KRB5I: - sec->ps_sectype = PTLRPC_SEC_TYPE_AUTH; - break; - case PTLRPC_SEC_GSS_KRB5P: - sec->ps_sectype = PTLRPC_SEC_TYPE_PRIV; - break; - default: - LBUG(); - } - sec->ps_expire = GSS_CREDCACHE_EXPIRE; sec->ps_nextgc = get_seconds() + sec->ps_expire; sec->ps_flags = 0; - CDEBUG(D_SEC, "Create GSS security instance at %p(external %p)\n", - gsec, sec); + current->fsuid = save_uid; + + CDEBUG(D_SEC, "Create sec.gss %p\n", gsec); RETURN(sec); #ifdef __KERNEL__ @@ -1711,6 +1723,7 @@ err_rmdir: *pos = 0; rpc_rmdir(gsec->gs_pipepath); err_free_path: + current->fsuid = save_uid; OBD_FREE(gsec->gs_pipepath, pipepath_len); err_mech_put: #endif @@ -1731,7 +1744,7 @@ void gss_destroy_sec(struct ptlrpc_sec *sec) ENTRY; gsec = container_of(sec, struct gss_sec, gs_base); - CDEBUG(D_SEC, "Destroy GSS security instance at %p\n", gsec); + CDEBUG(D_SEC, "Destroy sec.gss %p\n", gsec); LASSERT(gsec->gs_mech); LASSERT(!atomic_read(&sec->ps_refcount)); @@ -1768,7 +1781,7 @@ struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec, atomic_set(&cred->pc_refcount, 0); cred->pc_sec = sec; cred->pc_ops = &gss_credops; - cred->pc_expire = get_seconds() + GSS_CRED_EXPIRE; + cred->pc_expire = 0; cred->pc_flags = 0; cred->pc_pag = vcred->vc_pag; cred->pc_uid = vcred->vc_uid; @@ -1778,12 +1791,14 @@ struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec, RETURN(cred); } -static int gss_estimate_payload(struct ptlrpc_sec *sec, int msgsize) +static int gss_estimate_payload(struct ptlrpc_sec *sec, + struct ptlrpc_request *req, + int msgsize) { - switch (sec->ps_sectype) { - case PTLRPC_SEC_TYPE_AUTH: + switch (SEC_FLAVOR_SVC(req->rq_req_secflvr)) { + case PTLRPCS_SVC_AUTH: return GSS_MAX_AUTH_PAYLOAD; - case PTLRPC_SEC_TYPE_PRIV: + case PTLRPCS_SVC_PRIV: return size_round16(GSS_MAX_AUTH_PAYLOAD + msgsize + GSS_PRIVBUF_PREFIX_LEN + GSS_PRIVBUF_SUFFIX_LEN); @@ -1804,9 +1819,9 @@ static int gss_alloc_reqbuf(struct ptlrpc_sec *sec, /* In PRIVACY mode, lustre message is always 0 (already encoded into * security payload). */ - privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV; + privacy = (SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV); msg_payload = privacy ? 0 : lmsg_size; - sec_payload = gss_estimate_payload(sec, lmsg_size); + sec_payload = gss_estimate_payload(sec, req, lmsg_size); rc = sec_alloc_reqbuf(sec, req, msg_payload, sec_payload); if (rc) @@ -1840,7 +1855,7 @@ static void gss_free_reqbuf(struct ptlrpc_sec *sec, LASSERT(req->rq_reqmsg); LASSERT(req->rq_reqlen); - privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV; + privacy = SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV; if (privacy) { buf = (char *) req->rq_reqmsg - GSS_PRIVBUF_PREFIX_LEN; LASSERT(buf < req->rq_reqbuf || @@ -1865,9 +1880,9 @@ static struct ptlrpc_secops gss_secops = { static struct ptlrpc_sec_type gss_type = { .pst_owner = THIS_MODULE, - .pst_name = "GSS_SEC", + .pst_name = "sec.gss", .pst_inst = ATOMIC_INIT(0), - .pst_flavor = {PTLRPC_SEC_GSS, 0}, + .pst_flavor = PTLRPCS_FLVR_MAJOR_GSS, .pst_ops = &gss_secops, };