mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 08:02:27 +02:00
nfsd: call op_release, even when op_func returns an error
For ops with "trivial" replies, nfsd4_encode_operation will shortcut
most of the encoding work and skip to just marshalling up the status.
One of the things it skips is calling op_release. This could cause a
memory leak in the layoutget codepath if there is an error at an
inopportune time.
Have the compound processing engine always call op_release, even when
op_func sets an error in op->status. With this change, we also need
nfsd4_block_get_device_info_scsi to set the gd_device pointer to NULL
on error to avoid a double free.
Reported-by: Zhi Li <yieli@redhat.com>
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2181403
Fixes: 34b1744c91 ("nfsd4: define ->op_release for compound ops")
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
804d8e0a6e
commit
15a8b55dbb
|
|
@ -297,6 +297,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
|
||||||
|
|
||||||
out_free_dev:
|
out_free_dev:
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
|
gdp->gd_device = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5400,10 +5400,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||||
__be32 *p;
|
__be32 *p;
|
||||||
|
|
||||||
p = xdr_reserve_space(xdr, 8);
|
p = xdr_reserve_space(xdr, 8);
|
||||||
if (!p) {
|
if (!p)
|
||||||
WARN_ON_ONCE(1);
|
goto release;
|
||||||
return;
|
|
||||||
}
|
|
||||||
*p++ = cpu_to_be32(op->opnum);
|
*p++ = cpu_to_be32(op->opnum);
|
||||||
post_err_offset = xdr->buf->len;
|
post_err_offset = xdr->buf->len;
|
||||||
|
|
||||||
|
|
@ -5418,8 +5416,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||||
op->status = encoder(resp, op->status, &op->u);
|
op->status = encoder(resp, op->status, &op->u);
|
||||||
if (op->status)
|
if (op->status)
|
||||||
trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
|
trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
|
||||||
if (opdesc && opdesc->op_release)
|
|
||||||
opdesc->op_release(&op->u);
|
|
||||||
xdr_commit_encode(xdr);
|
xdr_commit_encode(xdr);
|
||||||
|
|
||||||
/* nfsd4_check_resp_size guarantees enough room for error status */
|
/* nfsd4_check_resp_size guarantees enough room for error status */
|
||||||
|
|
@ -5460,6 +5456,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
|
||||||
}
|
}
|
||||||
status:
|
status:
|
||||||
*p = op->status;
|
*p = op->status;
|
||||||
|
release:
|
||||||
|
if (opdesc && opdesc->op_release)
|
||||||
|
opdesc->op_release(&op->u);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user