Changeset View
Changeset View
Standalone View
Standalone View
sys/rpc/rpcsec_tls/rpctls_impl.c
Show All 32 Lines | |||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_kern_tls.h" | #include "opt_kern_tls.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/capsicum.h> | #include <sys/capsicum.h> | ||||
#include <sys/file.h> | #include <sys/file.h> | ||||
#include <sys/filedesc.h> | #include <sys/filedesc.h> | ||||
#include <sys/jail.h> | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
#include <sys/syscall.h> | #include <sys/syscall.h> | ||||
#include <sys/syscallsubr.h> | #include <sys/syscallsubr.h> | ||||
#include <sys/sysent.h> | #include <sys/sysent.h> | ||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
#include <net/vnet.h> | |||||
#include <rpc/rpc.h> | #include <rpc/rpc.h> | ||||
#include <rpc/rpc_com.h> | #include <rpc/rpc_com.h> | ||||
#include <rpc/rpcsec_tls.h> | #include <rpc/rpcsec_tls.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
#include "rpctlscd.h" | #include "rpctlscd.h" | ||||
#include "rpctlssd.h" | #include "rpctlssd.h" | ||||
/* | /* | ||||
* Syscall hooks | * Syscall hooks | ||||
*/ | */ | ||||
static struct syscall_helper_data rpctls_syscalls[] = { | static struct syscall_helper_data rpctls_syscalls[] = { | ||||
SYSCALL_INIT_HELPER(rpctls_syscall), | SYSCALL_INIT_HELPER(rpctls_syscall), | ||||
SYSCALL_INIT_LAST | SYSCALL_INIT_LAST | ||||
}; | }; | ||||
static CLIENT *rpctls_connect_handle; | static CLIENT *rpctls_connect_handle; | ||||
static struct mtx rpctls_connect_lock; | static struct mtx rpctls_connect_lock; | ||||
static struct socket *rpctls_connect_so = NULL; | static struct socket *rpctls_connect_so = NULL; | ||||
static CLIENT *rpctls_connect_cl = NULL; | static CLIENT *rpctls_connect_cl = NULL; | ||||
static CLIENT *rpctls_server_handle[RPCTLS_SRV_MAXNPROCS]; | |||||
static struct mtx rpctls_server_lock; | static struct mtx rpctls_server_lock; | ||||
static struct socket *rpctls_server_so = NULL; | |||||
static SVCXPRT *rpctls_server_xprt = NULL; | |||||
static bool rpctls_srv_newdaemon = false; | |||||
static int rpctls_srv_prevproc = 0; | |||||
static bool rpctls_server_busy[RPCTLS_SRV_MAXNPROCS]; | |||||
static struct opaque_auth rpctls_null_verf; | static struct opaque_auth rpctls_null_verf; | ||||
KRPC_VNET_DEFINE_STATIC(CLIENT **, rpctls_server_handle); | |||||
KRPC_VNET_DEFINE_STATIC(struct socket *, rpctls_server_so) = NULL; | |||||
KRPC_VNET_DEFINE_STATIC(SVCXPRT *, rpctls_server_xprt) = NULL; | |||||
KRPC_VNET_DEFINE_STATIC(bool, rpctls_srv_newdaemon) = false; | |||||
KRPC_VNET_DEFINE_STATIC(int, rpctls_srv_prevproc) = 0; | |||||
KRPC_VNET_DEFINE_STATIC(bool *, rpctls_server_busy); | |||||
static CLIENT *rpctls_connect_client(void); | static CLIENT *rpctls_connect_client(void); | ||||
static CLIENT *rpctls_server_client(int procpos); | static CLIENT *rpctls_server_client(int procpos); | ||||
static enum clnt_stat rpctls_server(SVCXPRT *xprt, struct socket *so, | static enum clnt_stat rpctls_server(SVCXPRT *xprt, struct socket *so, | ||||
uint32_t *flags, uint64_t *sslp, | uint32_t *flags, uint64_t *sslp, | ||||
uid_t *uid, int *ngrps, gid_t **gids, | uid_t *uid, int *ngrps, gid_t **gids, | ||||
int *procposp); | int *procposp); | ||||
static void | |||||
rpctls_vnetinit(const void *unused __unused) | |||||
{ | |||||
int i; | |||||
KRPC_VNET(rpctls_server_handle) = malloc(sizeof(CLIENT *) * | |||||
RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO); | |||||
KRPC_VNET(rpctls_server_busy) = malloc(sizeof(bool) * | |||||
RPCTLS_SRV_MAXNPROCS, M_RPC, M_WAITOK | M_ZERO); | |||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) | |||||
KRPC_VNET(rpctls_server_busy)[i] = false; | |||||
} | |||||
VNET_SYSINIT(rpctls_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, | |||||
rpctls_vnetinit, NULL); | |||||
int | int | ||||
rpctls_init(void) | rpctls_init(void) | ||||
{ | { | ||||
int error, i; | int error; | ||||
error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD); | error = syscall_helper_register(rpctls_syscalls, SY_THR_STATIC_KLD); | ||||
if (error != 0) { | if (error != 0) { | ||||
printf("rpctls_init: cannot register syscall\n"); | printf("rpctls_init: cannot register syscall\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
mtx_init(&rpctls_connect_lock, "rpctls_connect_lock", NULL, | mtx_init(&rpctls_connect_lock, "rpctls_connect_lock", NULL, | ||||
MTX_DEF); | MTX_DEF); | ||||
mtx_init(&rpctls_server_lock, "rpctls_server_lock", NULL, | mtx_init(&rpctls_server_lock, "rpctls_server_lock", NULL, | ||||
MTX_DEF); | MTX_DEF); | ||||
rpctls_null_verf.oa_flavor = AUTH_NULL; | rpctls_null_verf.oa_flavor = AUTH_NULL; | ||||
rpctls_null_verf.oa_base = RPCTLS_START_STRING; | rpctls_null_verf.oa_base = RPCTLS_START_STRING; | ||||
rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING); | rpctls_null_verf.oa_length = strlen(RPCTLS_START_STRING); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) | |||||
rpctls_server_busy[i] = false; | |||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap) | sys_rpctls_syscall(struct thread *td, struct rpctls_syscall_args *uap) | ||||
{ | { | ||||
struct sockaddr_un sun; | struct sockaddr_un sun; | ||||
struct netconfig *nconf; | struct netconfig *nconf; | ||||
struct file *fp; | struct file *fp; | ||||
struct socket *so; | struct socket *so; | ||||
SVCXPRT *xprt; | SVCXPRT *xprt; | ||||
char path[MAXPATHLEN]; | char path[MAXPATHLEN]; | ||||
int fd = -1, error, i, try_count; | int fd = -1, error, i, try_count; | ||||
CLIENT *cl, *oldcl[RPCTLS_SRV_MAXNPROCS], *concl; | CLIENT *cl, *oldcl[RPCTLS_SRV_MAXNPROCS], *concl; | ||||
uint64_t ssl[3]; | uint64_t ssl[3]; | ||||
struct timeval timeo; | struct timeval timeo; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
u_int maxlen; | u_int maxlen; | ||||
#endif | #endif | ||||
error = priv_check(td, PRIV_NFS_DAEMON); | error = priv_check(td, PRIV_NFS_DAEMON); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
KRPC_CURVNET_SET(KRPC_TD_TO_VNET(td)); | |||||
switch (uap->op) { | switch (uap->op) { | ||||
case RPCTLS_SYSC_SRVSTARTUP: | case RPCTLS_SYSC_SRVSTARTUP: | ||||
if (jailed(curthread->td_ucred) && | |||||
!prison_check_nfsd(curthread->td_ucred)) | |||||
error = EPERM; | |||||
if (error == 0) { | |||||
/* Get rid of all old CLIENTs. */ | /* Get rid of all old CLIENTs. */ | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
oldcl[i] = rpctls_server_handle[i]; | oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; | ||||
rpctls_server_handle[i] = NULL; | KRPC_VNET(rpctls_server_handle)[i] = NULL; | ||||
rpctls_server_busy[i] = false; | KRPC_VNET(rpctls_server_busy)[i] = false; | ||||
} | } | ||||
rpctls_srv_newdaemon = true; | KRPC_VNET(rpctls_srv_newdaemon) = true; | ||||
rpctls_srv_prevproc = 0; | KRPC_VNET(rpctls_srv_prevproc) = 0; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
if (oldcl[i] != NULL) { | if (oldcl[i] != NULL) { | ||||
CLNT_CLOSE(oldcl[i]); | CLNT_CLOSE(oldcl[i]); | ||||
CLNT_RELEASE(oldcl[i]); | CLNT_RELEASE(oldcl[i]); | ||||
} | } | ||||
} | } | ||||
} | |||||
break; | break; | ||||
case RPCTLS_SYSC_CLSETPATH: | case RPCTLS_SYSC_CLSETPATH: | ||||
if (jailed(curthread->td_ucred)) | |||||
error = EPERM; | |||||
if (error == 0) | |||||
error = copyinstr(uap->path, path, sizeof(path), NULL); | error = copyinstr(uap->path, path, sizeof(path), NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
error = ENXIO; | error = ENXIO; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
if (rpctls_getinfo(&maxlen, false, false)) | if (rpctls_getinfo(&maxlen, false, false)) | ||||
error = 0; | error = 0; | ||||
#endif | #endif | ||||
} | } | ||||
if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || | if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || | ||||
Show All 39 Lines | #endif | ||||
mtx_unlock(&rpctls_connect_lock); | mtx_unlock(&rpctls_connect_lock); | ||||
if (oldcl[0] != NULL) { | if (oldcl[0] != NULL) { | ||||
CLNT_CLOSE(oldcl[0]); | CLNT_CLOSE(oldcl[0]); | ||||
CLNT_RELEASE(oldcl[0]); | CLNT_RELEASE(oldcl[0]); | ||||
} | } | ||||
break; | break; | ||||
case RPCTLS_SYSC_SRVSETPATH: | case RPCTLS_SYSC_SRVSETPATH: | ||||
if (jailed(curthread->td_ucred) && | |||||
!prison_check_nfsd(curthread->td_ucred)) | |||||
error = EPERM; | |||||
if (error == 0) | |||||
error = copyinstr(uap->path, path, sizeof(path), NULL); | error = copyinstr(uap->path, path, sizeof(path), NULL); | ||||
if (error == 0) { | if (error == 0) { | ||||
error = ENXIO; | error = ENXIO; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
if (rpctls_getinfo(&maxlen, false, false)) | if (rpctls_getinfo(&maxlen, false, false)) | ||||
error = 0; | error = 0; | ||||
#endif | #endif | ||||
} | } | ||||
if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || | if (error == 0 && (strlen(path) + 1 > sizeof(sun.sun_path) || | ||||
Show All 28 Lines | if (error == 0) { | ||||
CLNT_CONTROL(cl, CLSET_TIMEOUT, &timeo); | CLNT_CONTROL(cl, CLSET_TIMEOUT, &timeo); | ||||
} else | } else | ||||
error = EINVAL; | error = EINVAL; | ||||
} | } | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) | ||||
oldcl[i] = NULL; | oldcl[i] = NULL; | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
if (rpctls_srv_newdaemon) { | if (KRPC_VNET(rpctls_srv_newdaemon)) { | ||||
/* | /* | ||||
* For a new daemon, the rpctls_srv_handles have | * For a new daemon, the rpctls_srv_handles have | ||||
* already been cleaned up by RPCTLS_SYSC_SRVSTARTUP. | * already been cleaned up by RPCTLS_SYSC_SRVSTARTUP. | ||||
* Scan for an available array entry to use. | * Scan for an available array entry to use. | ||||
*/ | */ | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
if (rpctls_server_handle[i] == NULL) | if (KRPC_VNET(rpctls_server_handle)[i] == NULL) | ||||
break; | break; | ||||
} | } | ||||
if (i == RPCTLS_SRV_MAXNPROCS && error == 0) | if (i == RPCTLS_SRV_MAXNPROCS && error == 0) | ||||
error = ENXIO; | error = ENXIO; | ||||
} else { | } else { | ||||
/* For an old daemon, clear out old CLIENTs. */ | /* For an old daemon, clear out old CLIENTs. */ | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
oldcl[i] = rpctls_server_handle[i]; | oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; | ||||
rpctls_server_handle[i] = NULL; | KRPC_VNET(rpctls_server_handle)[i] = NULL; | ||||
rpctls_server_busy[i] = false; | KRPC_VNET(rpctls_server_busy)[i] = false; | ||||
} | } | ||||
i = 0; /* Set to use rpctls_server_handle[0]. */ | i = 0; /* Set to use rpctls_server_handle[0]. */ | ||||
} | } | ||||
if (error == 0) | if (error == 0) | ||||
rpctls_server_handle[i] = cl; | KRPC_VNET(rpctls_server_handle)[i] = cl; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
if (oldcl[i] != NULL) { | if (oldcl[i] != NULL) { | ||||
CLNT_CLOSE(oldcl[i]); | CLNT_CLOSE(oldcl[i]); | ||||
CLNT_RELEASE(oldcl[i]); | CLNT_RELEASE(oldcl[i]); | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case RPCTLS_SYSC_CLSHUTDOWN: | case RPCTLS_SYSC_CLSHUTDOWN: | ||||
mtx_lock(&rpctls_connect_lock); | mtx_lock(&rpctls_connect_lock); | ||||
oldcl[0] = rpctls_connect_handle; | oldcl[0] = rpctls_connect_handle; | ||||
rpctls_connect_handle = NULL; | rpctls_connect_handle = NULL; | ||||
mtx_unlock(&rpctls_connect_lock); | mtx_unlock(&rpctls_connect_lock); | ||||
if (oldcl[0] != NULL) { | if (oldcl[0] != NULL) { | ||||
CLNT_CLOSE(oldcl[0]); | CLNT_CLOSE(oldcl[0]); | ||||
CLNT_RELEASE(oldcl[0]); | CLNT_RELEASE(oldcl[0]); | ||||
} | } | ||||
break; | break; | ||||
case RPCTLS_SYSC_SRVSHUTDOWN: | case RPCTLS_SYSC_SRVSHUTDOWN: | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
oldcl[i] = rpctls_server_handle[i]; | oldcl[i] = KRPC_VNET(rpctls_server_handle)[i]; | ||||
rpctls_server_handle[i] = NULL; | KRPC_VNET(rpctls_server_handle)[i] = NULL; | ||||
} | } | ||||
rpctls_srv_newdaemon = false; | KRPC_VNET(rpctls_srv_newdaemon) = false; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | for (i = 0; i < RPCTLS_SRV_MAXNPROCS; i++) { | ||||
if (oldcl[i] != NULL) { | if (oldcl[i] != NULL) { | ||||
CLNT_CLOSE(oldcl[i]); | CLNT_CLOSE(oldcl[i]); | ||||
CLNT_RELEASE(oldcl[i]); | CLNT_RELEASE(oldcl[i]); | ||||
} | } | ||||
} | } | ||||
Show All 22 Lines | if (so != NULL) { | ||||
fdrop(fp, td); /* Drop fp reference. */ | fdrop(fp, td); /* Drop fp reference. */ | ||||
td->td_retval[0] = fd; | td->td_retval[0] = fd; | ||||
} | } | ||||
} else | } else | ||||
error = EPERM; | error = EPERM; | ||||
break; | break; | ||||
case RPCTLS_SYSC_SRVSOCKET: | case RPCTLS_SYSC_SRVSOCKET: | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
so = rpctls_server_so; | so = KRPC_VNET(rpctls_server_so); | ||||
rpctls_server_so = NULL; | KRPC_VNET(rpctls_server_so) = NULL; | ||||
xprt = rpctls_server_xprt; | xprt = KRPC_VNET(rpctls_server_xprt); | ||||
rpctls_server_xprt = NULL; | KRPC_VNET(rpctls_server_xprt) = NULL; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
if (so != NULL) { | if (so != NULL) { | ||||
error = falloc(td, &fp, &fd, 0); | error = falloc(td, &fp, &fd, 0); | ||||
if (error == 0) { | if (error == 0) { | ||||
/* | /* | ||||
* Once this file descriptor is associated | * Once this file descriptor is associated | ||||
* with the socket, it cannot be closed by | * with the socket, it cannot be closed by | ||||
* the server side krpc code (svc_vc.c). | * the server side krpc code (svc_vc.c). | ||||
*/ | */ | ||||
soref(so); | soref(so); | ||||
sx_xlock(&xprt->xp_lock); | sx_xlock(&xprt->xp_lock); | ||||
xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL; | xprt->xp_tls = RPCTLS_FLAGS_HANDSHFAIL; | ||||
sx_xunlock(&xprt->xp_lock); | sx_xunlock(&xprt->xp_lock); | ||||
finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, | finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, | ||||
&socketops); | &socketops); | ||||
fdrop(fp, td); /* Drop fp reference. */ | fdrop(fp, td); /* Drop fp reference. */ | ||||
td->td_retval[0] = fd; | td->td_retval[0] = fd; | ||||
} | } | ||||
} else | } else | ||||
error = EPERM; | error = EPERM; | ||||
break; | break; | ||||
default: | default: | ||||
error = EINVAL; | error = EINVAL; | ||||
} | } | ||||
KRPC_CURVNET_RESTORE(); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Acquire the rpctls_connect_handle and return it with a reference count, | * Acquire the rpctls_connect_handle and return it with a reference count, | ||||
* if it is available. | * if it is available. | ||||
*/ | */ | ||||
Show All 14 Lines | |||||
* Acquire the rpctls_server_handle and return it with a reference count, | * Acquire the rpctls_server_handle and return it with a reference count, | ||||
* if it is available. | * if it is available. | ||||
*/ | */ | ||||
static CLIENT * | static CLIENT * | ||||
rpctls_server_client(int procpos) | rpctls_server_client(int procpos) | ||||
{ | { | ||||
CLIENT *cl; | CLIENT *cl; | ||||
KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); | |||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
cl = rpctls_server_handle[procpos]; | cl = KRPC_VNET(rpctls_server_handle)[procpos]; | ||||
if (cl != NULL) | if (cl != NULL) | ||||
CLNT_ACQUIRE(cl); | CLNT_ACQUIRE(cl); | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
KRPC_CURVNET_RESTORE(); | |||||
return (cl); | return (cl); | ||||
} | } | ||||
/* Do an upcall for a new socket connect using TLS. */ | /* Do an upcall for a new socket connect using TLS. */ | ||||
enum clnt_stat | enum clnt_stat | ||||
rpctls_connect(CLIENT *newclient, char *certname, struct socket *so, | rpctls_connect(CLIENT *newclient, char *certname, struct socket *so, | ||||
uint64_t *sslp, uint32_t *reterr) | uint64_t *sslp, uint32_t *reterr) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
enum clnt_stat stat; | enum clnt_stat stat; | ||||
CLIENT *cl; | CLIENT *cl; | ||||
struct rpctlssd_connect_res res; | struct rpctlssd_connect_res res; | ||||
gid_t *gidp; | gid_t *gidp; | ||||
uint32_t *gidv; | uint32_t *gidv; | ||||
int i, procpos; | int i, procpos; | ||||
KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); | |||||
cl = NULL; | cl = NULL; | ||||
procpos = -1; | procpos = -1; | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
for (i = (rpctls_srv_prevproc + 1) % RPCTLS_SRV_MAXNPROCS; | for (i = (KRPC_VNET(rpctls_srv_prevproc) + 1) % RPCTLS_SRV_MAXNPROCS; | ||||
i != rpctls_srv_prevproc; i = (i + 1) % RPCTLS_SRV_MAXNPROCS) { | i != KRPC_VNET(rpctls_srv_prevproc); | ||||
if (rpctls_server_handle[i] != NULL) | i = (i + 1) % RPCTLS_SRV_MAXNPROCS) { | ||||
if (KRPC_VNET(rpctls_server_handle)[i] != NULL) | |||||
break; | break; | ||||
} | } | ||||
if (i == rpctls_srv_prevproc) { | if (i == KRPC_VNET(rpctls_srv_prevproc)) { | ||||
if (rpctls_server_handle[i] != NULL) | if (KRPC_VNET(rpctls_server_handle)[i] != NULL) | ||||
procpos = i; | procpos = i; | ||||
} else | } else | ||||
rpctls_srv_prevproc = procpos = i; | KRPC_VNET(rpctls_srv_prevproc) = procpos = i; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
if (procpos >= 0) | if (procpos >= 0) | ||||
cl = rpctls_server_client(procpos); | cl = rpctls_server_client(procpos); | ||||
if (cl == NULL) | if (cl == NULL) { | ||||
KRPC_CURVNET_RESTORE(); | |||||
return (RPC_SYSTEMERROR); | return (RPC_SYSTEMERROR); | ||||
} | |||||
/* Serialize the server upcalls. */ | /* Serialize the server upcalls. */ | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
while (rpctls_server_busy[procpos]) | while (KRPC_VNET(rpctls_server_busy)[procpos]) | ||||
msleep(&rpctls_server_busy[procpos], &rpctls_server_lock, PVFS, | msleep(&KRPC_VNET(rpctls_server_busy)[procpos], | ||||
"rtlssn", 0); | &rpctls_server_lock, PVFS, "rtlssn", 0); | ||||
rpctls_server_busy[procpos] = true; | KRPC_VNET(rpctls_server_busy)[procpos] = true; | ||||
rpctls_server_so = so; | KRPC_VNET(rpctls_server_so) = so; | ||||
rpctls_server_xprt = xprt; | KRPC_VNET(rpctls_server_xprt) = xprt; | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
/* Do the server upcall. */ | /* Do the server upcall. */ | ||||
res.gid.gid_val = NULL; | res.gid.gid_val = NULL; | ||||
stat = rpctlssd_connect_1(NULL, &res, cl); | stat = rpctlssd_connect_1(NULL, &res, cl); | ||||
if (stat == RPC_SUCCESS) { | if (stat == RPC_SUCCESS) { | ||||
*flags = res.flags; | *flags = res.flags; | ||||
*sslp++ = res.sec; | *sslp++ = res.sec; | ||||
Show All 18 Lines | if (stat == RPC_SUCCESS) { | ||||
*/ | */ | ||||
soshutdown(so, SHUT_RD); | soshutdown(so, SHUT_RD); | ||||
} | } | ||||
CLNT_RELEASE(cl); | CLNT_RELEASE(cl); | ||||
mem_free(res.gid.gid_val, 0); | mem_free(res.gid.gid_val, 0); | ||||
/* Once the upcall is done, the daemon is done with the fp and so. */ | /* Once the upcall is done, the daemon is done with the fp and so. */ | ||||
mtx_lock(&rpctls_server_lock); | mtx_lock(&rpctls_server_lock); | ||||
rpctls_server_so = NULL; | KRPC_VNET(rpctls_server_so) = NULL; | ||||
rpctls_server_xprt = NULL; | KRPC_VNET(rpctls_server_xprt) = NULL; | ||||
rpctls_server_busy[procpos] = false; | KRPC_VNET(rpctls_server_busy)[procpos] = false; | ||||
wakeup(&rpctls_server_busy[procpos]); | wakeup(&KRPC_VNET(rpctls_server_busy)[procpos]); | ||||
mtx_unlock(&rpctls_server_lock); | mtx_unlock(&rpctls_server_lock); | ||||
KRPC_CURVNET_RESTORE(); | |||||
return (stat); | return (stat); | ||||
} | } | ||||
/* | /* | ||||
* Handle the NULL RPC with authentication flavor of AUTH_TLS. | * Handle the NULL RPC with authentication flavor of AUTH_TLS. | ||||
* This is a STARTTLS command, so do the upcall to the rpctlssd daemon, | * This is a STARTTLS command, so do the upcall to the rpctlssd daemon, | ||||
* which will do the TLS handshake. | * which will do the TLS handshake. | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
return (false); | return (false); | ||||
siz = sizeof(maxlen); | siz = sizeof(maxlen); | ||||
error = kernel_sysctlbyname(curthread, "kern.ipc.tls.maxlen", | error = kernel_sysctlbyname(curthread, "kern.ipc.tls.maxlen", | ||||
&maxlen, &siz, NULL, 0, NULL, 0); | &maxlen, &siz, NULL, 0, NULL, 0); | ||||
if (error != 0) | if (error != 0) | ||||
return (false); | return (false); | ||||
if (rpctlscd_run && rpctls_connect_handle == NULL) | if (rpctlscd_run && rpctls_connect_handle == NULL) | ||||
return (false); | return (false); | ||||
if (rpctlssd_run && rpctls_server_handle[0] == NULL) | KRPC_CURVNET_SET_QUIET(KRPC_TD_TO_VNET(curthread)); | ||||
if (rpctlssd_run && KRPC_VNET(rpctls_server_handle)[0] == NULL) { | |||||
KRPC_CURVNET_RESTORE(); | |||||
return (false); | return (false); | ||||
} | |||||
KRPC_CURVNET_RESTORE(); | |||||
*maxlenp = maxlen; | *maxlenp = maxlen; | ||||
return (enable); | return (enable); | ||||
} | |||||
/* Osd entry for prison cleanup. */ | |||||
int | |||||
rpctls_prison_cleanup(void *obj, void *data __unused) | |||||
{ | |||||
struct prison *pr = obj; | |||||
if ((pr->pr_flags & PR_VNET) == 0) | |||||
return (0); | |||||
KRPC_CURVNET_SET(pr->pr_vnet); | |||||
free(KRPC_VNET(rpctls_server_handle), M_RPC); | |||||
free(KRPC_VNET(rpctls_server_busy), M_RPC); | |||||
KRPC_CURVNET_RESTORE(); | |||||
return (0); | |||||
} | } | ||||