From c9ef26814c33b33d3302194297fb3cfabf2deba6 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 26 Jan 2000 20:51:29 +0000 Subject: [PATCH] Fix catastrophic bug in NQNFS related to UDP mounts. The 'nqhost' struct contains a major union for which lph_slp was being initialized only for TCP connections, but accessed for all types of connections leading to a crash. Also, a conditional controlling an nfs_slplock() call contained an improper paren grouping, causing a second crash in the UDP case. The nqhost structure has been reorganized and lph_slp has been made a normal structural field rather then a union field, and properly initialized for all connection types. Approved by: jkh --- sys/nfs/nfs_nqlease.c | 29 ++++++++++++++--------------- sys/nfs/nqnfs.h | 17 ++++++----------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/sys/nfs/nfs_nqlease.c b/sys/nfs/nfs_nqlease.c index ccaa8488e42..fb02f2c1413 100644 --- a/sys/nfs/nfs_nqlease.c +++ b/sys/nfs/nfs_nqlease.c @@ -387,6 +387,7 @@ nqsrv_addhost(lph, slp, nam) return; } nsso = slp->ns_so; + lph->lph_slp = slp; if (nsso && nsso->so_proto->pr_protocol == IPPROTO_UDP) { saddr = (struct sockaddr_in *)nam; lph->lph_flag |= (LC_VALID | LC_UDP); @@ -399,7 +400,6 @@ nqsrv_addhost(lph, slp, nam) #endif } else { lph->lph_flag |= (LC_VALID | LC_SREF); - lph->lph_slp = slp; slp->ns_sref++; } } @@ -506,7 +506,6 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred) register int siz; struct nqm *lphnext = lp->lc_morehosts; struct mbuf *m, *mreq, *mb, *mb2, *mheadend; - struct socket *so; struct sockaddr *nam2; struct sockaddr_in *saddr; nfsfh_t nfh; @@ -514,12 +513,16 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred) caddr_t bpos, cp; u_int32_t xid, *tl; int len = 1, ok = 1, i = 0; - int sotype, *solockp; while (ok && (lph->lph_flag & LC_VALID)) { - if (nqsrv_cmpnam(slp, nam, lph)) + if (nqsrv_cmpnam(slp, nam, lph)) { lph->lph_flag |= LC_VACATED; - else if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) { + } else if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) { + struct socket *so; + int sotype; + int *solockp = NULL; + + so = lph->lph_slp->ns_so; if (lph->lph_flag & LC_UDP) { MALLOC(nam2, struct sockaddr *, sizeof *nam2, M_SONAME, M_WAITOK); @@ -528,20 +531,16 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred) saddr->sin_family = AF_INET; saddr->sin_addr.s_addr = lph->lph_inetaddr; saddr->sin_port = lph->lph_port; - so = lph->lph_slp->ns_so; } else if (lph->lph_flag & LC_CLTP) { nam2 = lph->lph_nam; - so = lph->lph_slp->ns_so; } else if (lph->lph_slp->ns_flag & SLP_VALID) { nam2 = (struct sockaddr *)0; - so = lph->lph_slp->ns_so; - } else + } else { goto nextone; + } sotype = so->so_type; if (so->so_proto->pr_flags & PR_CONNREQUIRED) solockp = &lph->lph_slp->ns_solock; - else - solockp = (int *)0; nfsm_reqhead((struct vnode *)0, NQNFSPROC_EVICTED, NFSX_V3FH + NFSX_UNSIGNED); fhp = &nfh.fh_generic; @@ -576,11 +575,11 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred) * nfs_sndlock if PR_CONNREQUIRED XXX */ - if (((lph->lph_flag & (LC_UDP | LC_CLTP)) == 0 && - (lph->lph_slp->ns_flag & SLP_VALID) == 0) || - (nfs_slplock(lph->lph_slp, 0) == 0)) + if ((lph->lph_flag & (LC_UDP | LC_CLTP)) == 0 && + ((lph->lph_slp->ns_flag & SLP_VALID) == 0 || + nfs_slplock(lph->lph_slp, 0) == 0)) { m_freem(m); - else { + } else { (void) nfs_send(so, nam2, m, (struct nfsreq *)0); if (solockp) diff --git a/sys/nfs/nqnfs.h b/sys/nfs/nqnfs.h index 9afe58dbfd8..36e50067eca 100644 --- a/sys/nfs/nqnfs.h +++ b/sys/nfs/nqnfs.h @@ -87,31 +87,26 @@ #define LC_MOREHOSTSIZ 10 struct nqhost { + u_int16_t lph_flag; + u_int16_t lph_port; + struct nfssvc_sock *lph_slp; + union { struct { - u_int16_t udp_flag; - u_int16_t udp_port; union nethostaddr udp_haddr; } un_udp; struct { - u_int16_t connless_flag; - u_int16_t connless_spare; union nethostaddr connless_haddr; } un_connless; struct { - u_int16_t conn_flag; - u_int16_t conn_spare; - struct nfssvc_sock *conn_slp; + int dummy; } un_conn; } lph_un; }; -#define lph_flag lph_un.un_udp.udp_flag -#define lph_port lph_un.un_udp.udp_port #define lph_haddr lph_un.un_udp.udp_haddr #define lph_inetaddr lph_un.un_udp.udp_haddr.had_inetaddr #define lph_claddr lph_un.un_connless.connless_haddr #define lph_nam lph_un.un_connless.connless_haddr.had_nam -#define lph_slp lph_un.un_conn.conn_slp struct nqlease { LIST_ENTRY(nqlease) lc_hash; /* Fhandle hash list */ @@ -123,7 +118,7 @@ struct nqlease { char lc_fiddata[MAXFIDSZ]; struct vnode *lc_vp; /* Soft reference to associated vnode */ }; -#define lc_flag lc_host.lph_un.un_udp.udp_flag +#define lc_flag lc_host.lph_flag /* lc_flag bits */ #define LC_VALID 0x0001 /* Host address valid */