From: John L. Hammond Date: Wed, 10 Jul 2013 20:45:18 +0000 (-0500) Subject: LU-3233 mdt: validate open handle cookies X-Git-Tag: 2.4.53~68 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=419e094e39885195caa7d652cc4dd800402b3079 LU-3233 mdt: validate open handle cookies Add a const void *h_owner member to struct portals_handle. Add a const void *owner parameter to class_handle2object() which must be matched by the h_owner member of the handle in addition to the cookie. Adjust the callers of class_handle2object() accordingly, using NULL as the argument to the owner parameter, except in the case of mdt_handle2mfd() where we add an explicit mdt_export_data parameter which we use as the owner when searching for a MFD. When allocating a new MFD, pass a pointer to the mdt_export_data into mdt_mfd_new() and store it in h_owner. This allows the MDT to validate that the client has not sent the wrong open handle cookie, or sent the right cookie to the wrong MDT. Signed-off-by: John L. Hammond Change-Id: I4c26504d808db0c27cfc2f8ebcf7e1fa19719170 Reviewed-on: http://review.whamcloud.com/6938 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Fan Yong Reviewed-by: Mike Pershin --- diff --git a/lustre/include/lustre_handles.h b/lustre/include/lustre_handles.h index 035ae06..496887e 100644 --- a/lustre/include/lustre_handles.h +++ b/lustre/include/lustre_handles.h @@ -79,7 +79,8 @@ struct portals_handle_ops { struct portals_handle { cfs_list_t h_link; __u64 h_cookie; - struct portals_handle_ops *h_ops; + const void *h_owner; + struct portals_handle_ops *h_ops; /* newly added fields to handle the RCU issue. -jxiong */ cfs_rcu_head_t h_rcu; @@ -96,7 +97,7 @@ void class_handle_hash(struct portals_handle *, struct portals_handle_ops *ops); void class_handle_unhash(struct portals_handle *); void class_handle_hash_back(struct portals_handle *); -void *class_handle2object(__u64 cookie); +void *class_handle2object(__u64 cookie, const void *owner); void class_handle_free_cb(cfs_rcu_head_t *); int class_handle_init(void); void class_handle_cleanup(void); diff --git a/lustre/ldlm/ldlm_lock.c b/lustre/ldlm/ldlm_lock.c index 1e17527..334de9c 100644 --- a/lustre/ldlm/ldlm_lock.c +++ b/lustre/ldlm/ldlm_lock.c @@ -610,7 +610,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, LASSERT(handle); - lock = class_handle2object(handle->cookie); + lock = class_handle2object(handle->cookie, NULL); if (lock == NULL) RETURN(NULL); diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index 767ca73..2c7f854 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -105,10 +105,10 @@ static inline void lov_put_reqset(struct lov_request_set *set) } static inline struct lov_lock_handles * -lov_handle2llh(struct lustre_handle *handle) +lov_handle2llh(const struct lustre_handle *handle) { - LASSERT(handle != NULL); - return(class_handle2object(handle->cookie)); + LASSERT(handle != NULL); + return class_handle2object(handle->cookie, NULL); } static inline void lov_llh_put(struct lov_lock_handles *llh) diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index 8b204de..8f813d8 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -760,8 +760,9 @@ void mdt_mfd_set_mode(struct mdt_file_data *mfd, int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc); -struct mdt_file_data *mdt_handle2mfd(struct mdt_thread_info *, - const struct lustre_handle *); +struct mdt_file_data *mdt_handle2mfd(struct mdt_export_data *med, + const struct lustre_handle *handle, + bool is_replay); enum { MDT_IOEPOCH_CLOSED = 0, @@ -782,7 +783,7 @@ int mdt_object_is_som_enabled(struct mdt_object *mo); int mdt_write_get(struct mdt_object *o); void mdt_write_put(struct mdt_object *o); int mdt_write_read(struct mdt_object *o); -struct mdt_file_data *mdt_mfd_new(void); +struct mdt_file_data *mdt_mfd_new(const struct mdt_export_data *med); int mdt_mfd_close(struct mdt_thread_info *info, struct mdt_file_data *mfd); void mdt_mfd_free(struct mdt_file_data *mfd); int mdt_close(struct mdt_thread_info *info); diff --git a/lustre/mdt/mdt_open.c b/lustre/mdt/mdt_open.c index 6ac5eee..f408eba 100644 --- a/lustre/mdt/mdt_open.c +++ b/lustre/mdt/mdt_open.c @@ -58,18 +58,20 @@ static struct portals_handle_ops mfd_handle_ops = { /* Create a new mdt_file_data struct, initialize it, * and insert it to global hash table */ -struct mdt_file_data *mdt_mfd_new(void) +struct mdt_file_data *mdt_mfd_new(const struct mdt_export_data *med) { - struct mdt_file_data *mfd; - ENTRY; + struct mdt_file_data *mfd; + ENTRY; - OBD_ALLOC_PTR(mfd); - if (mfd != NULL) { - CFS_INIT_LIST_HEAD(&mfd->mfd_handle.h_link); - CFS_INIT_LIST_HEAD(&mfd->mfd_list); + OBD_ALLOC_PTR(mfd); + if (mfd != NULL) { + CFS_INIT_LIST_HEAD(&mfd->mfd_handle.h_link); + mfd->mfd_handle.h_owner = med; + CFS_INIT_LIST_HEAD(&mfd->mfd_list); class_handle_hash(&mfd->mfd_handle, &mfd_handle_ops); - } - RETURN(mfd); + } + + RETURN(mfd); } /* @@ -77,25 +79,25 @@ struct mdt_file_data *mdt_mfd_new(void) * In case of replay the handle is obsoleted * but mfd can be found in mfd list by that handle */ -struct mdt_file_data *mdt_handle2mfd(struct mdt_thread_info *info, - const struct lustre_handle *handle) +struct mdt_file_data *mdt_handle2mfd(struct mdt_export_data *med, + const struct lustre_handle *handle, + bool is_replay) { - struct ptlrpc_request *req = mdt_info_req(info); - struct mdt_file_data *mfd; - ENTRY; + struct mdt_file_data *mfd; + ENTRY; - LASSERT(handle != NULL); - mfd = class_handle2object(handle->cookie); - /* during dw/setattr replay the mfd can be found by old handle */ - if (mfd == NULL && req_is_replay(req)) { - struct mdt_export_data *med = &req->rq_export->exp_mdt_data; - cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) { - if (mfd->mfd_old_handle.cookie == handle->cookie) - RETURN (mfd); - } - mfd = NULL; - } - RETURN (mfd); + LASSERT(handle != NULL); + mfd = class_handle2object(handle->cookie, med); + /* during dw/setattr replay the mfd can be found by old handle */ + if (mfd == NULL && is_replay) { + cfs_list_for_each_entry(mfd, &med->med_open_head, mfd_list) { + if (mfd->mfd_old_handle.cookie == handle->cookie) + RETURN(mfd); + } + mfd = NULL; + } + + RETURN(mfd); } /* free mfd */ @@ -725,76 +727,77 @@ static int mdt_mfd_open(struct mdt_thread_info *info, struct mdt_object *p, if (rc) GOTO(err_out, rc); - mfd = mdt_mfd_new(); - if (mfd != NULL) { - /* - * Keep a reference on this object for this open, and is - * released by mdt_mfd_close(). - */ - mdt_object_get(info->mti_env, o); + mfd = mdt_mfd_new(med); + if (mfd == NULL) + GOTO(err_out, rc = -ENOMEM); - /* - * @flags is always not zero. At least it should be FMODE_READ, - * FMODE_WRITE or MDS_FMODE_EXEC. - */ - LASSERT(flags != 0); - - /* Open handling. */ - mdt_mfd_set_mode(mfd, flags); - - mfd->mfd_object = o; - mfd->mfd_xid = req->rq_xid; - - /* replay handle */ - if (req_is_replay(req)) { - struct mdt_file_data *old_mfd; - /* Check wheather old cookie already exist in - * the list, becasue when do recovery, client - * might be disconnected from server, and - * restart replay, so there maybe some orphan - * mfd here, we should remove them */ - LASSERT(info->mti_rr.rr_handle != NULL); - old_mfd = mdt_handle2mfd(info, info->mti_rr.rr_handle); - if (old_mfd) { - CDEBUG(D_HA, "del orph mfd %p fid=("DFID") " - "cookie=" LPX64"\n", mfd, - PFID(mdt_object_fid(mfd->mfd_object)), - info->mti_rr.rr_handle->cookie); - spin_lock(&med->med_open_lock); - class_handle_unhash(&old_mfd->mfd_handle); - cfs_list_del_init(&old_mfd->mfd_list); - spin_unlock(&med->med_open_lock); - /* no attr update for that close */ - la->la_valid = 0; - ma->ma_valid |= MA_FLAGS; - ma->ma_attr_flags |= MDS_RECOV_OPEN; - mdt_mfd_close(info, old_mfd); - ma->ma_attr_flags &= ~MDS_RECOV_OPEN; - ma->ma_valid &= ~MA_FLAGS; - } - CDEBUG(D_HA, "Store old cookie "LPX64" in new mfd\n", - info->mti_rr.rr_handle->cookie); - mfd->mfd_old_handle.cookie = - info->mti_rr.rr_handle->cookie; - } - repbody->handle.cookie = mfd->mfd_handle.h_cookie; + /* + * Keep a reference on this object for this open, and is + * released by mdt_mfd_close(). + */ + mdt_object_get(info->mti_env, o); - if (req->rq_export->exp_disconnected) { - spin_lock(&med->med_open_lock); - class_handle_unhash(&mfd->mfd_handle); - cfs_list_del_init(&mfd->mfd_list); - spin_unlock(&med->med_open_lock); - mdt_mfd_close(info, mfd); - } else { + /* + * @flags is always not zero. At least it should be FMODE_READ, + * FMODE_WRITE or MDS_FMODE_EXEC. + */ + LASSERT(flags != 0); + + /* Open handling. */ + mdt_mfd_set_mode(mfd, flags); + + mfd->mfd_object = o; + mfd->mfd_xid = req->rq_xid; + + /* replay handle */ + if (req_is_replay(req)) { + struct mdt_file_data *old_mfd; + /* Check wheather old cookie already exist in + * the list, becasue when do recovery, client + * might be disconnected from server, and + * restart replay, so there maybe some orphan + * mfd here, we should remove them */ + LASSERT(info->mti_rr.rr_handle != NULL); + old_mfd = mdt_handle2mfd(med, info->mti_rr.rr_handle, true); + if (old_mfd != NULL) { + CDEBUG(D_HA, "delete orphan mfd = %p, fid = "DFID", " + "cookie = "LPX64"\n", mfd, + PFID(mdt_object_fid(mfd->mfd_object)), + info->mti_rr.rr_handle->cookie); spin_lock(&med->med_open_lock); - cfs_list_add(&mfd->mfd_list, &med->med_open_head); + class_handle_unhash(&old_mfd->mfd_handle); + cfs_list_del_init(&old_mfd->mfd_list); spin_unlock(&med->med_open_lock); - } + /* no attr update for that close */ + la->la_valid = 0; + ma->ma_valid |= MA_FLAGS; + ma->ma_attr_flags |= MDS_RECOV_OPEN; + mdt_mfd_close(info, old_mfd); + ma->ma_attr_flags &= ~MDS_RECOV_OPEN; + ma->ma_valid &= ~MA_FLAGS; + } - mdt_empty_transno(info, rc); - } else { - GOTO(err_out, rc = -ENOMEM); - } + CDEBUG(D_HA, "Store old cookie "LPX64" in new mfd\n", + info->mti_rr.rr_handle->cookie); + + mfd->mfd_old_handle.cookie = info->mti_rr.rr_handle->cookie; + } + + repbody->handle.cookie = mfd->mfd_handle.h_cookie; + + if (req->rq_export->exp_disconnected) { + spin_lock(&med->med_open_lock); + class_handle_unhash(&mfd->mfd_handle); + cfs_list_del_init(&mfd->mfd_list); + spin_unlock(&med->med_open_lock); + mdt_mfd_close(info, mfd); + } else { + spin_lock(&med->med_open_lock); + cfs_list_add(&mfd->mfd_list, &med->med_open_head); + spin_unlock(&med->med_open_lock); + } + + mdt_empty_transno(info, rc); RETURN(rc); @@ -1881,7 +1884,8 @@ int mdt_close(struct mdt_thread_info *info) med = &req->rq_export->exp_mdt_data; spin_lock(&med->med_open_lock); - mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle); + mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle, + req_is_replay(req)); if (mdt_mfd_closed(mfd)) { spin_unlock(&med->med_open_lock); CDEBUG(D_INODE, "no handle for file close: fid = "DFID @@ -1956,7 +1960,8 @@ int mdt_done_writing(struct mdt_thread_info *info) med = &info->mti_exp->exp_mdt_data; spin_lock(&med->med_open_lock); - mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle); + mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle, + req_is_replay(req)); if (mfd == NULL) { spin_unlock(&med->med_open_lock); CDEBUG(D_INODE, "no handle for done write: fid = "DFID diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index f8ab022..c861792 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -521,7 +521,7 @@ static int mdt_reint_setattr(struct mdt_thread_info *info, if (rc) GOTO(out_put, rc); - mfd = mdt_mfd_new(); + mfd = mdt_mfd_new(med); if (mfd == NULL) { mdt_write_put(mo); GOTO(out_put, rc = -ENOMEM); @@ -549,7 +549,8 @@ static int mdt_reint_setattr(struct mdt_thread_info *info, LASSERT(info->mti_ioepoch); spin_lock(&med->med_open_lock); - mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle); + mfd = mdt_handle2mfd(med, &info->mti_ioepoch->handle, + req_is_replay(req)); if (mfd == NULL) { spin_unlock(&med->med_open_lock); CDEBUG(D_INODE, "no handle for file close: " diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index f8c2b93..91b6262 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -716,8 +716,8 @@ struct obd_export *class_conn2export(struct lustre_handle *conn) } CDEBUG(D_INFO, "looking for export cookie "LPX64"\n", conn->cookie); - export = class_handle2object(conn->cookie); - RETURN(export); + export = class_handle2object(conn->cookie, NULL); + RETURN(export); } EXPORT_SYMBOL(class_conn2export); diff --git a/lustre/obdclass/lustre_handles.c b/lustre/obdclass/lustre_handles.c index 268545b..e090a8a 100644 --- a/lustre/obdclass/lustre_handles.c +++ b/lustre/obdclass/lustre_handles.c @@ -164,7 +164,7 @@ void class_handle_hash_back(struct portals_handle *h) } EXPORT_SYMBOL(class_handle_hash_back); -void *class_handle2object(__u64 cookie) +void *class_handle2object(__u64 cookie, const void *owner) { struct handle_bucket *bucket; struct portals_handle *h; @@ -179,7 +179,7 @@ void *class_handle2object(__u64 cookie) rcu_read_lock(); list_for_each_entry_rcu(h, &bucket->head, h_link) { - if (h->h_cookie != cookie) + if (h->h_cookie != cookie || h->h_owner != owner) continue; spin_lock(&h->h_lock);