Print this page
NEX-3997 Kernel BAD TRAP type=d panic from di_mem_addr on bogus di_state_t structure
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
        
*** 556,585 ****
  di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
  {
          struct di_state *st;
          int             m = (int)getminor(dev) - DI_NODE_SPECIES;
  
!         if (m < 0) {
                  cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
                      m + DI_NODE_SPECIES);
                  return (ENXIO);
          }
  
-         st = di_states[m];
-         ASSERT(m < di_max_opens && st != NULL);
- 
-         di_freemem(st);
-         kmem_free(st, sizeof (struct di_state));
- 
          /*
           * empty slot in state table
           */
          mutex_enter(&di_lock);
          di_states[m] = NULL;
          dcmn_err((CE_CONT, "di_close: thread = %p, assigned minor = %d\n",
              (void *)curthread, m + DI_NODE_SPECIES));
-         mutex_exit(&di_lock);
  
          return (0);
  }
  
  
--- 556,586 ----
  di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
  {
          struct di_state *st;
          int             m = (int)getminor(dev) - DI_NODE_SPECIES;
  
!         if (m < 0 || m >= di_max_opens) {
                  cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
                      m + DI_NODE_SPECIES);
                  return (ENXIO);
          }
  
          /*
           * empty slot in state table
           */
          mutex_enter(&di_lock);
+         st = di_states[m];
          di_states[m] = NULL;
+         mutex_exit(&di_lock);
+ 
+         if (st != NULL) {
+                 di_freemem(st);
+                 kmem_free(st, sizeof (struct di_state));
+         }
+ 
          dcmn_err((CE_CONT, "di_close: thread = %p, assigned minor = %d\n",
              (void *)curthread, m + DI_NODE_SPECIES));
  
          return (0);
  }
  
  
*** 601,611 ****
          if (m < 0 || m >= di_max_opens) {
                  return (ENXIO);
          }
  
          st = di_states[m];
!         ASSERT(st != NULL);
  
          dcmn_err2((CE_CONT, "di_ioctl: mode = %x, cmd = %x\n", mode, cmd));
  
          switch (cmd) {
          case DINFOIDENT:
--- 602,614 ----
          if (m < 0 || m >= di_max_opens) {
                  return (ENXIO);
          }
  
          st = di_states[m];
!         if(st == NULL) {
!                 return (ENXIO);
!         }
  
          dcmn_err2((CE_CONT, "di_ioctl: mode = %x, cmd = %x\n", mode, cmd));
  
          switch (cmd) {
          case DINFOIDENT: