diff options
author | dillon <dillon@FreeBSD.org> | 2000-01-26 20:51:29 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2000-01-26 20:51:29 +0000 |
commit | 860c8411e16b55730d5f2a310ff816581da1ce7e (patch) | |
tree | b2a018f0717bae4e49223391c85eb9e33ebf630d | |
parent | c54637f2845865f50d208cf5f73391606f9aec7a (diff) | |
download | FreeBSD-src-860c8411e16b55730d5f2a310ff816581da1ce7e.zip FreeBSD-src-860c8411e16b55730d5f2a310ff816581da1ce7e.tar.gz |
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
-rw-r--r-- | sys/nfs/nfs_nqlease.c | 29 | ||||
-rw-r--r-- | 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 ccaa848..fb02f2c 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 9afe58d..36e5006 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 */ |