Whamcloud - gitweb
LU-4698 target: check for NULL tgt before deref 36/9936/10
authorNathaniel Clark <nathaniel.l.clark@intel.com>
Fri, 11 Apr 2014 20:29:07 +0000 (16:29 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 7 May 2015 16:17:57 +0000 (16:17 +0000)
In the case of and echo server during obdfilter-survey tests a target
can be missing from the obd_device.
Check for a valid pointer before dereferencing it, return error if
it's NULL.
Check for valid obt in class_exp2tgt otherwise return NULL target.
Add checks for all places that call class_exp2tgt for NULL return
value.

Signed-off-by: Nathaniel Clark <nathaniel.l.clark@intel.com>
Change-Id: I27a3020dc7ef9943fb600c3ddb6432f7f67f8b39
Reviewed-on: http://review.whamcloud.com/9936
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Reviewed-by: Bob Glossman <bob.glossman@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/obd_class.h
lustre/target/tgt_handler.c
lustre/target/tgt_lastrcvd.c

index 46a6794..bfb5e9e 100644 (file)
@@ -305,6 +305,8 @@ static inline enum obd_option exp_flags_from_obd(struct obd_device *obd)
 static inline struct lu_target *class_exp2tgt(struct obd_export *exp)
 {
         LASSERT(exp->exp_obd);
+       if (exp->exp_obd->u.obt.obt_magic != OBT_MAGIC)
+               return NULL;
         return exp->exp_obd->u.obt.obt_lut;
 }
 
index 93ff6cb..39caceb 100644 (file)
@@ -554,6 +554,11 @@ static struct tgt_handler *tgt_handler_find_check(struct ptlrpc_request *req)
        ENTRY;
 
        tgt = class_exp2tgt(req->rq_export);
+       if (unlikely(tgt == NULL)) {
+               DEBUG_REQ(D_ERROR, req, "%s: No target for connected export\n",
+                         class_exp2obd(req->rq_export)->obd_name);
+               RETURN(ERR_PTR(-EINVAL));
+       }
 
        for (s = tgt->lut_slice; s->tos_hs != NULL; s++)
                if (s->tos_opc_start <= opc && opc < s->tos_opc_end)
@@ -627,6 +632,14 @@ int tgt_request_handle(struct ptlrpc_request *req)
        else
                tsi->tsi_jobid = NULL;
 
+       if (tgt == NULL) {
+               DEBUG_REQ(D_ERROR, req, "%s: No target for connected export\n",
+                         class_exp2obd(req->rq_export)->obd_name);
+               req->rq_status = -EINVAL;
+               rc = ptlrpc_error(req);
+               GOTO(out, rc);
+       }
+
        request_fail_id = tgt->lut_request_fail_id;
        tsi->tsi_reply_fail_id = tgt->lut_reply_fail_id;
 
@@ -744,6 +757,12 @@ static int tgt_init_sec_level(struct ptlrpc_request *req)
                RETURN(0);
        }
 
+       if (unlikely(tgt == NULL)) {
+               DEBUG_REQ(D_ERROR, req, "%s: No target for connected export\n",
+                         class_exp2obd(req->rq_export)->obd_name);
+               RETURN(-EINVAL);
+       }
+
        client = libcfs_nid2str(req->rq_peer.nid);
        /* no GSS support case */
        if (!req->rq_auth_gss) {
@@ -884,6 +903,11 @@ int tgt_adapt_sptlrpc_conf(struct lu_target *tgt, int initial)
        struct sptlrpc_rule_set  tmp_rset;
        int                      rc;
 
+       if (unlikely(tgt == NULL)) {
+               CERROR("No target passed");
+               return -EINVAL;
+       }
+
        sptlrpc_rule_set_init(&tmp_rset);
        rc = sptlrpc_conf_target_get_rules(tgt->lut_obd, &tmp_rset, initial);
        if (rc) {
@@ -1148,6 +1172,12 @@ static int tgt_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
 
        tgt = class_exp2tgt(lock->l_export);
 
+       if (unlikely(tgt == NULL)) {
+               CDEBUG(D_ERROR, "%s: No target for connected export\n",
+                      class_exp2obd(lock->l_export)->obd_name);
+               RETURN(-EINVAL);
+       }
+
        if (flag == LDLM_CB_CANCELING &&
            (lock->l_granted_mode & (LCK_PW | LCK_GROUP)) &&
            (tgt->lut_sync_lock_cancel == ALWAYS_SYNC_ON_CANCEL ||
index c31e3f4..bf024bd 100644 (file)
@@ -92,7 +92,7 @@ void tgt_client_free(struct obd_export *exp)
        if (ted->ted_lr_idx < 0)
                return;
        /* Clear bit when lcd is freed */
-       LASSERT(lut->lut_client_bitmap);
+       LASSERT(lut && lut->lut_client_bitmap);
        if (!test_and_clear_bit(ted->ted_lr_idx, lut->lut_client_bitmap)) {
                CERROR("%s: client %u bit already clear in bitmap\n",
                       exp->exp_obd->obd_name, ted->ted_lr_idx);
@@ -157,6 +157,12 @@ static int tgt_client_data_update(const struct lu_env *env,
 
        ENTRY;
 
+       if (unlikely(tgt == NULL)) {
+               CDEBUG(D_ERROR, "%s: No target for connected export\n",
+                         class_exp2obd(exp)->obd_name);
+               RETURN(-EINVAL);
+       }
+
        th = dt_trans_create(env, tgt->lut_bottom);
        if (IS_ERR(th))
                RETURN(PTR_ERR(th));
@@ -330,7 +336,7 @@ static void tgt_client_epoch_update(const struct lu_env *env,
        struct lsd_client_data  *lcd = exp->exp_target_data.ted_lcd;
        struct lu_target        *tgt = class_exp2tgt(exp);
 
-       LASSERT(tgt->lut_bottom);
+       LASSERT(tgt && tgt->lut_bottom);
        /** VBR: set client last_epoch to current epoch */
        if (lcd->lcd_last_epoch >= tgt->lut_lsd.lsd_start_epoch)
                return;
@@ -534,7 +540,7 @@ int tgt_client_new(const struct lu_env *env, struct obd_export *exp)
 
        ENTRY;
 
-       LASSERT(tgt->lut_client_bitmap != NULL);
+       LASSERT(tgt && tgt->lut_client_bitmap != NULL);
        if (!strcmp(ted->ted_lcd->lcd_uuid, tgt->lut_obd->obd_uuid.uuid))
                RETURN(0);
 
@@ -600,7 +606,7 @@ int tgt_client_add(const struct lu_env *env,  struct obd_export *exp, int idx)
 
        ENTRY;
 
-       LASSERT(tgt->lut_client_bitmap != NULL);
+       LASSERT(tgt && tgt->lut_client_bitmap != NULL);
        LASSERTF(idx >= 0, "%d\n", idx);
 
        if (!strcmp(ted->ted_lcd->lcd_uuid, tgt->lut_obd->obd_uuid.uuid) ||
@@ -637,6 +643,12 @@ int tgt_client_del(const struct lu_env *env, struct obd_export *exp)
 
        LASSERT(ted->ted_lcd);
 
+       if (unlikely(tgt == NULL)) {
+               CDEBUG(D_ERROR, "%s: No target for connected export\n",
+                      class_exp2obd(exp)->obd_name);
+               RETURN(-EINVAL);
+       }
+
        /* XXX if lcd_uuid were a real obd_uuid, I could use obd_uuid_equals */
        if (!strcmp((char *)ted->ted_lcd->lcd_uuid,
                    (char *)tgt->lut_obd->obd_uuid.uuid) ||