615 * user's address space via setcontext(2) or /proc.
616 *
617 * Note about null selector. When running on the hypervisor if we allow a
618 * process to set its %cs to null selector with RPL of 0 the hypervisor will
619 * crash the domain. If running on bare metal we would get a #gp fault and
620 * be able to kill the process and continue on. Therefore we make sure to
621 * force RPL to SEL_UPL even for null selector when setting %cs.
622 */
623
624 #if defined(IS_CS) || defined(IS_NOT_CS)
625 #error "IS_CS and IS_NOT_CS already defined"
626 #endif
627
628 #define IS_CS 1
629 #define IS_NOT_CS 0
630
631 /*ARGSUSED*/
632 static greg_t
633 fix_segreg(greg_t sr, int iscs, model_t datamodel)
634 {
635 switch (sr &= 0xffff) {
636
637 case 0:
638 if (iscs == IS_CS)
639 return (0 | SEL_UPL);
640 else
641 return (0);
642
643 #if defined(__amd64)
644 /*
645 * If lwp attempts to switch data model then force their
646 * code selector to be null selector.
647 */
648 case U32CS_SEL:
649 if (datamodel == DATAMODEL_NATIVE)
650 return (0 | SEL_UPL);
651 else
652 return (sr);
653
654 case UCS_SEL:
655 if (datamodel == DATAMODEL_ILP32)
656 return (0 | SEL_UPL);
657 #elif defined(__i386)
658 case UCS_SEL:
659 #endif
660 /*FALLTHROUGH*/
661 case UDS_SEL:
662 case LWPFS_SEL:
663 case LWPGS_SEL:
664 case SEL_UPL:
665 return (sr);
666 default:
667 break;
668 }
669
670 /*
671 * Force it into the LDT in ring 3 for 32-bit processes, which by
672 * default do not have an LDT, so that any attempt to use an invalid
673 * selector will reference the (non-existant) LDT, and cause a #gp
674 * fault for the process.
675 *
676 * 64-bit processes get the null gdt selector since they
677 * are not allowed to have a private LDT.
678 */
679 #if defined(__amd64)
680 if (datamodel == DATAMODEL_ILP32) {
681 return (sr | SEL_TI_LDT | SEL_UPL);
682 } else {
683 if (iscs == IS_CS)
684 return (0 | SEL_UPL);
685 else
686 return (0);
687 }
|
615 * user's address space via setcontext(2) or /proc.
616 *
617 * Note about null selector. When running on the hypervisor if we allow a
618 * process to set its %cs to null selector with RPL of 0 the hypervisor will
619 * crash the domain. If running on bare metal we would get a #gp fault and
620 * be able to kill the process and continue on. Therefore we make sure to
621 * force RPL to SEL_UPL even for null selector when setting %cs.
622 */
623
624 #if defined(IS_CS) || defined(IS_NOT_CS)
625 #error "IS_CS and IS_NOT_CS already defined"
626 #endif
627
628 #define IS_CS 1
629 #define IS_NOT_CS 0
630
631 /*ARGSUSED*/
632 static greg_t
633 fix_segreg(greg_t sr, int iscs, model_t datamodel)
634 {
635 kthread_t *t = curthread;
636
637 switch (sr &= 0xffff) {
638
639 case 0:
640 if (iscs == IS_CS)
641 return (0 | SEL_UPL);
642 else
643 return (0);
644
645 #if defined(__amd64)
646 /*
647 * If lwp attempts to switch data model then force their
648 * code selector to be null selector.
649 */
650 case U32CS_SEL:
651 if (datamodel == DATAMODEL_NATIVE)
652 return (0 | SEL_UPL);
653 else
654 return (sr);
655
656 case UCS_SEL:
657 if (datamodel == DATAMODEL_ILP32)
658 return (0 | SEL_UPL);
659 #elif defined(__i386)
660 case UCS_SEL:
661 #endif
662 /*FALLTHROUGH*/
663 case UDS_SEL:
664 case LWPFS_SEL:
665 case LWPGS_SEL:
666 case SEL_UPL:
667 return (sr);
668 default:
669 break;
670 }
671
672 /*
673 * Allow this process's brand to do any necessary segment register
674 * manipulation.
675 */
676 if (PROC_IS_BRANDED(t->t_procp) && BRMOP(t->t_procp)->b_fixsegreg) {
677 greg_t bsr = BRMOP(t->t_procp)->b_fixsegreg(sr, datamodel);
678
679 if (bsr == 0 && iscs == IS_CS)
680 return (0 | SEL_UPL);
681 else
682 return (bsr);
683 }
684
685 /*
686 * Force it into the LDT in ring 3 for 32-bit processes, which by
687 * default do not have an LDT, so that any attempt to use an invalid
688 * selector will reference the (non-existant) LDT, and cause a #gp
689 * fault for the process.
690 *
691 * 64-bit processes get the null gdt selector since they
692 * are not allowed to have a private LDT.
693 */
694 #if defined(__amd64)
695 if (datamodel == DATAMODEL_ILP32) {
696 return (sr | SEL_TI_LDT | SEL_UPL);
697 } else {
698 if (iscs == IS_CS)
699 return (0 | SEL_UPL);
700 else
701 return (0);
702 }
|