Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Dec 2023 19:18:17 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 3f079b3f2f33 - releng/13.2 - nfsclient: Propagate copyin() errors from nfsm_uiombuf()
Message-ID:  <202312121918.3BCJIH67088224@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch releng/13.2 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=3f079b3f2f3371ae1c2a11d00a8ddfe183f4ecba

commit 3f079b3f2f3371ae1c2a11d00a8ddfe183f4ecba
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-12-12 01:04:56 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-12-12 19:15:39 +0000

    nfsclient: Propagate copyin() errors from nfsm_uiombuf()
    
    Approved by:    so
    Security:       SA-23:18.nfsclient
    Reviewed by:    rmacklem
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 6fa843f6e647a1a1e0e42af1e7abc9e903699f31)
    (cherry picked from commit f1d1d50e1d089f0bfcd38e5f08b1e8bf5a1d64c3)
---
 sys/fs/nfs/nfs_var.h             |  2 +-
 sys/fs/nfsclient/nfs_clcomsubs.c | 23 ++++++++++++++++-------
 sys/fs/nfsclient/nfs_clrpcops.c  | 23 ++++++++++++++++++++---
 sys/fs/nfsclient/nfs_clvnops.c   |  4 ++--
 4 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 9dd3be3d5c42..ac0c75b8d3f4 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -368,7 +368,7 @@ int nfsrpc_destroysession(struct nfsmount *, struct nfsclsession *,
     struct ucred *, NFSPROC_T *);
 
 /* nfs_clcomsubs.c */
-void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
+int nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
 struct mbuf *nfsm_uiombuflist(struct uio *, int, u_int);
 u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
 int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
diff --git a/sys/fs/nfsclient/nfs_clcomsubs.c b/sys/fs/nfsclient/nfs_clcomsubs.c
index 640d47fed93d..7aa7e3f84479 100644
--- a/sys/fs/nfsclient/nfs_clcomsubs.c
+++ b/sys/fs/nfsclient/nfs_clcomsubs.c
@@ -53,12 +53,12 @@ NFSCLSTATEMUTEX;
  * copies a uio scatter/gather list to an mbuf chain.
  * NOTE: can only handle iovcnt == 1
  */
-void
+int
 nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
 {
 	char *uiocp;
 	struct mbuf *mp, *mp2;
-	int xfer, left, mlen;
+	int error, xfer, left, mlen;
 	int uiosiz, clflg, rem;
 	char *mcp, *tcp;
 
@@ -106,8 +106,11 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
 			xfer = (left > mlen) ? mlen : left;
 			if (uiop->uio_segflg == UIO_SYSSPACE)
 				NFSBCOPY(uiocp, mcp, xfer);
-			else
-				copyin(uiocp, mcp, xfer);
+			else {
+				error = copyin(uiocp, mcp, xfer);
+				if (error != 0)
+					return (error);
+			}
 			mp->m_len += xfer;
 			left -= xfer;
 			uiocp += xfer;
@@ -150,6 +153,7 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
 	}
 	nd->nd_bpos = mcp;
 	nd->nd_mb = mp;
+	return (0);
 }
 
 /*
@@ -162,7 +166,7 @@ nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
 {
 	char *uiocp;
 	struct mbuf *mp, *mp2, *firstmp;
-	int extpg, extpgsiz = 0, i, left, mlen, rem, xfer;
+	int error, extpg, extpgsiz = 0, i, left, mlen, rem, xfer;
 	int uiosiz, clflg;
 	char *mcp, *tcp;
 
@@ -220,8 +224,13 @@ nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
 			xfer = (left > mlen) ? mlen : left;
 			if (uiop->uio_segflg == UIO_SYSSPACE)
 				NFSBCOPY(uiocp, mcp, xfer);
-			else
-				copyin(uiocp, mcp, xfer);
+			else {
+				error = copyin(uiocp, mcp, xfer);
+				if (error != 0) {
+					m_freem(firstmp);
+					return (NULL);
+				}
+			}
 			mp->m_len += xfer;
 			mcp += xfer;
 			if (maxext > 0) {
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 51c7bb25d357..854fad6c56c7 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1890,7 +1890,12 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
 			*tl++ = x;      /* total to this offset */
 			*tl = x;        /* size of this write */
 		}
-		nfsm_uiombuf(nd, uiop, len);
+		error = nfsm_uiombuf(nd, uiop, len);
+		if (error != 0) {
+			m_freem(nd->nd_mreq);
+			free(nd, M_TEMP);
+			return (error);
+		}
 		/*
 		 * Although it is tempting to do a normal Getattr Op in the
 		 * NFSv4 compound, the result can be a nearly hung client
@@ -5981,6 +5986,10 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
 						iovlen = uiop->uio_iov->iov_len;
 						m = nfsm_uiombuflist(uiop, len,
 						    0);
+						if (m == NULL) {
+							error = EFAULT;
+							break;
+						}
 					}
 					tdrpc = drpc = malloc(sizeof(*drpc) *
 					    (mirrorcnt - 1), M_TEMP, M_WAITOK |
@@ -6553,7 +6562,11 @@ nfsrpc_writeds(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
 		*tl++ = txdr_unsigned(len);
 	*tl++ = txdr_unsigned(*iomode);
 	*tl = txdr_unsigned(len);
-	nfsm_uiombuf(nd, uiop, len);
+	error = nfsm_uiombuf(nd, uiop, len);
+	if (error != 0) {
+		m_freem(nd->nd_mreq);
+		return (error);
+	}
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
 		/* If NULL, use the MDS socket. */
@@ -8639,7 +8652,11 @@ nfsrpc_setextattr(vnode_t vp, const char *name, struct uio *uiop,
 	nfsm_strtom(nd, name, strlen(name));
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(uiop->uio_resid);
-	nfsm_uiombuf(nd, uiop, uiop->uio_resid);
+	error = nfsm_uiombuf(nd, uiop, uiop->uio_resid);
+	if (error != 0) {
+		m_freem(nd->nd_mreq);
+		return (error);
+	}
 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
 	NFSGETATTR_ATTRBIT(&attrbits);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 02e5e3540d72..4fb76fce088e 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1579,7 +1579,7 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
 		error = nfscl_doiods(vp, uiop, NULL, NULL,
 		    NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
 	NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
-	if (error != 0)
+	if (error != 0 && error != EFAULT)
 		error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
 		    &attrflag, NULL);
 	if (attrflag) {
@@ -1610,7 +1610,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
 		error = nfscl_doiods(vp, uiop, iomode, must_commit,
 		    NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
 	NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
-	if (error != 0)
+	if (error != 0 && error != EFAULT)
 		error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
 		    uiop->uio_td, &nfsva, &attrflag, called_from_strategy,
 		    ioflag);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202312121918.3BCJIH67088224>