From fc234394fe30adbec8907058fce67a7427d6295f Mon Sep 17 00:00:00 2001 From: zec Date: Fri, 28 Aug 2009 19:12:44 +0000 Subject: [PATCH] MFC r196503: Fix NFS panics with options VIMAGE kernels by apropriately setting curvnet context inside the RPC code. Temporarily set td's cred to mount's cred before calling socreate() via __rpc_nconf2socket(). Submitted by: rmacklem (in part) Reviewed by: rmacklem, rwatson Discussed with: dfr, bz Approved by: re (rwatson), julian (mentor) Approved by: re (rwatson) git-svn-id: svn://svn.freebsd.org/base/stable/8@196622 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/fs/nfsclient/nfs_clvnops.c | 4 ++-- sys/nfsclient/nfs_vnops.c | 3 +++ sys/rpc/clnt_dg.c | 5 +++++ sys/rpc/clnt_rc.c | 5 +++-- sys/rpc/clnt_vc.c | 9 ++++++++- sys/rpc/rpc_generic.c | 10 +++++++++- sys/rpc/svc_dg.c | 6 ++++++ sys/rpc/svc_generic.c | 7 +++++++ sys/rpc/svc_vc.c | 21 ++++++++++++++++++--- 9 files changed, 61 insertions(+), 9 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 219c62e8c..5dc3a5934 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1405,8 +1405,8 @@ again: } mtx_unlock(&dnp->n_mtx); - CURVNET_SET(P_TO_VNET(&proc0)); #ifdef INET + CURVNET_SET(CRED_TO_VNET(cnp->cn_cred)); IN_IFADDR_RLOCK(); if (!TAILQ_EMPTY(&V_in_ifaddrhead)) cverf.lval[0] = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr; @@ -1415,9 +1415,9 @@ again: cverf.lval[0] = create_verf; #ifdef INET IN_IFADDR_RUNLOCK(); + CURVNET_RESTORE(); #endif cverf.lval[1] = ++create_verf; - CURVNET_RESTORE(); error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen, vap, cverf, fmode, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, NULL); diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index 165849b39..7dfd298da 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1552,6 +1553,7 @@ again: *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF); #ifdef INET + CURVNET_SET(CRED_TO_VNET(cnp->cn_cred)); IN_IFADDR_RLOCK(); if (!TAILQ_EMPTY(&V_in_ifaddrhead)) *tl++ = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr; @@ -1560,6 +1562,7 @@ again: *tl++ = create_verf; #ifdef INET IN_IFADDR_RUNLOCK(); + CURVNET_RESTORE(); #endif *tl = ++create_verf; } else { diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c index 0b49375b9..78f4a9a21 100644 --- a/sys/rpc/clnt_dg.c +++ b/sys/rpc/clnt_dg.c @@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -197,11 +199,14 @@ clnt_dg_create( return (NULL); } + CURVNET_SET(so->so_vnet); if (!__rpc_socket2sockinfo(so, &si)) { rpc_createerr.cf_stat = RPC_TLIERROR; rpc_createerr.cf_error.re_errno = 0; + CURVNET_RESTORE(); return (NULL); } + CURVNET_RESTORE(); /* * Find the receive and the send size diff --git a/sys/rpc/clnt_rc.c b/sys/rpc/clnt_rc.c index 217608c4b..24fc09a36 100644 --- a/sys/rpc/clnt_rc.c +++ b/sys/rpc/clnt_rc.c @@ -175,15 +175,16 @@ clnt_reconnect_connect(CLIENT *cl) rc->rc_connecting = TRUE; mtx_unlock(&rc->rc_lock); + oldcred = td->td_ucred; + td->td_ucred = rc->rc_ucred; so = __rpc_nconf2socket(rc->rc_nconf); if (!so) { stat = rpc_createerr.cf_stat = RPC_TLIERROR; rpc_createerr.cf_error.re_errno = 0; + td->td_ucred = oldcred; goto out; } - oldcred = td->td_ucred; - td->td_ucred = rc->rc_ucred; if (rc->rc_privport) bindresvport(so, NULL); diff --git a/sys/rpc/clnt_vc.c b/sys/rpc/clnt_vc.c index 3f15c435c..85e89abe5 100644 --- a/sys/rpc/clnt_vc.c +++ b/sys/rpc/clnt_vc.c @@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$"); #include #include #include + +#include + #include #include @@ -217,8 +220,11 @@ clnt_vc_create( } } - if (!__rpc_socket2sockinfo(so, &si)) + CURVNET_SET(so->so_vnet); + if (!__rpc_socket2sockinfo(so, &si)) { + CURVNET_RESTORE(); goto err; + } if (so->so_proto->pr_flags & PR_CONNREQUIRED) { bzero(&sopt, sizeof(sopt)); @@ -239,6 +245,7 @@ clnt_vc_create( sopt.sopt_valsize = sizeof(one); sosetopt(so, &sopt); } + CURVNET_RESTORE(); ct->ct_closeit = FALSE; diff --git a/sys/rpc/rpc_generic.c b/sys/rpc/rpc_generic.c index d9100b340..f15ad28f2 100644 --- a/sys/rpc/rpc_generic.c +++ b/sys/rpc/rpc_generic.c @@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -822,6 +824,7 @@ bindresvport(struct socket *so, struct sockaddr *sa) sa->sa_len = salen; if (*portp == 0) { + CURVNET_SET(so->so_vnet); bzero(&opt, sizeof(opt)); opt.sopt_dir = SOPT_GET; opt.sopt_level = proto; @@ -829,12 +832,15 @@ bindresvport(struct socket *so, struct sockaddr *sa) opt.sopt_val = &old; opt.sopt_valsize = sizeof(old); error = sogetopt(so, &opt); - if (error) + if (error) { + CURVNET_RESTORE(); goto out; + } opt.sopt_dir = SOPT_SET; opt.sopt_val = &portlow; error = sosetopt(so, &opt); + CURVNET_RESTORE(); if (error) goto out; } @@ -845,7 +851,9 @@ bindresvport(struct socket *so, struct sockaddr *sa) if (error) { opt.sopt_dir = SOPT_SET; opt.sopt_val = &old; + CURVNET_SET(so->so_vnet); sosetopt(so, &opt); + CURVNET_RESTORE(); } } out: diff --git a/sys/rpc/svc_dg.c b/sys/rpc/svc_dg.c index 0747d1d96..9d7696b01 100644 --- a/sys/rpc/svc_dg.c +++ b/sys/rpc/svc_dg.c @@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include @@ -101,8 +103,10 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, struct sockaddr* sa; int error; + CURVNET_SET(so->so_vnet); if (!__rpc_socket2sockinfo(so, &si)) { printf(svc_dg_str, svc_dg_err1); + CURVNET_RESTORE(); return (NULL); } /* @@ -112,6 +116,7 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); if ((sendsize == 0) || (recvsize == 0)) { printf(svc_dg_str, svc_dg_err2); + CURVNET_RESTORE(); return (NULL); } @@ -124,6 +129,7 @@ svc_dg_create(SVCPOOL *pool, struct socket *so, size_t sendsize, xprt->xp_ops = &svc_dg_ops; error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); + CURVNET_RESTORE(); if (error) goto freedata; diff --git a/sys/rpc/svc_generic.c b/sys/rpc/svc_generic.c index 38380f25d..e6e8acdb1 100644 --- a/sys/rpc/svc_generic.c +++ b/sys/rpc/svc_generic.c @@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include #include @@ -228,11 +230,14 @@ svc_tli_create( /* * It is an open socket. Get the transport info. */ + CURVNET_SET(so->so_vnet); if (!__rpc_socket2sockinfo(so, &si)) { printf( "svc_tli_create: could not get transport information\n"); + CURVNET_RESTORE(); return (NULL); } + CURVNET_RESTORE(); } /* @@ -259,7 +264,9 @@ svc_tli_create( "svc_tli_create: could not bind to requested address\n"); goto freedata; } + CURVNET_SET(so->so_vnet); solisten(so, (int)bindaddr->qlen, curthread); + CURVNET_RESTORE(); } } diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c index b7da5e227..85d335fa0 100644 --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -58,6 +58,9 @@ __FBSDID("$FreeBSD$"); #include #include #include + +#include + #include #include @@ -151,9 +154,12 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, xprt->xp_p2 = NULL; xprt->xp_ops = &svc_vc_rendezvous_ops; + CURVNET_SET(so->so_vnet); error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); - if (error) + if (error) { + CURVNET_RESTORE(); goto cleanup_svc_vc_create; + } memcpy(&xprt->xp_ltaddr, sa, sa->sa_len); free(sa, M_SONAME); @@ -161,6 +167,7 @@ svc_vc_create(SVCPOOL *pool, struct socket *so, size_t sendsize, xprt_register(xprt); solisten(so, SOMAXCONN, curthread); + CURVNET_RESTORE(); SOCKBUF_LOCK(&so->so_rcv); xprt->xp_upcallset = 1; @@ -193,9 +200,12 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) opt.sopt_name = SO_KEEPALIVE; opt.sopt_val = &one; opt.sopt_valsize = sizeof(one); + CURVNET_SET(so->so_vnet); error = sosetopt(so, &opt); - if (error) + if (error) { + CURVNET_RESTORE(); return (NULL); + } if (so->so_proto->pr_protocol == IPPROTO_TCP) { bzero(&opt, sizeof(struct sockopt)); @@ -205,9 +215,12 @@ svc_vc_create_conn(SVCPOOL *pool, struct socket *so, struct sockaddr *raddr) opt.sopt_val = &one; opt.sopt_valsize = sizeof(one); error = sosetopt(so, &opt); - if (error) + if (error) { + CURVNET_RESTORE(); return (NULL); + } } + CURVNET_RESTORE(); cd = mem_alloc(sizeof(*cd)); cd->strm_stat = XPRT_IDLE; @@ -625,8 +638,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg, uio.uio_td = curthread; m = NULL; rcvflag = MSG_DONTWAIT; + CURVNET_SET(xprt->xp_socket->so_vnet); error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL, &rcvflag); + CURVNET_RESTORE(); if (error == EWOULDBLOCK) { /* -- 2.45.0