During initialization of unlockdata or lockdata structures, if acquiring the nfs_open_context fails, the current operation must be aborted to ensure the nfs_open_context remains valid after initialization completes. This is critical because both lock and unlock release callbacks dereference the nfs_open_context - an invalid context could lead to null pointer dereference. Fixes: faf5f49c2d9c ("NFSv4: Make NFS clean up byte range locks asynchronously") Fixes: a5d16a4d090b ("NFSv4: Convert LOCK rpc call into an asynchronous RPC call") Signed-off-by: Li Lingfeng <lilingfeng3@xxxxxxxxxx> --- fs/nfs/nfs4proc.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9f5689c43a50..d76cf0f79f9c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -7075,24 +7075,27 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, struct nfs4_state *state = lsp->ls_state; struct inode *inode = state->inode; struct nfs_lock_context *l_ctx; + struct nfs_open_context *open_ctx; p = kzalloc(sizeof(*p), GFP_KERNEL); if (p == NULL) return NULL; l_ctx = nfs_get_lock_context(ctx); - if (!IS_ERR(l_ctx)) { + if (!IS_ERR(l_ctx)) p->l_ctx = l_ctx; - } else { - kfree(p); - return NULL; - } + else + goto out_free; + /* Ensure we don't close file until we're done freeing locks! */ + open_ctx = get_nfs_open_context(ctx); + if (open_ctx) + p->ctx = open_ctx; + else + goto out_free; p->arg.fh = NFS_FH(inode); p->arg.fl = &p->fl; p->arg.seqid = seqid; p->res.seqid = seqid; p->lsp = lsp; - /* Ensure we don't close file until we're done freeing locks! */ - p->ctx = get_nfs_open_context(ctx); locks_init_lock(&p->fl); locks_copy_lock(&p->fl, fl); p->server = NFS_SERVER(inode); @@ -7100,6 +7103,9 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, nfs4_stateid_copy(&p->arg.stateid, &lsp->ls_stateid); spin_unlock(&state->state_lock); return p; +out_free: + kfree(p); + return NULL; } static void nfs4_locku_release_calldata(void *data) @@ -7327,6 +7333,8 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, p->lsp = lsp; p->server = server; p->ctx = get_nfs_open_context(ctx); + if (!p->ctx) + goto out_free_seqid; locks_init_lock(&p->fl); locks_copy_lock(&p->fl, fl); return p; -- 2.31.1