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) MFC after: 3 days
This commit is contained in:
parent
2b73aacaf9
commit
0348c661d1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196503
@ -1405,8 +1405,8 @@ nfs_create(struct vop_create_args *ap)
|
||||
}
|
||||
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 @@ nfs_create(struct vop_create_args *ap)
|
||||
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);
|
||||
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mount.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/namei.h>
|
||||
@ -1552,6 +1553,7 @@ nfs_create(struct vop_create_args *ap)
|
||||
*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 @@ nfs_create(struct vop_create_args *ap)
|
||||
*tl++ = create_verf;
|
||||
#ifdef INET
|
||||
IN_IFADDR_RUNLOCK();
|
||||
CURVNET_RESTORE();
|
||||
#endif
|
||||
*tl = ++create_verf;
|
||||
} else {
|
||||
|
@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpc_com.h>
|
||||
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
@ -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;
|
||||
|
||||
|
@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/nettype.h>
|
||||
|
||||
@ -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:
|
||||
|
@ -57,6 +57,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#include <rpc/rpc_com.h>
|
||||
@ -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;
|
||||
|
||||
|
@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sx.h>
|
||||
#include <sys/ucred.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpcb_clnt.h>
|
||||
#include <rpc/nettype.h>
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -58,6 +58,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sx.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
@ -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) {
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user