Print this page
    
OS-4112 stack overflow from promisc callbacks
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/disp/thread_intr.c
          +++ new/usr/src/uts/common/disp/thread_intr.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26      -
  27   26  /*
  28      - * FILE NOTICE BEGIN
  29      - *
  30      - * This file should not be modified.  If you wish to modify it or have it
  31      - * modified, please contact Sun Microsystems at <LFI149367@-sun-.-com->
  32      - * (without anti-spam dashes)
  33      - *
  34      - * FILE NOTICE END
       27 + * Copyright 2015, Joyent, Inc.
  35   28   */
  36   29  
  37      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  38      -
  39   30  #include <sys/cpuvar.h>
  40   31  #include <sys/stack.h>
  41   32  #include <vm/seg_kp.h>
  42   33  #include <sys/proc.h>
  43   34  #include <sys/pset.h>
  44   35  #include <sys/sysmacros.h>
  45   36  
  46   37  /*
       38 + * Use a slightly larger thread stack size for interrupt threads rather than the
       39 + * default. This is useful for cases where the networking stack may do an rx and
       40 + * a tx in the context of a single interrupt and when combined with various
       41 + * promisc hooks that need memory, can cause us to get dangerously close to the
       42 + * edge of the traditional stack sizes. This is only a few pages more than a
       43 + * traditional stack and given that we don't have that many interrupt threads,
       44 + * the memory costs end up being more than worthwhile.
       45 + */
       46 +#define LL_INTR_STKSZ   (32 * 1024)
       47 +
       48 +/*
  47   49   * Create and initialize an interrupt thread.
  48   50   */
  49   51  static void
  50   52  thread_create_intr(cpu_t *cp)
  51   53  {
  52   54          kthread_t *tp;
  53   55  
  54      -        tp = thread_create(NULL, 0,
       56 +        tp = thread_create(NULL, LL_INTR_STKSZ,
  55   57              (void (*)())thread_create_intr, NULL, 0, &p0, TS_ONPROC, 0);
  56   58  
  57   59          /*
  58   60           * Set the thread in the TS_FREE state.  The state will change
  59   61           * to TS_ONPROC only while the interrupt is active.  Think of these
  60   62           * as being on a private free list for the CPU.  Being TS_FREE keeps
  61   63           * inactive interrupt threads out of debugger thread lists.
  62   64           *
  63   65           * We cannot call thread_create with TS_FREE because of the current
  64   66           * checks there for ONPROC.  Fix this when thread_create takes flags.
  65   67           */
  66   68          THREAD_FREEINTR(tp, cp);
  67   69  
  68   70          /*
  69   71           * Nobody should ever reference the credentials of an interrupt
  70   72           * thread so make it NULL to catch any such references.
  71   73           */
  72   74          tp->t_cred = NULL;
  73   75          tp->t_flag |= T_INTR_THREAD;
  74   76          tp->t_cpu = cp;
  75   77          tp->t_bound_cpu = cp;
  76   78          tp->t_disp_queue = cp->cpu_disp;
  77   79          tp->t_affinitycnt = 1;
  78   80          tp->t_preempt = 1;
  79   81  
  80   82          /*
  81   83           * Don't make a user-requested binding on this thread so that
  82   84           * the processor can be offlined.
  83   85           */
  84   86          tp->t_bind_cpu = PBIND_NONE;    /* no USER-requested binding */
  85   87          tp->t_bind_pset = PS_NONE;
  86   88  
  87   89  #if defined(__i386) || defined(__amd64)
  88   90          tp->t_stk -= STACK_ALIGN;
  89   91          *(tp->t_stk) = 0;               /* terminate intr thread stack */
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
  90   92  #endif
  91   93  
  92   94          /*
  93   95           * Link onto CPU's interrupt pool.
  94   96           */
  95   97          tp->t_link = cp->cpu_intr_thread;
  96   98          cp->cpu_intr_thread = tp;
  97   99  }
  98  100  
  99  101  /*
 100      - * Allocate a given number of interrupt threads for a given CPU.
 101      - * These threads will get freed by cpu_destroy_bound_threads()
 102      - * when CPU gets unconfigured.
      102 + * Allocate a given number of interrupt threads for a given CPU.  These threads
      103 + * will get freed by cpu_destroy_bound_threads() when CPU gets unconfigured.
      104 + *
      105 + * Note, high level interrupts are always serviced using cpu_intr_stack and are
      106 + * not allowed to block. Low level interrupts or soft-interrupts use the
      107 + * kthread_t's that we create through the calls to thread_create_intr().
 103  108   */
 104  109  void
 105  110  cpu_intr_alloc(cpu_t *cp, int n)
 106  111  {
 107  112          int i;
 108  113  
 109  114          for (i = 0; i < n; i++)
 110  115                  thread_create_intr(cp);
 111  116  
 112  117          cp->cpu_intr_stack = (caddr_t)segkp_get(segkp, INTR_STACK_SIZE,
 113      -                KPD_HASREDZONE | KPD_NO_ANON | KPD_LOCKED) +
 114      -                INTR_STACK_SIZE - SA(MINFRAME);
      118 +            KPD_HASREDZONE | KPD_NO_ANON | KPD_LOCKED) +
      119 +            INTR_STACK_SIZE - SA(MINFRAME);
 115  120  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX