[LU-8811] mdc_close() may return a freed request in *request Created: 08/Nov/16  Updated: 21/Jul/17  Resolved: 17/Dec/16

Status: Resolved
Project: Lustre
Component/s: None
Affects Version/s: Lustre 2.9.0
Fix Version/s: Lustre 2.10.0

Type: Bug Priority: Minor
Reporter: John Hammond Assignee: John Hammond
Resolution: Fixed Votes: 0
Labels: mdc

Issue Links:
Related
is related to LU-8582 Interop: master<->b2_8 - sanity test... Resolved
Severity: 3
Rank (Obsolete): 9223372036854775807

 Description   

In mdc_close() if ptlrpc_request_pack() fails then a freed request is returned in *request.

static int mdc_close(struct obd_export *exp, struct md_op_data *op_data,
                     struct md_open_data *mod, struct ptlrpc_request **request)
{
...
        *request = NULL;
        if (OBD_FAIL_CHECK(OBD_FAIL_MDC_CLOSE))
                req = NULL;
        else
                req = ptlrpc_request_alloc(class_exp2cliimp(exp), req_fmt);
...
        rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, MDS_CLOSE);
        if (rc) {
                ptlrpc_request_free(req);
                GOTO(out, rc);
        }
...
out:
        if (mod) {
                if (rc != 0)
                        mod->mod_close_req = NULL;
                /* Since now, mod is accessed through open_req only,       
                 * thus close req does not keep a reference on mod anymore. */
                obd_mod_put(mod);
        }
        *request = req;

        RETURN(rc < 0 ? rc : saved_rc);
}

This will result in a use after free in ll_close_inode_openhandle() or ll_open_cleanup().

This was introduced by

commit 62713a8530349a75b7202c9bfc6be121409a0203
Author: Alexander Boyko <alexander.boyko@seagate.com>
Date:   Thu Dec 3 09:57:36 2015 +0300

    LU-5282 mdc: fix panic at mdc_free_open()
    
    Assertion was happened for open request when rq_replay is set
    to 1.
        ASSERTION(mod->mod_open_req->rq_replay == 0)
    But this situation is not fatal for client, and could happened
    when mdc_close() failed.
    The fix allow to free such requests. If mdc_close fail, MDS doesn`t
    receive close request from client. And in a worst case client would
    be evicted.
    
    The test recreates issue when mdc_close failed and
    client asserts:
       ASSERTION( mod->mod_open_req->rq_replay == 0 ) failed
    
    Signed-off-by: Alexander Boyko <alexander.boyko@seagate.com>
    Seagate-bug-id: MRP-3156
    Change-Id: I5f98901f633355849fc107149eadc9cf171819af
    Reviewed-on: http://review.whamcloud.com/17495
    Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
    Tested-by: Jenkins
    Tested-by: Maloo <hpdd-maloo@intel.com>
    Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
    Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>


 Comments   
Comment by Gerrit Updater [ 17/Nov/16 ]

John L. Hammond (john.hammond@intel.com) uploaded a new patch: http://review.whamcloud.com/23843
Subject: LU-8811 mdc: avoid returning freed request
Project: fs/lustre-release
Branch: master
Current Patch Set: 1
Commit: d0f9be5c9bfddebce501428ef50a5040c2821c2f

Comment by Gerrit Updater [ 17/Dec/16 ]

Oleg Drokin (oleg.drokin@intel.com) merged in patch https://review.whamcloud.com/23843/
Subject: LU-8811 mdc: avoid returning freed request
Project: fs/lustre-release
Branch: master
Current Patch Set:
Commit: d641bbe4fc1a81102456b16535309e90e1c10b53

Comment by Peter Jones [ 17/Dec/16 ]

Landed for 2.10

Generated at Sat Feb 10 02:20:45 UTC 2024 using Jira 9.4.14#940014-sha1:734e6822bbf0d45eff9af51f82432957f73aa32c.