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>


 541                 return (EAGAIN);
 542         }
 543         mutex_exit(&di_lock);
 544 
 545         ASSERT(m < di_max_opens);
 546         *devp = makedevice(getmajor(*devp), (minor_t)(m + DI_NODE_SPECIES));
 547 
 548         dcmn_err((CE_CONT, "di_open: thread = %p, assigned minor = %d\n",
 549             (void *)curthread, m + DI_NODE_SPECIES));
 550 
 551         return (0);
 552 }
 553 
 554 /*ARGSUSED*/
 555 static int
 556 di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
 557 {
 558         struct di_state *st;
 559         int             m = (int)getminor(dev) - DI_NODE_SPECIES;
 560 
 561         if (m < 0) {
 562                 cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
 563                     m + DI_NODE_SPECIES);
 564                 return (ENXIO);
 565         }
 566 
 567         st = di_states[m];
 568         ASSERT(m < di_max_opens && st != NULL);
 569 
 570         di_freemem(st);
 571         kmem_free(st, sizeof (struct di_state));
 572 
 573         /*
 574          * empty slot in state table
 575          */
 576         mutex_enter(&di_lock);

 577         di_states[m] = NULL;







 578         dcmn_err((CE_CONT, "di_close: thread = %p, assigned minor = %d\n",
 579             (void *)curthread, m + DI_NODE_SPECIES));
 580         mutex_exit(&di_lock);
 581 
 582         return (0);
 583 }
 584 
 585 
 586 /*ARGSUSED*/
 587 static int
 588 di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
 589 {
 590         int             rv, error;
 591         di_off_t        off;
 592         struct di_all   *all;
 593         struct di_state *st;
 594         int             m = (int)getminor(dev) - DI_NODE_SPECIES;
 595         major_t         i;
 596         char            *drv_name;
 597         size_t          map_size, size;
 598         struct di_mem   *dcp;
 599         int             ndi_flags;
 600 
 601         if (m < 0 || m >= di_max_opens) {
 602                 return (ENXIO);
 603         }
 604 
 605         st = di_states[m];
 606         ASSERT(st != NULL);


 607 
 608         dcmn_err2((CE_CONT, "di_ioctl: mode = %x, cmd = %x\n", mode, cmd));
 609 
 610         switch (cmd) {
 611         case DINFOIDENT:
 612                 /*
 613                  * This is called from di_init to verify that the driver
 614                  * opened is indeed devinfo. The purpose is to guard against
 615                  * sending ioctl to an unknown driver in case of an
 616                  * unresolved major number conflict during bfu.
 617                  */
 618                 *rvalp = DI_MAGIC;
 619                 return (0);
 620 
 621         case DINFOLODRV:
 622                 /*
 623                  * Hold an installed driver and return the result
 624                  */
 625                 if (DI_UNPRIVILEGED_NODE(m)) {
 626                         /*




 541                 return (EAGAIN);
 542         }
 543         mutex_exit(&di_lock);
 544 
 545         ASSERT(m < di_max_opens);
 546         *devp = makedevice(getmajor(*devp), (minor_t)(m + DI_NODE_SPECIES));
 547 
 548         dcmn_err((CE_CONT, "di_open: thread = %p, assigned minor = %d\n",
 549             (void *)curthread, m + DI_NODE_SPECIES));
 550 
 551         return (0);
 552 }
 553 
 554 /*ARGSUSED*/
 555 static int
 556 di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
 557 {
 558         struct di_state *st;
 559         int             m = (int)getminor(dev) - DI_NODE_SPECIES;
 560 
 561         if (m < 0 || m >= di_max_opens) {
 562                 cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
 563                     m + DI_NODE_SPECIES);
 564                 return (ENXIO);
 565         }
 566 






 567         /*
 568          * empty slot in state table
 569          */
 570         mutex_enter(&di_lock);
 571         st = di_states[m];
 572         di_states[m] = NULL;
 573         mutex_exit(&di_lock);
 574 
 575         if (st != NULL) {
 576                 di_freemem(st);
 577                 kmem_free(st, sizeof (struct di_state));
 578         }
 579 
 580         dcmn_err((CE_CONT, "di_close: thread = %p, assigned minor = %d\n",
 581             (void *)curthread, m + DI_NODE_SPECIES));

 582 
 583         return (0);
 584 }
 585 
 586 
 587 /*ARGSUSED*/
 588 static int
 589 di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
 590 {
 591         int             rv, error;
 592         di_off_t        off;
 593         struct di_all   *all;
 594         struct di_state *st;
 595         int             m = (int)getminor(dev) - DI_NODE_SPECIES;
 596         major_t         i;
 597         char            *drv_name;
 598         size_t          map_size, size;
 599         struct di_mem   *dcp;
 600         int             ndi_flags;
 601 
 602         if (m < 0 || m >= di_max_opens) {
 603                 return (ENXIO);
 604         }
 605 
 606         st = di_states[m];
 607         if(st == NULL) {
 608                 return (ENXIO);
 609         }
 610 
 611         dcmn_err2((CE_CONT, "di_ioctl: mode = %x, cmd = %x\n", mode, cmd));
 612 
 613         switch (cmd) {
 614         case DINFOIDENT:
 615                 /*
 616                  * This is called from di_init to verify that the driver
 617                  * opened is indeed devinfo. The purpose is to guard against
 618                  * sending ioctl to an unknown driver in case of an
 619                  * unresolved major number conflict during bfu.
 620                  */
 621                 *rvalp = DI_MAGIC;
 622                 return (0);
 623 
 624         case DINFOLODRV:
 625                 /*
 626                  * Hold an installed driver and return the result
 627                  */
 628                 if (DI_UNPRIVILEGED_NODE(m)) {
 629                         /*