git: 70910e4b55ca - main - nfscl: Acquire a refcount on "cred" for mirrored pNFS RPCs
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 03 May 2022 14:23:59 UTC
The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=70910e4b55ca976ca0ad4aa3e34252ba148a6126 commit 70910e4b55ca976ca0ad4aa3e34252ba148a6126 Author: Rick Macklem <rmacklem@FreeBSD.org> AuthorDate: 2022-05-03 14:22:15 +0000 Commit: Rick Macklem <rmacklem@FreeBSD.org> CommitDate: 2022-05-03 14:22:15 +0000 nfscl: Acquire a refcount on "cred" for mirrored pNFS RPCs When the NFSv4.1/4.2 client is doing a pnfs mount to mirrored DS(s), asynchronous threads are used to do the RPCs against the DS(s) concurrently. If a DS is slow to reply, it is possible for the "cred" to be free'd before the asynchronous thread is done with it, causing a panic/crash. This patch fixes the problem by acquiring a refcount on the "cred" while it is being used by the asynchronous thread for a DS RPC. This bug was found during a recent IETF NFSv4 testing event. This bug only affects "pnfs" mounts to mirrored pNFS servers. MFC after: 2 weeks --- sys/fs/nfsclient/nfs_clrpcops.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index 9d19114ab07c..83ce96107ecc 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -7010,6 +7010,7 @@ start_writedsmir(void *arg, int pending) drpc->fhp, drpc->m, drpc->vers, drpc->minorvers, drpc->cred, drpc->p); drpc->done = 1; + crfree(drpc->cred); NFSCL_DEBUG(4, "start_writedsmir: err=%d\n", drpc->err); } @@ -7037,7 +7038,7 @@ nfsio_writedsmir(vnode_t vp, int *iomode, int *must_commit, drpc->m = m; drpc->vers = vers; drpc->minorvers = minorvers; - drpc->cred = cred; + drpc->cred = crhold(cred); drpc->p = p; drpc->inprog = 0; ret = EIO; @@ -7045,9 +7046,11 @@ nfsio_writedsmir(vnode_t vp, int *iomode, int *must_commit, ret = nfs_pnfsio(start_writedsmir, drpc); NFSCL_DEBUG(4, "nfsio_writedsmir: nfs_pnfsio=%d\n", ret); } - if (ret != 0) + if (ret != 0) { error = nfsrpc_writedsmir(vp, iomode, &drpc->must_commit, stateidp, dsp, off, len, fhp, m, vers, minorvers, cred, p); + crfree(drpc->cred); + } NFSCL_DEBUG(4, "nfsio_writedsmir: error=%d\n", error); return (error); } @@ -7195,6 +7198,7 @@ start_commitds(void *arg, int pending) drpc->dsp, drpc->fhp, drpc->vers, drpc->minorvers, drpc->cred, drpc->p); drpc->done = 1; + crfree(drpc->cred); NFSCL_DEBUG(4, "start_commitds: err=%d\n", drpc->err); } @@ -7217,7 +7221,7 @@ nfsio_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp, drpc->fhp = fhp; drpc->vers = vers; drpc->minorvers = minorvers; - drpc->cred = cred; + drpc->cred = crhold(cred); drpc->p = p; drpc->inprog = 0; ret = EIO; @@ -7225,9 +7229,11 @@ nfsio_commitds(vnode_t vp, uint64_t offset, int cnt, struct nfsclds *dsp, ret = nfs_pnfsio(start_commitds, drpc); NFSCL_DEBUG(4, "nfsio_commitds: nfs_pnfsio=%d\n", ret); } - if (ret != 0) + if (ret != 0) { error = nfsrpc_commitds(vp, offset, cnt, dsp, fhp, vers, minorvers, cred, p); + crfree(drpc->cred); + } NFSCL_DEBUG(4, "nfsio_commitds: error=%d\n", error); return (error); } @@ -7334,11 +7340,12 @@ start_adviseds(void *arg, int pending) drpc->advise, drpc->dsp, drpc->fhp, drpc->vers, drpc->minorvers, drpc->cred, drpc->p); drpc->done = 1; + crfree(drpc->cred); NFSCL_DEBUG(4, "start_adviseds: err=%d\n", drpc->err); } /* - * Set up the commit DS mirror call for the pNFS I/O thread. + * Set up the advise DS mirror call for the pNFS I/O thread. */ static int nfsio_adviseds(vnode_t vp, uint64_t offset, int cnt, int advise, @@ -7357,7 +7364,7 @@ nfsio_adviseds(vnode_t vp, uint64_t offset, int cnt, int advise, drpc->fhp = fhp; drpc->vers = vers; drpc->minorvers = minorvers; - drpc->cred = cred; + drpc->cred = crhold(cred); drpc->p = p; drpc->inprog = 0; ret = EIO; @@ -7365,9 +7372,11 @@ nfsio_adviseds(vnode_t vp, uint64_t offset, int cnt, int advise, ret = nfs_pnfsio(start_adviseds, drpc); NFSCL_DEBUG(4, "nfsio_adviseds: nfs_pnfsio=%d\n", ret); } - if (ret != 0) + if (ret != 0) { error = nfsrpc_adviseds(vp, offset, cnt, advise, dsp, fhp, vers, minorvers, cred, p); + crfree(drpc->cred); + } NFSCL_DEBUG(4, "nfsio_adviseds: error=%d\n", error); return (error); }