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;