From 86e6d90f69d8c34f6af4c6e7eb7cad3e60b7278e Mon Sep 17 00:00:00 2001 From: Bobi Jam Date: Tue, 2 Nov 2021 15:27:59 +0800 Subject: [PATCH] LU-14781 osp: osp_object_free access NULL pointer If a osp_object is created by multiple threads at the same time, lu_object_find_at() could allocate an osp_object without object initialization, before hash inserting of the object, it find another object has been created and inserted by another thread, it will free the unintialized osp_object, and osp_object_free() will access an uninitialized list_head (opo_xattr_list). This patch initialize osp_object::opo_xattr_list in its allocation function. Call trace: lu_object_free.isra.30+0xf2/0x170 [obdclass] lu_object_find_at+0x496/0x930 [obdclass] lod_initialize_objects+0x3e4/0xba0 [lod] lod_parse_striping+0x693/0xc20 [lod] lod_striping_load+0x2b2/0x660 [lod] lod_declare_destroy+0x12b/0x600 [lod] mdd_declare_finish_unlink+0x91/0x210 [mdd] mdd_unlink+0x48f/0xab0 [mdd] mdt_reint_unlink+0xc32/0x1550 [mdt] mdt_reint_rec+0x83/0x210 [mdt] mdt_reint_internal+0x6e1/0xb00 [mdt] mdt_reint+0x67/0x140 [mdt] tgt_request_handle+0xaee/0x15f0 [ptlrpc] ptlrpc_server_handle_request+0x24b/0xab0 [ptlrpc] ptlrpc_main+0xb34/0x1470 [ptlrpc] kthread+0xd1/0xe0 Signed-off-by: Bobi Jam Change-Id: Ib86aca5b41e94a1758f177655ea3a0f680335e0f Reviewed-on: https://review.whamcloud.com/45442 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Alex Zhuravlev --- lustre/osp/osp_dev.c | 21 +++++++++++++-------- lustre/osp/osp_object.c | 11 ++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lustre/osp/osp_dev.c b/lustre/osp/osp_dev.c index 4413ef8..c316b52 100644 --- a/lustre/osp/osp_dev.c +++ b/lustre/osp/osp_dev.c @@ -112,33 +112,38 @@ static struct lu_object *osp_object_alloc(const struct lu_env *env, const struct lu_object_header *hdr, struct lu_device *d) { - struct lu_object_header *h = NULL; - struct osp_object *o; - struct lu_object *l; + struct osp_object *o; OBD_SLAB_ALLOC_PTR_GFP(o, osp_object_kmem, GFP_NOFS); if (o != NULL) { - l = &o->opo_obj.do_lu; + struct lu_object *l = &o->opo_obj.do_lu; /* If hdr is NULL, it means the object is not built * from the top dev(MDT/OST), usually it happens when * building striped object, like data object on MDT or * striped object for directory */ if (hdr == NULL) { - h = &o->opo_header; + struct lu_object_header *h = &o->opo_header; + lu_object_header_init(h); dt_object_init(&o->opo_obj, h, d); lu_object_add_top(h, l); } else { - dt_object_init(&o->opo_obj, h, d); + dt_object_init(&o->opo_obj, NULL, d); } l->lo_ops = &osp_lu_obj_ops; + init_rwsem(&o->opo_sem); + INIT_LIST_HEAD(&o->opo_xattr_list); + INIT_LIST_HEAD(&o->opo_invalidate_cb_list); + spin_lock_init(&o->opo_lock); + init_rwsem(&o->opo_invalidate_sem); + return l; - } else { - return NULL; } + + return NULL; } /** diff --git a/lustre/osp/osp_object.c b/lustre/osp/osp_object.c index 8126eb0f..52a12c4 100644 --- a/lustre/osp/osp_object.c +++ b/lustre/osp/osp_object.c @@ -2285,15 +2285,12 @@ static const struct dt_object_operations osp_obj_ops = { static int osp_object_init(const struct lu_env *env, struct lu_object *o, const struct lu_object_conf *conf) { - struct osp_object *po = lu2osp_obj(o); - int rc = 0; + struct osp_object *po = lu2osp_obj(o); + int rc = 0; + ENTRY; - spin_lock_init(&po->opo_lock); o->lo_header->loh_attr |= LOHA_REMOTE; - INIT_LIST_HEAD(&po->opo_xattr_list); - INIT_LIST_HEAD(&po->opo_invalidate_cb_list); - init_rwsem(&po->opo_invalidate_sem); if (is_ost_obj(o)) { po->opo_obj.do_ops = &osp_obj_ops; @@ -2316,8 +2313,8 @@ static int osp_object_init(const struct lu_env *env, struct lu_object *o, rc = 0; } } - init_rwsem(&po->opo_sem); } + RETURN(rc); } -- 1.8.3.1