Print this page
3354 kernel crash in rpcsec_gss after using gsscred
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Carlos Neira <cneirabustos@gmail.com>
Approved by: Robert Mustacchi <rm@joyent.com>
NEX-771 Long RPC messages could confuse kernel and cause panic
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
re #12783 rb4338 Flow control is needed in rpcmod when the NFS server is unable to keep up with the network
re #13613 rb4516 Tunables needs volatile keyword
@@ -22,11 +22,13 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright 2012 Marcel Telka <marcel@telka.sk>
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
*/
/* Copyright (c) 1990 Mentat Inc. */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -568,11 +570,10 @@
rmm_close(queue_t *q, int flag, cred_t *crp)
{
return ((*((struct temp_slot *)q->q_ptr)->ops->xo_close)(q, flag, crp));
}
-static void rpcmod_release(queue_t *, mblk_t *, bool_t);
/*
* rpcmodopen - open routine gets called when the module gets pushed
* onto the stream.
*/
/*ARGSUSED*/
@@ -579,23 +580,13 @@
int
rpcmodopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
struct rpcm *rmp;
- extern void (*rpc_rele)(queue_t *, mblk_t *, bool_t);
-
TRACE_0(TR_FAC_KRPC, TR_RPCMODOPEN_START, "rpcmodopen_start:");
/*
- * Initialize entry points to release a rpcmod slot (and an input
- * message if supplied) and to send an output message to the module
- * below rpcmod.
- */
- if (rpc_rele == NULL)
- rpc_rele = rpcmod_release;
-
- /*
* Only sufficiently privileged users can use this module, and it
* is assumed that they will use this module properly, and NOT send
* bulk data from downstream.
*/
if (secpolicy_rpcmod_open(crp) != 0)
@@ -948,14 +939,25 @@
(void) putbq(q, mp);
return;
}
}
-/* ARGSUSED */
-static void
-rpcmod_release(queue_t *q, mblk_t *bp, bool_t enable)
+void
+rpcmod_hold(queue_t *q)
{
+ struct rpcm *rmp = (struct rpcm *)q->q_ptr;
+
+ mutex_enter(&rmp->rm_lock);
+ rmp->rm_ref++;
+ mutex_exit(&rmp->rm_lock);
+}
+
+void
+rpcmod_release(queue_t *q, mblk_t *bp,
+ /* LINTED E_FUNC_ARG_UNUSED */
+ bool_t enable __unused)
+{
struct rpcm *rmp;
/*
* For now, just free the message.
*/
@@ -1003,11 +1005,10 @@
(canputnext(write_q) || ((mir_ptr)->mir_svc_no_more_msgs == 1))
static int mir_clnt_dup_request(queue_t *q, mblk_t *mp);
static void mir_rput_proto(queue_t *q, mblk_t *mp);
static int mir_svc_policy_notify(queue_t *q, int event);
-static void mir_svc_release(queue_t *wq, mblk_t *mp, bool_t);
static void mir_svc_start(queue_t *wq);
static void mir_svc_idle_start(queue_t *, mir_t *);
static void mir_svc_idle_stop(queue_t *, mir_t *);
static void mir_svc_start_close(queue_t *, mir_t *);
static void mir_clnt_idle_do_stop(queue_t *);
@@ -1018,16 +1019,15 @@
static void mir_wsrv(queue_t *q);
static void mir_disconnect(queue_t *, mir_t *ir);
static int mir_check_len(queue_t *, mblk_t *);
static void mir_timer(void *);
-extern void (*mir_rele)(queue_t *, mblk_t *, bool_t);
extern void (*mir_start)(queue_t *);
extern void (*clnt_stop_idle)(queue_t *);
-clock_t clnt_idle_timeout = MIR_CLNT_IDLE_TIMEOUT;
-clock_t svc_idle_timeout = MIR_SVC_IDLE_TIMEOUT;
+volatile clock_t clnt_idle_timeout = MIR_CLNT_IDLE_TIMEOUT;
+volatile clock_t svc_idle_timeout = MIR_SVC_IDLE_TIMEOUT;
/*
* Timeout for subsequent notifications of idle connection. This is
* typically used to clean up after a wedged orderly release.
*/
@@ -1257,12 +1257,10 @@
{
mir_t *mir;
RPCLOG(32, "rpcmod: mir_open of q 0x%p\n", (void *)q);
/* Set variables used directly by kRPC. */
- if (!mir_rele)
- mir_rele = mir_svc_release;
if (!mir_start)
mir_start = mir_svc_start;
if (!clnt_stop_idle)
clnt_stop_idle = mir_clnt_idle_do_stop;
if (!clnt_max_msg_sizep)
@@ -2017,15 +2015,25 @@
* responses downstream, regardless of flow control.
*/
qenable(wq);
}
+void
+mir_svc_hold(queue_t *wq)
+{
+ mir_t *mir = (mir_t *)wq->q_ptr;
+
+ mutex_enter(&mir->mir_mutex);
+ mir->mir_ref_cnt++;
+ mutex_exit(&mir->mir_mutex);
+}
+
/*
* This routine is called directly by kRPC after a request is completed,
* whether a reply was sent or the request was dropped.
*/
-static void
+void
mir_svc_release(queue_t *wq, mblk_t *mp, bool_t enable)
{
mir_t *mir = (mir_t *)wq->q_ptr;
mblk_t *cmp = NULL;