summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Rochford <Karen.Rochford@Sun.COM>2010-03-22 08:06:49 -0500
committerKaren Rochford <Karen.Rochford@Sun.COM>2010-03-22 08:06:49 -0500
commit60536ef9142d77aa1b72c9be89a1833c06e14629 (patch)
tree4ca5b5817456287d72348d0c9e28d0c7de30be84
parentb92a49ee0e4c83e644a2e7f8cd7753cd479a412a (diff)
downloadillumos-gate-60536ef9142d77aa1b72c9be89a1833c06e14629.tar.gz
6896473 Server rpcmod panic when client trying to mount rdma/krb5
-rw-r--r--usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c15
-rw-r--r--usr/src/uts/common/rpc/svc.c16
-rw-r--r--usr/src/uts/common/rpc/svc.h12
-rw-r--r--usr/src/uts/common/rpc/svc_clts.c20
-rw-r--r--usr/src/uts/common/rpc/svc_cots.c5
-rw-r--r--usr/src/uts/common/rpc/svc_rdma.c57
6 files changed, 93 insertions, 32 deletions
diff --git a/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c b/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c
index ffe4255580..3d47fab865 100644
--- a/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c
+++ b/usr/src/uts/common/rpc/sec_gss/svc_rpcsec_gss.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -970,20 +970,9 @@ rpcsec_gss_init(
/* get a xprt clone for taskq thread, taskq func must free it */
arg->rq_xprt = svc_clone_init();
- svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt);
+ svc_clone_link(rqst->rq_xprt->xp_master, arg->rq_xprt, rqst->rq_xprt);
arg->rq_xprt->xp_xid = rqst->rq_xprt->xp_xid;
- /* UDP uses the incoming mblk for the response, so dup it. */
- /* Note this probably should be done by svc_clone_link(). */
- if (rqst->rq_xprt->xp_type == T_CLTS) {
- struct udp_data *ud_src =
- (struct udp_data *)rqst->rq_xprt->xp_p2buf;
- struct udp_data *ud_dst =
- (struct udp_data *)arg->rq_xprt->xp_p2buf;
- if (ud_src->ud_resp) {
- ud_dst->ud_resp = dupb(ud_src->ud_resp);
- }
- }
/* set the appropriate wrap/unwrap routine for RPCSEC_GSS */
arg->rq_xprt->xp_auth.svc_ah_ops = svc_rpc_gss_ops;
diff --git a/usr/src/uts/common/rpc/svc.c b/usr/src/uts/common/rpc/svc.c
index 7c2f7f2f5e..a6bf8c76b2 100644
--- a/usr/src/uts/common/rpc/svc.c
+++ b/usr/src/uts/common/rpc/svc.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1469,7 +1469,7 @@ svc_clone_free(SVCXPRT *clone_xprt)
* - call a transport specific clone routine.
*/
void
-svc_clone_link(SVCMASTERXPRT *xprt, SVCXPRT *clone_xprt)
+svc_clone_link(SVCMASTERXPRT *xprt, SVCXPRT *clone_xprt, SVCXPRT *clone_xprt2)
{
cred_t *cred = clone_xprt->xp_cred;
@@ -1496,14 +1496,8 @@ svc_clone_link(SVCMASTERXPRT *xprt, SVCXPRT *clone_xprt)
/* Restore per-thread fields (xp_cred) */
clone_xprt->xp_cred = cred;
-
- /*
- * NOTICE: There is no transport-type specific code now.
- * If you want to add a transport-type specific cloning code
- * add one more operation (e.g. xp_clone()) to svc_ops,
- * implement it for each transport type, and call it here
- * through an appropriate macro (e.g. SVC_CLONE()).
- */
+ if (clone_xprt2)
+ SVC_CLONE_XPRT(clone_xprt2, clone_xprt);
}
/*
@@ -2192,7 +2186,7 @@ svc_run(SVCPOOL *pool)
if (next != xprt) {
if (xprt)
svc_clone_unlink(clone_xprt);
- svc_clone_link(next, clone_xprt);
+ svc_clone_link(next, clone_xprt, NULL);
xprt = next;
}
diff --git a/usr/src/uts/common/rpc/svc.h b/usr/src/uts/common/rpc/svc.h
index cd9149afd2..912d5b3961 100644
--- a/usr/src/uts/common/rpc/svc.h
+++ b/usr/src/uts/common/rpc/svc.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -187,6 +187,8 @@ struct svc_ops {
/* destroy a clone xprt */
void (*xp_start)(SVCMASTERXPRT *);
/* `ready-to-receive' */
+ void (*xp_clone_xprt)(SVCXPRT *, SVCXPRT *);
+ /* transport specific clone function */
};
#else /* _KERNEL */
/*
@@ -510,6 +512,12 @@ struct __svcxprt {
*/
#ifdef _KERNEL
+
+#define SVC_CLONE_XPRT(src_xprt, dst_xprt) \
+ if ((src_xprt)->xp_ops->xp_clone_xprt) \
+ (*(src_xprt)->xp_ops->xp_clone_xprt) \
+ (src_xprt, dst_xprt)
+
#define SVC_RECV(clone_xprt, mp, msg) \
(*(clone_xprt)->xp_ops->xp_recv)((clone_xprt), (mp), (msg))
@@ -1103,7 +1111,7 @@ extern int __svc_vc_dupdone();
*/
extern SVCXPRT *svc_clone_init(void);
extern void svc_clone_free(SVCXPRT *);
-extern void svc_clone_link(SVCMASTERXPRT *, SVCXPRT *);
+extern void svc_clone_link(SVCMASTERXPRT *, SVCXPRT *, SVCXPRT *);
extern void svc_clone_unlink(SVCXPRT *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/rpc/svc_clts.c b/usr/src/uts/common/rpc/svc_clts.c
index 56355eae8a..a738e63863 100644
--- a/usr/src/uts/common/rpc/svc_clts.c
+++ b/usr/src/uts/common/rpc/svc_clts.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -79,6 +79,7 @@ static int32_t *svc_clts_kgetres(SVCXPRT *, int);
static void svc_clts_kclone_destroy(SVCXPRT *);
static void svc_clts_kfreeres(SVCXPRT *);
static void svc_clts_kstart(SVCMASTERXPRT *);
+static void svc_clts_kclone_xprt(SVCXPRT *, SVCXPRT *);
/*
* Server transport operations vector.
@@ -94,7 +95,8 @@ struct svc_ops svc_clts_op = {
svc_clts_kgetres, /* Get pointer to response buffer */
svc_clts_kfreeres, /* Destroy pre-serialized response header */
svc_clts_kclone_destroy, /* Destroy a clone xprt */
- svc_clts_kstart /* Tell `ready-to-receive' to rpcmod */
+ svc_clts_kstart, /* Tell `ready-to-receive' to rpcmod */
+ svc_clts_kclone_xprt /* transport specific clone xprt function */
};
/*
@@ -230,6 +232,20 @@ svc_clts_kstart(SVCMASTERXPRT *xprt)
{
}
+static void
+svc_clts_kclone_xprt(SVCXPRT *src_xprt, SVCXPRT *dst_xprt)
+{
+ struct udp_data *ud_src =
+ (struct udp_data *)src_xprt->xp_p2buf;
+ struct udp_data *ud_dst =
+ (struct udp_data *)dst_xprt->xp_p2buf;
+
+ if (ud_src->ud_resp)
+ ud_dst->ud_resp = dupb(ud_src->ud_resp);
+
+}
+
+
/*
* Receive rpc requests.
* Pulls a request in off the socket, checks if the packet is intact,
diff --git a/usr/src/uts/common/rpc/svc_cots.c b/usr/src/uts/common/rpc/svc_cots.c
index c010f145a3..32ad943958 100644
--- a/usr/src/uts/common/rpc/svc_cots.c
+++ b/usr/src/uts/common/rpc/svc_cots.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,7 +99,8 @@ struct svc_ops svc_cots_op = {
svc_cots_kgetres, /* Get pointer to response buffer */
svc_cots_kfreeres, /* Destroy pre-serialized response header */
svc_cots_kclone_destroy, /* Destroy a clone xprt */
- svc_cots_kstart /* Tell `ready-to-receive' to rpcmod */
+ svc_cots_kstart, /* Tell `ready-to-receive' to rpcmod */
+ NULL /* Transport specific clone xprt */
};
/*
diff --git a/usr/src/uts/common/rpc/svc_rdma.c b/usr/src/uts/common/rpc/svc_rdma.c
index 18c32559c6..89770026e1 100644
--- a/usr/src/uts/common/rpc/svc_rdma.c
+++ b/usr/src/uts/common/rpc/svc_rdma.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -90,12 +90,14 @@ struct rdma_data {
* Plugin connection specific data stashed away in clone SVCXPRT
*/
struct clone_rdma_data {
+ bool_t cloned; /* xprt cloned for thread processing */
CONN *conn; /* RDMA connection */
rdma_buf_t rpcbuf; /* RPC req/resp buffer */
struct clist *cl_reply; /* reply chunk buffer info */
struct clist *cl_wlist; /* write list clist */
};
+
#define MAXADDRLEN 128 /* max length for address mask */
/*
@@ -115,6 +117,7 @@ static void svc_rdma_kfreeres(SVCXPRT *);
static void svc_rdma_kclone_destroy(SVCXPRT *);
static void svc_rdma_kstart(SVCMASTERXPRT *);
void svc_rdma_kstop(SVCMASTERXPRT *);
+static void svc_rdma_kclone_xprt(SVCXPRT *, SVCXPRT *);
static int svc_process_long_reply(SVCXPRT *, xdrproc_t,
caddr_t, struct rpc_msg *, bool_t, int *,
@@ -141,7 +144,8 @@ struct svc_ops rdma_svc_ops = {
svc_rdma_kgetres, /* Get pointer to response buffer */
svc_rdma_kfreeres, /* Destroy pre-serialized response header */
svc_rdma_kclone_destroy, /* Destroy a clone xprt */
- svc_rdma_kstart /* Tell `ready-to-receive' to rpcmod */
+ svc_rdma_kstart, /* Tell `ready-to-receive' to rpcmod */
+ svc_rdma_kclone_xprt /* Transport specific clone xprt */
};
/*
@@ -384,8 +388,46 @@ svc_rdma_kstop(SVCMASTERXPRT *xprt)
static void
svc_rdma_kclone_destroy(SVCXPRT *clone_xprt)
{
+
+ struct clone_rdma_data *cdrp;
+ cdrp = (struct clone_rdma_data *)clone_xprt->xp_p2buf;
+
+ /*
+ * Only free buffers and release connection when cloned is set.
+ */
+ if (cdrp->cloned != TRUE)
+ return;
+
+ rdma_buf_free(cdrp->conn, &cdrp->rpcbuf);
+ if (cdrp->cl_reply) {
+ clist_free(cdrp->cl_reply);
+ cdrp->cl_reply = NULL;
+ }
+ RDMA_REL_CONN(cdrp->conn);
+
+ cdrp->cloned = 0;
}
+/*
+ * Clone the xprt specific information. It will be freed by
+ * SVC_CLONE_DESTROY.
+ */
+static void
+svc_rdma_kclone_xprt(SVCXPRT *src_xprt, SVCXPRT *dst_xprt)
+{
+ struct clone_rdma_data *srcp2;
+ struct clone_rdma_data *dstp2;
+
+ srcp2 = (struct clone_rdma_data *)src_xprt->xp_p2buf;
+ dstp2 = (struct clone_rdma_data *)dst_xprt->xp_p2buf;
+
+ if (srcp2->conn != NULL) {
+ srcp2->cloned = TRUE;
+ *dstp2 = *srcp2;
+ }
+}
+
+
static bool_t
svc_rdma_krecv(SVCXPRT *clone_xprt, mblk_t *mp, struct rpc_msg *msg)
{
@@ -1029,7 +1071,18 @@ svc_rdma_kfreeargs(SVCXPRT *clone_xprt, xdrproc_t xdr_args,
struct clone_rdma_data *crdp;
bool_t retval;
+ /*
+ * If the cloned bit is true, then this transport specific
+ * rmda data has been duplicated into another cloned xprt. Do
+ * not free, or release the connection, it is still in use. The
+ * buffers will be freed and the connection released later by
+ * SVC_CLONE_DESTROY().
+ */
crdp = (struct clone_rdma_data *)clone_xprt->xp_p2buf;
+ if (crdp->cloned == TRUE) {
+ crdp->cloned = 0;
+ return (TRUE);
+ }
/*
* Free the args if needed then XDR_DESTROY