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,32 ****
--- 22,34 ----
   * 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,578 ****
  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*/
--- 570,579 ----
*** 579,601 ****
  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)
--- 580,592 ----
*** 948,961 ****
                  (void) putbq(q, mp);
                  return;
          }
  }
  
! /* ARGSUSED */
! static void
! rpcmod_release(queue_t *q, mblk_t *bp, bool_t enable)
  {
          struct rpcm *rmp;
  
          /*
           * For now, just free the message.
           */
--- 939,963 ----
                  (void) putbq(q, mp);
                  return;
          }
  }
  
! 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,1013 ****
          (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 *);
--- 1005,1014 ----
*** 1018,1033 ****
  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;
  
  /*
   * Timeout for subsequent notifications of idle connection.  This is
   * typically used to clean up after a wedged orderly release.
   */
--- 1019,1033 ----
  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_start)(queue_t *);
  extern void     (*clnt_stop_idle)(queue_t *);
  
! 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,1268 ****
  {
          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)
--- 1257,1266 ----
*** 2017,2031 ****
           * responses downstream, regardless of flow control.
           */
          qenable(wq);
  }
  
  /*
   * This routine is called directly by kRPC after a request is completed,
   * whether a reply was sent or the request was dropped.
   */
! static 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;
  
--- 2015,2039 ----
           * 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.
   */
! 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;