Skip to content

Commit 15a8b55

Browse files
jtlaytonchucklever
authored andcommitted
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 <[email protected]> Link: https://bugzilla.redhat.com/show_bug.cgi?id=2181403 Fixes: 34b1744 ("nfsd4: define ->op_release for compound ops") Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 804d8e0 commit 15a8b55

File tree

2 files changed

+6
-6
lines changed

2 files changed

+6
-6
lines changed

fs/nfsd/blocklayout.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
297297

298298
out_free_dev:
299299
kfree(dev);
300+
gdp->gd_device = NULL;
300301
return ret;
301302
}
302303

fs/nfsd/nfs4xdr.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5400,10 +5400,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
54005400
__be32 *p;
54015401

54025402
p = xdr_reserve_space(xdr, 8);
5403-
if (!p) {
5404-
WARN_ON_ONCE(1);
5405-
return;
5406-
}
5403+
if (!p)
5404+
goto release;
54075405
*p++ = cpu_to_be32(op->opnum);
54085406
post_err_offset = xdr->buf->len;
54095407

@@ -5418,8 +5416,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
54185416
op->status = encoder(resp, op->status, &op->u);
54195417
if (op->status)
54205418
trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
5421-
if (opdesc && opdesc->op_release)
5422-
opdesc->op_release(&op->u);
54235419
xdr_commit_encode(xdr);
54245420

54255421
/* 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)
54605456
}
54615457
status:
54625458
*p = op->status;
5459+
release:
5460+
if (opdesc && opdesc->op_release)
5461+
opdesc->op_release(&op->u);
54635462
}
54645463

54655464
/*

0 commit comments

Comments
 (0)