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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/rpc/rpcmod.c
          +++ new/usr/src/uts/common/rpc/rpcmod.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  /*
  26   26   * Copyright 2012 Milan Jurik. All rights reserved.
       27 + * Copyright 2012 Marcel Telka <marcel@telka.sk>
  27   28   * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       29 + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  28   30   */
  29   31  /* Copyright (c) 1990 Mentat Inc. */
  30   32  
  31   33  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  32      -/*        All Rights Reserved   */
       34 +/*      All Rights Reserved     */
  33   35  
  34   36  /*
  35   37   * Kernel RPC filtering module
  36   38   */
  37   39  
  38   40  #include <sys/param.h>
  39   41  #include <sys/types.h>
  40   42  #include <sys/stream.h>
  41   43  #include <sys/stropts.h>
  42   44  #include <sys/strsubr.h>
↓ open down ↓ 520 lines elided ↑ open up ↑
 563  565  {
 564  566          (*((struct temp_slot *)q->q_ptr)->ops->xo_wsrv)(q);
 565  567  }
 566  568  
 567  569  int
 568  570  rmm_close(queue_t *q, int flag, cred_t *crp)
 569  571  {
 570  572          return ((*((struct temp_slot *)q->q_ptr)->ops->xo_close)(q, flag, crp));
 571  573  }
 572  574  
 573      -static void rpcmod_release(queue_t *, mblk_t *, bool_t);
 574  575  /*
 575  576   * rpcmodopen - open routine gets called when the module gets pushed
 576  577   *              onto the stream.
 577  578   */
 578  579  /*ARGSUSED*/
 579  580  int
 580  581  rpcmodopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
 581  582  {
 582  583          struct rpcm *rmp;
 583  584  
 584      -        extern void (*rpc_rele)(queue_t *, mblk_t *, bool_t);
 585      -
 586  585          TRACE_0(TR_FAC_KRPC, TR_RPCMODOPEN_START, "rpcmodopen_start:");
 587  586  
 588  587          /*
 589      -         * Initialize entry points to release a rpcmod slot (and an input
 590      -         * message if supplied) and to send an output message to the module
 591      -         * below rpcmod.
 592      -         */
 593      -        if (rpc_rele == NULL)
 594      -                rpc_rele = rpcmod_release;
 595      -
 596      -        /*
 597  588           * Only sufficiently privileged users can use this module, and it
 598  589           * is assumed that they will use this module properly, and NOT send
 599  590           * bulk data from downstream.
 600  591           */
 601  592          if (secpolicy_rpcmod_open(crp) != 0)
 602  593                  return (EPERM);
 603  594  
 604  595          /*
 605  596           * Allocate slot data structure.
 606  597           */
↓ open down ↓ 336 lines elided ↑ open up ↑
 943  934                   */
 944  935                  if (rmp->rm_type == RPC_SERVER || canputnext(q)) {
 945  936                          putnext(q, mp);
 946  937                          continue;
 947  938                  }
 948  939                  (void) putbq(q, mp);
 949  940                  return;
 950  941          }
 951  942  }
 952  943  
 953      -/* ARGSUSED */
 954      -static void
 955      -rpcmod_release(queue_t *q, mblk_t *bp, bool_t enable)
      944 +void
      945 +rpcmod_hold(queue_t *q)
 956  946  {
      947 +        struct rpcm *rmp = (struct rpcm *)q->q_ptr;
      948 +
      949 +        mutex_enter(&rmp->rm_lock);
      950 +        rmp->rm_ref++;
      951 +        mutex_exit(&rmp->rm_lock);
      952 +}
      953 +
      954 +void
      955 +rpcmod_release(queue_t *q, mblk_t *bp,
      956 +    /* LINTED E_FUNC_ARG_UNUSED */
      957 +    bool_t enable __unused)
      958 +{
 957  959          struct rpcm *rmp;
 958  960  
 959  961          /*
 960  962           * For now, just free the message.
 961  963           */
 962  964          if (bp)
 963  965                  freemsg(bp);
 964  966          rmp = (struct rpcm *)q->q_ptr;
 965  967  
 966  968          mutex_enter(&rmp->rm_lock);
↓ open down ↓ 31 lines elided ↑ open up ↑
 998 1000  /*
 999 1001   * Don't block service procedure (and mir_close) if
1000 1002   * we are in the process of closing.
1001 1003   */
1002 1004  #define MIR_WCANPUTNEXT(mir_ptr, write_q)       \
1003 1005          (canputnext(write_q) || ((mir_ptr)->mir_svc_no_more_msgs == 1))
1004 1006  
1005 1007  static int      mir_clnt_dup_request(queue_t *q, mblk_t *mp);
1006 1008  static void     mir_rput_proto(queue_t *q, mblk_t *mp);
1007 1009  static int      mir_svc_policy_notify(queue_t *q, int event);
1008      -static void     mir_svc_release(queue_t *wq, mblk_t *mp, bool_t);
1009 1010  static void     mir_svc_start(queue_t *wq);
1010 1011  static void     mir_svc_idle_start(queue_t *, mir_t *);
1011 1012  static void     mir_svc_idle_stop(queue_t *, mir_t *);
1012 1013  static void     mir_svc_start_close(queue_t *, mir_t *);
1013 1014  static void     mir_clnt_idle_do_stop(queue_t *);
1014 1015  static void     mir_clnt_idle_stop(queue_t *, mir_t *);
1015 1016  static void     mir_clnt_idle_start(queue_t *, mir_t *);
1016 1017  static void     mir_wput(queue_t *q, mblk_t *mp);
1017 1018  static void     mir_wput_other(queue_t *q, mblk_t *mp);
1018 1019  static void     mir_wsrv(queue_t *q);
1019 1020  static  void    mir_disconnect(queue_t *, mir_t *ir);
1020 1021  static  int     mir_check_len(queue_t *, mblk_t *);
1021 1022  static  void    mir_timer(void *);
1022 1023  
1023      -extern void     (*mir_rele)(queue_t *, mblk_t *, bool_t);
1024 1024  extern void     (*mir_start)(queue_t *);
1025 1025  extern void     (*clnt_stop_idle)(queue_t *);
1026 1026  
1027      -clock_t clnt_idle_timeout = MIR_CLNT_IDLE_TIMEOUT;
1028      -clock_t svc_idle_timeout = MIR_SVC_IDLE_TIMEOUT;
     1027 +volatile clock_t        clnt_idle_timeout = MIR_CLNT_IDLE_TIMEOUT;
     1028 +volatile clock_t        svc_idle_timeout = MIR_SVC_IDLE_TIMEOUT;
1029 1029  
1030 1030  /*
1031 1031   * Timeout for subsequent notifications of idle connection.  This is
1032 1032   * typically used to clean up after a wedged orderly release.
1033 1033   */
1034 1034  clock_t svc_ordrel_timeout = MIR_SVC_ORDREL_TIMEOUT; /* milliseconds */
1035 1035  
1036 1036  extern  uint_t  *clnt_max_msg_sizep;
1037 1037  extern  uint_t  *svc_max_msg_sizep;
1038 1038  uint_t  clnt_max_msg_size = RPC_MAXDATASIZE;
↓ open down ↓ 213 lines elided ↑ open up ↑
1252 1252  }
1253 1253  
1254 1254  /* ARGSUSED */
1255 1255  static int
1256 1256  mir_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
1257 1257  {
1258 1258          mir_t   *mir;
1259 1259  
1260 1260          RPCLOG(32, "rpcmod: mir_open of q 0x%p\n", (void *)q);
1261 1261          /* Set variables used directly by kRPC. */
1262      -        if (!mir_rele)
1263      -                mir_rele = mir_svc_release;
1264 1262          if (!mir_start)
1265 1263                  mir_start = mir_svc_start;
1266 1264          if (!clnt_stop_idle)
1267 1265                  clnt_stop_idle = mir_clnt_idle_do_stop;
1268 1266          if (!clnt_max_msg_sizep)
1269 1267                  clnt_max_msg_sizep = &clnt_max_msg_size;
1270 1268          if (!svc_max_msg_sizep)
1271 1269                  svc_max_msg_sizep = &svc_max_msg_size;
1272 1270  
1273 1271          /* Allocate a zero'ed out mir structure for this stream. */
↓ open down ↓ 738 lines elided ↑ open up ↑
2012 2010          mir->mir_hold_inbound = 0;
2013 2011          qenable(RD(wq));
2014 2012  
2015 2013          /*
2016 2014           * Meanwhile force the write service procedure to send the
2017 2015           * responses downstream, regardless of flow control.
2018 2016           */
2019 2017          qenable(wq);
2020 2018  }
2021 2019  
     2020 +void
     2021 +mir_svc_hold(queue_t *wq)
     2022 +{
     2023 +        mir_t *mir = (mir_t *)wq->q_ptr;
     2024 +
     2025 +        mutex_enter(&mir->mir_mutex);
     2026 +        mir->mir_ref_cnt++;
     2027 +        mutex_exit(&mir->mir_mutex);
     2028 +}
     2029 +
2022 2030  /*
2023 2031   * This routine is called directly by kRPC after a request is completed,
2024 2032   * whether a reply was sent or the request was dropped.
2025 2033   */
2026      -static void
     2034 +void
2027 2035  mir_svc_release(queue_t *wq, mblk_t *mp, bool_t enable)
2028 2036  {
2029 2037          mir_t   *mir = (mir_t *)wq->q_ptr;
2030 2038          mblk_t  *cmp = NULL;
2031 2039  
2032 2040          ASSERT((wq->q_flag & QREADR) == 0);
2033 2041          if (mp)
2034 2042                  freemsg(mp);
2035 2043  
2036 2044          if (enable)
↓ open down ↓ 810 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX