untrusted comment: verify with openbsd-63-base.pub
RWRxzbLwAd76ZdDqZo6LADrtHmdrzlxmicibn0H6YtBtSD0PIdSpq296Vs3tG2I3Uv4hUVPgZwPKOiRQ/tEt+3BKs/Iw5XK7UAU=
OpenBSD 6.3 errata 029, February 5, 2019:
Incorrect length checks in the NFS server and client can lead to
crashes and other errors.
Apply by doing:
signify -Vep /etc/signify/openbsd-63-base.pub -x 029_nfs.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
Index: sys/nfs/nfs_serv.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_serv.c,v
retrieving revision 1.112
diff -u -p -r1.112 nfs_serv.c
--- sys/nfs/nfs_serv.c 30 Dec 2017 20:47:00 -0000 1.112
+++ sys/nfs/nfs_serv.c 21 Jan 2019 22:28:46 -0000
@@ -1715,7 +1715,7 @@ nfsrv_symlink(struct nfsrv_descript *nfs
nfsm_mtouio(&io, len2);
if (!info.nmi_v3) {
nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
- va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
+ va.va_mode = nfstov_mode(sp->sa_mode);
}
*(pathcp + len2) = '\0';
if (nd.ni_vp) {
@@ -2080,12 +2080,12 @@ nfsrv_readdir(struct nfsrv_descript *nfs
}
off = toff;
cnt = fxdr_unsigned(int, *tl);
- siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
xfer = NFS_SRVMAXDATA(nfsd);
+ if (cnt > xfer || cnt < 0)
+ cnt = xfer;
+ siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
if (siz > xfer)
siz = xfer;
- if (cnt > xfer)
- cnt = xfer;
fullsiz = siz;
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
if (error) {
@@ -2273,19 +2273,18 @@ nfsrv_readdirplus(struct nfsrv_descript
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
- toff = fxdr_hyper(tl);
+ off = toff = fxdr_hyper(tl);
tl += 2;
verf = fxdr_hyper(tl);
tl += 2;
siz = fxdr_unsigned(int, *tl++);
cnt = fxdr_unsigned(int, *tl);
- off = toff;
- siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
xfer = NFS_SRVMAXDATA(nfsd);
+ if (cnt > xfer || cnt < 0)
+ cnt = xfer;
+ siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
if (siz > xfer)
siz = xfer;
- if (cnt > xfer)
- cnt = xfer;
fullsiz = siz;
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
if (error) {
@@ -2520,6 +2519,8 @@ nfsrv_commit(struct nfsrv_descript *nfsd
off = fxdr_hyper(tl);
tl += 2;
cnt = fxdr_unsigned(int, *tl);
+ if (cnt < 0)
+ cnt = 0;
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
if (error) {
nfsm_reply(2 * NFSX_UNSIGNED);
Index: sys/nfs/nfs_vnops.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.171
diff -u -p -r1.171 nfs_vnops.c
--- sys/nfs/nfs_vnops.c 22 Feb 2017 11:42:46 -0000 1.171
+++ sys/nfs/nfs_vnops.c 21 Jan 2019 22:28:46 -0000
@@ -1206,7 +1206,7 @@ nfs_writerpc(struct vnode *vp, struct ui
nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
+ NFSX_V3WRITEVERF);
rlen = fxdr_unsigned(int, *tl++);
- if (rlen == 0) {
+ if (rlen <= 0) {
error = NFSERR_IO;
break;
} else if (rlen < len) {
@@ -2489,7 +2489,8 @@ nfs_readdirplusrpc(struct vnode *vp, str
/* Just skip over the file handle */
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
i = fxdr_unsigned(int, *tl);
- nfsm_adv(nfsm_rndup(i));
+ if (i > 0)
+ nfsm_adv(nfsm_rndup(i));
}
if (newvp != NULLVP) {
vrele(newvp);
Index: sys/nfs/nfsm_subs.h
===================================================================
RCS file: /cvs/src/sys/nfs/nfsm_subs.h,v
retrieving revision 1.45
diff -u -p -r1.45 nfsm_subs.h
--- sys/nfs/nfsm_subs.h 29 Aug 2015 23:07:51 -0000 1.45
+++ sys/nfs/nfsm_subs.h 21 Jan 2019 22:28:46 -0000
@@ -173,7 +173,7 @@ struct nfsm_info {
#define nfsm_strsiz(s, m) { \
nfsm_dissect(tl, u_int32_t *,NFSX_UNSIGNED); \
- if (((s) = fxdr_unsigned(int32_t, *tl)) > (m)) { \
+ if (((s) = fxdr_unsigned(int32_t, *tl)) < 0 || (s) > (m)) { \
m_freem(info.nmi_mrep); \
error = EBADRPC; \
goto nfsmout; \