ceph: fix authentication races, auth_none oops
authorSage Weil <sage@newdream.net>
Tue, 16 Feb 2010 00:22:28 +0000 (16:22 -0800)
committerSage Weil <sage@newdream.net>
Wed, 17 Feb 2010 06:01:11 +0000 (22:01 -0800)
Call __validate_auth() under monc->mutex, and use helper for
initial hello so that the pending_auth flag is set.  This fixes
possible races in which we have an authentication request (hello
or otherwise) pending and send another one.  In particular, with
auth_none, we _never_ want to call ceph_build_auth() from
__validate_auth(), since the ->build_request() method is NULL.

Signed-off-by: Sage Weil <sage@newdream.net>
fs/ceph/mon_client.c

index 542276e..40d7d90 100644 (file)
@@ -95,6 +95,18 @@ int ceph_monmap_contains(struct ceph_monmap *m, struct ceph_entity_addr *addr)
        return 0;
 }
 
+/*
+ * Send an auth request.
+ */
+static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
+{
+       monc->pending_auth = 1;
+       monc->m_auth->front.iov_len = len;
+       monc->m_auth->hdr.front_len = cpu_to_le32(len);
+       ceph_msg_get(monc->m_auth);  /* keep our ref */
+       ceph_con_send(monc->con, monc->m_auth);
+}
+
 /*
  * Close monitor session, if any.
  */
@@ -137,10 +149,7 @@ static int __open_session(struct ceph_mon_client *monc)
                ret = ceph_auth_build_hello(monc->auth,
                                            monc->m_auth->front.iov_base,
                                            monc->m_auth->front_max);
-               monc->m_auth->front.iov_len = ret;
-               monc->m_auth->hdr.front_len = cpu_to_le32(ret);
-               ceph_msg_get(monc->m_auth);  /* keep our ref */
-               ceph_con_send(monc->con, monc->m_auth);
+               __send_prepared_auth_request(monc, ret);
        } else {
                dout("open_session mon%d already open\n", monc->cur_mon);
        }
@@ -507,11 +516,9 @@ static void delayed_work(struct work_struct *work)
                __open_session(monc);  /* continue hunting */
        } else {
                ceph_con_keepalive(monc->con);
-               mutex_unlock(&monc->mutex);
 
                __validate_auth(monc);
 
-               mutex_lock(&monc->mutex);
                if (monc->auth->ops->is_authenticated(monc->auth))
                        __send_subscribe(monc);
        }
@@ -650,16 +657,6 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
        kfree(monc->monmap);
 }
 
-static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len)
-{
-       monc->pending_auth = 1;
-       monc->m_auth->front.iov_len = len;
-       monc->m_auth->hdr.front_len = cpu_to_le32(len);
-       ceph_msg_get(monc->m_auth);  /* keep our ref */
-       ceph_con_send(monc->con, monc->m_auth);
-}
-
-
 static void handle_auth_reply(struct ceph_mon_client *monc,
                              struct ceph_msg *msg)
 {