summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2000-01-26 20:51:29 +0000
committerdillon <dillon@FreeBSD.org>2000-01-26 20:51:29 +0000
commit860c8411e16b55730d5f2a310ff816581da1ce7e (patch)
treeb2a018f0717bae4e49223391c85eb9e33ebf630d
parentc54637f2845865f50d208cf5f73391606f9aec7a (diff)
downloadFreeBSD-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.c29
-rw-r--r--sys/nfs/nqnfs.h17
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 */
OpenPOWER on IntegriCloud