From: tappro Date: Thu, 10 Aug 2006 12:08:23 +0000 (+0000) Subject: fix issue with use-after-free if commit occurs while journal_stop() X-Git-Tag: v1_8_0_110~486^2~1216 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=d8c7b3cf56ba1c9cd54e92d8aec203c8b7f96341;p=fs%2Flustre-release.git fix issue with use-after-free if commit occurs while journal_stop() the ot_ref count is added into osd_thandle and osd_thandle is freed only when last reference is dropped. --- diff --git a/lustre/osd/osd_handler.c b/lustre/osd/osd_handler.c index 6cf9751..3639e18 100644 --- a/lustre/osd/osd_handler.c +++ b/lustre/osd/osd_handler.c @@ -217,6 +217,7 @@ static struct dt_index_operations osd_index_compat_ops; struct osd_thandle { struct thandle ot_super; + int ot_ref; handle_t *ot_handle; struct journal_callback ot_jcb; }; @@ -435,6 +436,27 @@ static int osd_param_is_sane(const struct osd_device *dev, return param->tp_credits <= osd_journal(dev)->j_max_transaction_buffers; } +static inline void osd_thandle_get(struct osd_thandle *oh) +{ + LASSERT(oh->ot_ref > 0); + oh->ot_ref ++; +} + +static inline void osd_thandle_put(struct osd_thandle *oh) +{ + LASSERT(oh->ot_ref > 0); + if (-- oh->ot_ref == 0) { + struct thandle *th = &oh->ot_super; + + if (th->th_dev != NULL) { + lu_device_put(&th->th_dev->dd_lu_dev); + th->th_dev = NULL; + } + lu_context_fini(&th->th_ctx); + OBD_FREE_PTR(oh); + } +} + static void osd_trans_commit_cb(struct journal_callback *jcb, int error) { struct osd_thandle *oh = container_of0(jcb, struct osd_thandle, ot_jcb); @@ -442,14 +464,7 @@ static void osd_trans_commit_cb(struct journal_callback *jcb, int error) /* there is no thread context available */ dt_txn_hook_commit(&th->th_ctx, th->th_dev, th); - - if (th->th_dev != NULL) { - lu_device_put(&th->th_dev->dd_lu_dev); - th->th_dev = NULL; - } - - lu_context_fini(&th->th_ctx); - OBD_FREE_PTR(oh); + osd_thandle_put(oh); } static struct thandle *osd_trans_start(const struct lu_context *ctx, @@ -479,9 +494,14 @@ static struct thandle *osd_trans_start(const struct lu_context *ctx, * XXX temporary stuff. Some abstraction layer should * be used. */ + jh = journal_start(osd_journal(dev), p->tp_credits); if (!IS_ERR(jh)) { oh->ot_handle = jh; + /* hmm, since oh init and start are done together + * the ref starts from 2 + */ + oh->ot_ref = 2; th = &oh->ot_super; th->th_dev = d; lu_device_get(&d->dd_lu_dev); @@ -527,17 +547,12 @@ static void osd_trans_stop(const struct lu_context *ctx, struct thandle *th) if (result != 0) CERROR("Failure to stop transaction: %d\n", result); oh->ot_handle = NULL; + osd_thandle_put(oh); LASSERT(oti->oti_txns == 1); LASSERT(oti->oti_r_locks == 0); LASSERT(oti->oti_w_locks == 0); oti->oti_txns--; } -/* - if (th->th_dev != NULL) { - lu_device_put(&th->th_dev->dd_lu_dev); - th->th_dev = NULL; - } -*/ EXIT; }