Whamcloud - gitweb
roundup gss credential timeout down to avoid expiration between accept &
[fs/lustre-release.git] / lustre / sec / gss / sec_gss.c
index 8bd4f02..bdd6232 100644 (file)
@@ -76,23 +76,14 @@ struct rpc_clnt;
 #include "gss_internal.h"
 #include "gss_api.h"
 
-#define GSS_CREDCACHE_EXPIRE    (30 * 60)          /* 30 minute */
-/* not used now */
-#if 0
-#define GSS_CRED_EXPIRE         (8 * 60 * 60)      /* 8 hours */
-#define GSS_CRED_SIGN_SIZE      (1024)
-#define GSS_CRED_VERIFY_SIZE    (56)
-#endif
-
 #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     (10)
-
 static int secinit_compose_request(struct obd_import *imp,
                                    char *buf, int bufsize,
                                    int lustre_srv,
@@ -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;
@@ -572,7 +578,7 @@ void gss_cred_set_ctx(struct ptlrpc_cred *cred, struct gss_cl_ctx *ctx)
                 CERROR("unable to get expire time\n");
                 ctx_expiry = 1; /* make it expired now */
         }
-        cred->pc_expire = (unsigned long) ctx_expiry;
+        cred->pc_expire = gss_roundup_expire_time(ctx_expiry);
 
         write_lock(&gss_ctx_lock);
         old = gcred->gc_ctx;
@@ -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,7 +718,6 @@ 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;
 
@@ -731,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);
@@ -754,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);
@@ -853,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)
@@ -865,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);
@@ -882,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);
         }
@@ -903,7 +909,8 @@ 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);
@@ -1112,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");
 
@@ -1429,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;
@@ -1524,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) {
@@ -1575,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;
@@ -1582,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;
                 }
@@ -1612,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);
@@ -1640,10 +1651,11 @@ struct ptlrpc_sec* gss_create_sec(__u32 flavor,
 {
         struct gss_sec *gsec;
         struct ptlrpc_sec *sec;
+        uid_t save_uid;
+
 #ifdef __KERNEL__
         char *pos;
         int   pipepath_len;
-        uid_t save_uid;
 #endif
         ENTRY;
 
@@ -1701,8 +1713,7 @@ struct ptlrpc_sec* gss_create_sec(__u32 flavor,
 
         current->fsuid = save_uid;
 
-        CDEBUG(D_SEC, "Create GSS security instance at %p(external %p)\n",
-               gsec, sec);
+        CDEBUG(D_SEC, "Create sec.gss %p\n", gsec);
         RETURN(sec);
 
 #ifdef __KERNEL__
@@ -1733,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));