mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
nfsclient: Propagate copyin() errors from nfsm_uiombuf()
Approved by: so Security: SA-23:18.nfsclient Reviewed by: rmacklem Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
70547544ce
commit
6fa843f6e6
|
@ -370,7 +370,7 @@ int nfsrpc_destroysession(struct nfsmount *, struct nfsclsession *,
|
||||||
struct ucred *, NFSPROC_T *);
|
struct ucred *, NFSPROC_T *);
|
||||||
|
|
||||||
/* nfs_clcomsubs.c */
|
/* 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);
|
struct mbuf *nfsm_uiombuflist(struct uio *, int, u_int);
|
||||||
u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
|
u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
|
||||||
int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
|
int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
|
||||||
|
|
|
@ -51,12 +51,12 @@ NFSCLSTATEMUTEX;
|
||||||
* copies a uio scatter/gather list to an mbuf chain.
|
* copies a uio scatter/gather list to an mbuf chain.
|
||||||
* NOTE: can only handle iovcnt == 1
|
* NOTE: can only handle iovcnt == 1
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
|
nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
|
||||||
{
|
{
|
||||||
char *uiocp;
|
char *uiocp;
|
||||||
struct mbuf *mp, *mp2;
|
struct mbuf *mp, *mp2;
|
||||||
int xfer, left, mlen;
|
int error, xfer, left, mlen;
|
||||||
int uiosiz, clflg, rem;
|
int uiosiz, clflg, rem;
|
||||||
char *mcp, *tcp;
|
char *mcp, *tcp;
|
||||||
|
|
||||||
|
@ -104,8 +104,11 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
|
||||||
xfer = (left > mlen) ? mlen : left;
|
xfer = (left > mlen) ? mlen : left;
|
||||||
if (uiop->uio_segflg == UIO_SYSSPACE)
|
if (uiop->uio_segflg == UIO_SYSSPACE)
|
||||||
NFSBCOPY(uiocp, mcp, xfer);
|
NFSBCOPY(uiocp, mcp, xfer);
|
||||||
else
|
else {
|
||||||
copyin(uiocp, mcp, xfer);
|
error = copyin(uiocp, mcp, xfer);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
mp->m_len += xfer;
|
mp->m_len += xfer;
|
||||||
left -= xfer;
|
left -= xfer;
|
||||||
uiocp += xfer;
|
uiocp += xfer;
|
||||||
|
@ -148,6 +151,7 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *uiop, int siz)
|
||||||
}
|
}
|
||||||
nd->nd_bpos = mcp;
|
nd->nd_bpos = mcp;
|
||||||
nd->nd_mb = mp;
|
nd->nd_mb = mp;
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -160,7 +164,7 @@ nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
|
||||||
{
|
{
|
||||||
char *uiocp;
|
char *uiocp;
|
||||||
struct mbuf *mp, *mp2, *firstmp;
|
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;
|
int uiosiz, clflg;
|
||||||
char *mcp, *tcp;
|
char *mcp, *tcp;
|
||||||
|
|
||||||
|
@ -218,8 +222,13 @@ nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
|
||||||
xfer = (left > mlen) ? mlen : left;
|
xfer = (left > mlen) ? mlen : left;
|
||||||
if (uiop->uio_segflg == UIO_SYSSPACE)
|
if (uiop->uio_segflg == UIO_SYSSPACE)
|
||||||
NFSBCOPY(uiocp, mcp, xfer);
|
NFSBCOPY(uiocp, mcp, xfer);
|
||||||
else
|
else {
|
||||||
copyin(uiocp, mcp, xfer);
|
error = copyin(uiocp, mcp, xfer);
|
||||||
|
if (error != 0) {
|
||||||
|
m_freem(firstmp);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
mp->m_len += xfer;
|
mp->m_len += xfer;
|
||||||
mcp += xfer;
|
mcp += xfer;
|
||||||
if (maxext > 0) {
|
if (maxext > 0) {
|
||||||
|
|
|
@ -2104,7 +2104,12 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
|
||||||
*tl++ = x; /* total to this offset */
|
*tl++ = x; /* total to this offset */
|
||||||
*tl = x; /* size of this write */
|
*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
|
* Although it is tempting to do a normal Getattr Op in the
|
||||||
* NFSv4 compound, the result can be a nearly hung client
|
* NFSv4 compound, the result can be a nearly hung client
|
||||||
|
@ -6361,6 +6366,10 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
||||||
iovlen = uiop->uio_iov->iov_len;
|
iovlen = uiop->uio_iov->iov_len;
|
||||||
m = nfsm_uiombuflist(uiop, len,
|
m = nfsm_uiombuflist(uiop, len,
|
||||||
0);
|
0);
|
||||||
|
if (m == NULL) {
|
||||||
|
error = EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tdrpc = drpc = malloc(sizeof(*drpc) *
|
tdrpc = drpc = malloc(sizeof(*drpc) *
|
||||||
(mirrorcnt - 1), M_TEMP, M_WAITOK |
|
(mirrorcnt - 1), M_TEMP, M_WAITOK |
|
||||||
|
@ -6933,7 +6942,11 @@ nfsrpc_writeds(vnode_t vp, struct uio *uiop, int *iomode, int *must_commit,
|
||||||
*tl++ = txdr_unsigned(len);
|
*tl++ = txdr_unsigned(len);
|
||||||
*tl++ = txdr_unsigned(*iomode);
|
*tl++ = txdr_unsigned(*iomode);
|
||||||
*tl = txdr_unsigned(len);
|
*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;
|
nrp = dsp->nfsclds_sockp;
|
||||||
if (nrp == NULL)
|
if (nrp == NULL)
|
||||||
/* If NULL, use the MDS socket. */
|
/* If NULL, use the MDS socket. */
|
||||||
|
@ -9057,7 +9070,11 @@ nfsrpc_setextattr(vnode_t vp, const char *name, struct uio *uiop,
|
||||||
nfsm_strtom(nd, name, strlen(name));
|
nfsm_strtom(nd, name, strlen(name));
|
||||||
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||||
*tl = txdr_unsigned(uiop->uio_resid);
|
*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);
|
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
|
||||||
*tl = txdr_unsigned(NFSV4OP_GETATTR);
|
*tl = txdr_unsigned(NFSV4OP_GETATTR);
|
||||||
NFSGETATTR_ATTRBIT(&attrbits);
|
NFSGETATTR_ATTRBIT(&attrbits);
|
||||||
|
|
|
@ -1587,7 +1587,7 @@ ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
|
||||||
error = nfscl_doiods(vp, uiop, NULL, NULL,
|
error = nfscl_doiods(vp, uiop, NULL, NULL,
|
||||||
NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
|
NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
|
||||||
NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
|
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,
|
error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
|
||||||
&attrflag);
|
&attrflag);
|
||||||
if (attrflag) {
|
if (attrflag) {
|
||||||
|
@ -1618,7 +1618,7 @@ ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
|
||||||
error = nfscl_doiods(vp, uiop, iomode, must_commit,
|
error = nfscl_doiods(vp, uiop, iomode, must_commit,
|
||||||
NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
|
NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
|
||||||
NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
|
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,
|
error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
|
||||||
uiop->uio_td, &nfsva, &attrflag, called_from_strategy,
|
uiop->uio_td, &nfsva, &attrflag, called_from_strategy,
|
||||||
ioflag);
|
ioflag);
|
||||||
|
|
Loading…
Reference in a new issue