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
This commit is contained in:
parent
45248baa3c
commit
c9ef26814c
@ -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)
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user