VirtualBox

Changeset 51770 in vbox for trunk/src/VBox/HostDrivers


Ignore:
Timestamp:
Jul 1, 2014 6:14:02 PM (11 years ago)
Author:
vboxsync
Message:

Merged in iprt++ dev branch.

Location:
trunk
Files:
23 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/VBox

  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r51346 r51770  
    3131# Targets
    3232#
    33 LIBRARIES += SUPR3 SUPR3Static SUPR3HardenedStatic
     33LIBRARIES += SUPR3 SUPR3Static
     34ifdef VBOX_WITH_HARDENING
     35 LIBRARIES += SUPR3HardenedStatic
     36endif
     37DLLS.win += VBoxSupLib
    3438ifdef VBOX_WITH_32_ON_64_MAIN_API
    3539 LIBRARIES += SUPR3-x86
     
    7074endif # !VBOX_ONLY_DOCS && !VBOX_ONLY_EXTPACKS && !VBOX_ONLY_VALIDATIONKIT
    7175
     76#
     77# Authenticode related trust anchors and certificates -> .cpp
     78#
     79VBOX_SUP_WIN_CERTS_FILE = $(SUPR3_0_OUTDIR)/TrustAnchorsAndCerts.cpp
     80VBOX_SUP_WIN_CERTS := \
     81       SpcRootMicrosoft0=SpcRoot-MicrosoftAuthenticodeTmRootAuthority-01.taf \
     82       SpcRootMicrosoft1=SpcRoot-MicrosoftRootAuthority-00c1008b3c3c8811d13ef663ecdf40.taf \
     83       SpcRootMicrosoft2=SpcRoot-MicrosoftRootCertificateAuthority-79ad16a14aa0a5ad4c7358f407132e65.taf \
     84       SpcRootMicrosoft3=SpcRoot-MicrosoftRootCertificateAuthority2010-28cc3a25bfba44ac449a9b586b4339aa.taf \
     85       SpcRootMicrosoft4=SpcRoot-MicrosoftRootCertificateAuthority2011-3f8bc8b5fc9fb29643b569d66c42e144.taf \
     86       SpcRootMicrosoft5=SpcRoot-MicrosoftDigitalMediaAuthority2005-6eff330eb6e7569740680870104baaba.taf \
     87       NtRootMicrosoft6=NtRoot-MicrosoftCodeVerificationRoot-729404101f3e0ca347837fca175a8438.taf \
     88       TimeRootMicrosoft0=Timestamp-CopyrightC1997MicrosoftCorp-01.taf \
     89       TrustedCertVBox0=Trusted-OracleCorporationVirtualBox-51ca009816fdbd80f120e015ee75823e.taf
     90VBOX_SUP_WIN_CERT_NAMES := $(foreach cert,$(VBOX_SUP_WIN_CERTS),$(firstword $(subst =,$(SPACE) ,$(cert))))
     91VBOX_PATH_SUPR3_CERTIFICATES := $(PATH_SUB_CURRENT)/win/Certificates
     92
     93# 1=name, 2=filter, 3=buildcert?.
     94if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_HARDENING)
     95 VBOX_SUP_GEN_CERT_MACRO = 'SUPTAENTRY const g_aSUP$(1)TAs[] =' '{' \
     96       $(if-expr "$(3)" == "",,'    SUPTAENTRY_GEN(g_abSUPBuildCert),') \
     97        $(foreach certnm,$(filter $(2),$(VBOX_SUP_WIN_CERT_NAMES)), '    SUPTAENTRY_GEN(g_abSUP$(certnm)),') \
     98        '};' 'unsigned const g_cSUP$(1)TAs = RT_ELEMENTS(g_aSUP$(1)TAs);' '' ''
     99else
     100 VBOX_SUP_GEN_CERT_MACRO = 'SUPTAENTRY const g_aSUP$(1)TAs[] =' '{' \
     101        $(foreach certnm,$(filter $(2),$(VBOX_SUP_WIN_CERT_NAMES)), '    SUPTAENTRY_GEN(g_abSUP$(certnm)),') \
     102        '};' 'unsigned const g_cSUP$(1)TAs = RT_ELEMENTS(g_aSUP$(1)TAs);' '' ''
     103endif
     104
     105$$(VBOX_SUP_WIN_CERTS_FILE): $(MAKEFILE_CURRENT) \
     106                $(foreach cert,$(VBOX_SUP_WIN_CERTS),$(VBOX_PATH_SUPR3_CERTIFICATES)/$(lastword $(subst =,$(SPACE) ,$(cert)))) \
     107                $(VBOX_BIN2C) \
     108                $(if-expr  "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_HARDENING),$(VBOX_RTSIGNTOOL)) \
     109                | $$(dir $$@)
     110        $(QUIET)$(RM) -f -- $@ [email protected]
     111        $(QUIET)$(APPEND) -n "$@" \
     112        '' \
     113        '#include <VBox/sup.h>' \
     114               ''
     115        $(foreach cert,$(VBOX_SUP_WIN_CERTS), $(NLTAB)$(VBOX_BIN2C) -ascii --append \
     116                "SUP$(firstword $(subst =,$(SP) ,$(cert)))" \
     117                "$(VBOX_PATH_SUPR3_CERTIFICATES)/$(lastword $(subst =,$(SP) ,$(cert)))" \
     118                "$@")
     119# The build certificate.
     120if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_HARDENING)
     121        $(VBOX_RTSIGNTOOL) extract-exe-signer-cert --exe $(VBOX_RTSIGNTOOL) --output "[email protected]" --der
     122        $(VBOX_BIN2C) -ascii --append SUPBuildCert "[email protected]" $@
     123        $(QUIET)$(RM) -f -- [email protected]
     124endif
     125# Generate certificate lists.
     126        $(QUIET)$(APPEND) -n "$@" '' \
     127               $(call VBOX_SUP_GEN_CERT_MACRO,All,%,build) \
     128               $(call VBOX_SUP_GEN_CERT_MACRO,SpcRoot,SpcRoot%) \
     129               $(call VBOX_SUP_GEN_CERT_MACRO,NtKernelRoot,NtRoot%) \
     130               $(call VBOX_SUP_GEN_CERT_MACRO,Timestamp,TimeRoot%) \
     131               $(call VBOX_SUP_GEN_CERT_MACRO,Trusted,TrustedCert%,build)
     132
     133tst: $(VBOX_SUP_WIN_CERTS_FILE)
     134
    72135
    73136#
    74137# The Ring-3 Support Library (this is linked into the IPRT dll, VBoxRT).
    75138#
    76 SUPR3_TEMPLATE     = VBOXR3NP
     139SUPR3_TEMPLATE      = VBOXR3NP
    77140SUPR3_DEFS          = \
    78141        IN_SUP_R3 IN_RT_R3 \
     
    88151        SUPR3HardenedIPRT.cpp \
    89152        SUPR3HardenedVerify.cpp \
    90         $(KBUILD_TARGET)/SUPLib-$(KBUILD_TARGET).cpp
     153        $(KBUILD_TARGET)/SUPLib-$(KBUILD_TARGET).cpp \
     154        $(VBOX_SUP_WIN_CERTS_FILE)
     155ifdef VBOX_WITH_HARDENING
     156 SUPR3_SOURCES.win  = \
     157        win/SUPHardenedVerifyImage-win.cpp
     158endif
    91159
    92160SUPR3-x86_TEMPLATE = VBoxR3Dll-x86
     
    95163
    96164#
    97 # Static version of SUPR3.
     165# Static version of SUPR3.  This is more of a stub than anything else in a
     166# hardened build, at least on windows.
    98167#
    99168SUPR3Static_TEMPLATE = VBOXR3STATIC
    100169SUPR3Static_EXTENDS = SUPR3
     170SUPR3Static_DEFS = $(SUPR3_DEFS) IN_SUP_R3_STATIC
     171SUPR3Static_SOURCES.win = $(filter-out win/SUPHardenedVerifyImage-win.cpp, $(SUPR3_SOURCES.win))
     172
    101173
    102174#
    103175# The static part of the hardened support library (ring-3).
    104176#
     177VBOX_PATH_RUNTIME_SRC ?= $(PATH_ROOT)/src/VBox/Runtime
    105178SUPR3HardenedStatic_TEMPLATE = VBOXR3HARDENEDLIB
    106179SUPR3HardenedStatic_DEFS     = IN_SUP_HARDENED_R3
     
    108181        $(if $(VBOX_WITH_SUPSVC),VBOX_WITH_SUPSVC,) \
    109182        $(if $(VBOX_WITH_MAIN),VBOX_WITH_MAIN,) \
    110         $(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,)
     183        $(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,) \
     184        $(if $(VBOX_WITHOUT_DEBUGGER_CHECKS),VBOX_WITHOUT_DEBUGGER_CHECKS,)
     185ifdef VBOX_WITH_VISTA_NO_SP
     186 SUPR3HardenedStatic_DEFS.win += VBOX_WITH_VISTA_NO_SP
     187endif
    111188SUPR3HardenedStatic_INCS     = .
    112189SUPR3HardenedStatic_SOURCES  = \
    113190        SUPR3HardenedMain.cpp \
    114191        SUPR3HardenedVerify.cpp \
     192        SUPR3HardenedNoCrt.cpp \
    115193        $(KBUILD_TARGET)/SUPLib-$(KBUILD_TARGET).cpp
     194SUPR3HardenedStatic_SOURCES.win = \
     195        win/SUPR3HardenedMain-win.cpp \
     196        win/SUPR3HardenedMainA-win.asm \
     197       win/SUPHardenedVerifyProcess-win.cpp \
     198       win/SUPHardenedVerifyImage-win.cpp \
     199        $(VBOX_SUP_WIN_CERTS_FILE)
     200
     201if1of ($(KBUILD_TARGET),win) ## @todo some of this move up.
     202 SUPR3HardenedStatic_SDKS += VBoxOpenSslHardened
     203 SUPR3HardenedStatic_DEFS += IN_RT IN_RT_R3 IN_RT_STATIC IPRT_NO_CRT RT_WITH_NOCRT_ALIASES LOG_DISABLED IPRT_NO_ERROR_DATA
     204 SUPR3HardenedStatic_DEFS.win += LDR_ONLY_PE __STRALIGN_H_
     205
     206 SUPR3HardenedStatic_INCS += $(PATH_ROOT)/include/iprt/nocrt  $(VBOX_PATH_RUNTIME_SRC)/include
     207
     208 SUPR3HardenedStatic_SOURCES += \
     209        $(VBOX_PATH_RUNTIME_SRC)/common/ldr/ldr.cpp \
     210        $(VBOX_PATH_RUNTIME_SRC)/common/ldr/ldrEx.cpp \
     211        $(VBOX_PATH_RUNTIME_SRC)/common/ldr/ldrPE.cpp \
     212        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-basics.cpp \
     213        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-cursor.cpp \
     214        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-default-allocator.cpp \
     215        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-dump.cpp \
     216        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-encode.cpp \
     217        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-bitstring.cpp \
     218        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-bitstring-decode.cpp \
     219        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-boolean.cpp \
     220        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-boolean-decode.cpp \
     221        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-core.cpp \
     222        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-core-decode.cpp \
     223        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-dyntype.cpp \
     224        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-dyntype-decode.cpp \
     225        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-integer.cpp \
     226        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-integer-decode.cpp \
     227        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-null.cpp \
     228        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-null-decode.cpp \
     229        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-objid.cpp \
     230        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-objid-decode.cpp \
     231        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-octetstring.cpp \
     232        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-octetstring-decode.cpp \
     233        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-string.cpp \
     234        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-string-decode.cpp \
     235        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-time.cpp \
     236        $(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-ut-time-decode.cpp \
     237        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/digest-core.cpp \
     238        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/digest-builtin.cpp \
     239        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-asn1-decoder.cpp \
     240        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-core.cpp \
     241        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-init.cpp \
     242        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-sanity.cpp \
     243        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-verify.cpp \
     244        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkix-signature-builtin.cpp \
     245        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkix-signature-core.cpp \
     246        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkix-signature-rsa.cpp \
     247        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkix-verify.cpp \
     248        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkix-util.cpp \
     249        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/rsa-asn1-decoder.cpp \
     250        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/rsa-core.cpp \
     251        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/rsa-init.cpp \
     252        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/rsa-sanity.cpp \
     253        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/spc-asn1-decoder.cpp \
     254        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/spc-core.cpp \
     255        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/spc-init.cpp \
     256        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/spc-sanity.cpp \
     257        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-asn1-decoder.cpp \
     258        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-certpaths.cpp \
     259        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-core.cpp \
     260        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-init.cpp \
     261        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-sanity.cpp \
     262        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/x509-verify.cpp \
     263        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/store.cpp \
     264        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/store-inmem.cpp \
     265        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-asn1-decoder.cpp \
     266        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-core.cpp \
     267        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-init.cpp \
     268        $(VBOX_PATH_RUNTIME_SRC)/common/crypto/taf-sanity.cpp \
     269        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/md2.cpp \
     270        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/md5.cpp \
     271        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha1.cpp \
     272        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha256.cpp \
     273        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha512.cpp \
     274        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/md2str.cpp \
     275        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/md5str.cpp \
     276        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha1str.cpp \
     277        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha256str.cpp \
     278        $(VBOX_PATH_RUNTIME_SRC)/common/checksum/sha512str.cpp \
     279        $(VBOX_PATH_RUNTIME_SRC)/common/err/errinfo.cpp \
     280        $(VBOX_PATH_RUNTIME_SRC)/common/path/RTPathChangeToUnixSlashes.cpp \
     281        $(VBOX_PATH_RUNTIME_SRC)/common/path/RTPathExt.cpp \
     282        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrPrintHexBytes.cpp \
     283        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16PrintHexBytes.cpp \
     284        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16ICmpAscii.cpp \
     285        $(VBOX_PATH_RUNTIME_SRC)/common/string/strstrip.cpp \
     286       \
     287        $(VBOX_PATH_RUNTIME_SRC)/common/err/errmsg.cpp \
     288        $(VBOX_PATH_RUNTIME_SRC)/common/math/bignum.cpp \
     289        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg1Weak.cpp \
     290        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2Weak.cpp \
     291        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2WeakV.cpp \
     292        $(VBOX_PATH_RUNTIME_SRC)/common/string/memchr.asm \
     293        $(VBOX_PATH_RUNTIME_SRC)/common/string/memcmp.asm \
     294        $(VBOX_PATH_RUNTIME_SRC)/common/string/memcpy.asm \
     295        $(VBOX_PATH_RUNTIME_SRC)/common/string/memmove.asm \
     296        $(VBOX_PATH_RUNTIME_SRC)/common/string/mempcpy.asm \
     297        $(VBOX_PATH_RUNTIME_SRC)/common/string/memset.asm \
     298        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrCat.cpp \
     299        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrCmp.cpp \
     300        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrCopy.cpp \
     301        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrNCmp.cpp \
     302        $(VBOX_PATH_RUNTIME_SRC)/common/string/RTStrNLen.cpp \
     303        $(VBOX_PATH_RUNTIME_SRC)/common/string/strchr.asm \
     304        $(VBOX_PATH_RUNTIME_SRC)/common/string/strcmp.asm \
     305        $(VBOX_PATH_RUNTIME_SRC)/common/string/strcpy.asm \
     306        $(VBOX_PATH_RUNTIME_SRC)/common/string/strformat.cpp \
     307        $(VBOX_PATH_RUNTIME_SRC)/common/string/strformatrt.cpp \
     308        $(VBOX_PATH_RUNTIME_SRC)/common/string/strformattype.cpp \
     309        $(VBOX_PATH_RUNTIME_SRC)/common/string/stringalloc.cpp \
     310        $(VBOX_PATH_RUNTIME_SRC)/common/string/strlen.asm \
     311        $(VBOX_PATH_RUNTIME_SRC)/common/string/strncmp.asm \
     312        $(VBOX_PATH_RUNTIME_SRC)/common/string/strncpy.asm \
     313        $(VBOX_PATH_RUNTIME_SRC)/common/string/strprintf.cpp \
     314        $(VBOX_PATH_RUNTIME_SRC)/common/string/strtonum.cpp \
     315        $(VBOX_PATH_RUNTIME_SRC)/common/string/utf-16.cpp \
     316        $(VBOX_PATH_RUNTIME_SRC)/common/string/utf-8.cpp \
     317        $(VBOX_PATH_RUNTIME_SRC)/common/string/utf-8-case.cpp \
     318        $(VBOX_PATH_RUNTIME_SRC)/common/string/unidata-upper.cpp \
     319        $(VBOX_PATH_RUNTIME_SRC)/common/string/unidata-lower.cpp \
     320        $(VBOX_PATH_RUNTIME_SRC)/common/time/time.cpp \
     321        $(VBOX_PATH_RUNTIME_SRC)/generic/RTAssertShouldPanic-generic.cpp \
     322        $(VBOX_PATH_RUNTIME_SRC)/generic/memsafer-generic.cpp \
     323        $(VBOX_PATH_RUNTIME_SRC)/generic/uuid-generic.cpp \
     324
     325
     326 SUPR3HardenedStatic_SOURCES.win += \
     327        win/SUPR3HardenedNoCrt-win.cpp \
     328        $(VBOX_PATH_RUNTIME_SRC)/nt/RTErrConvertFromNtStatus.cpp \
     329        $(VBOX_PATH_RUNTIME_SRC)/win/RTErrConvertFromWin32.cpp \
     330        $(VBOX_PATH_RUNTIME_SRC)/win/errmsgwin.cpp
     331
     332 # Add necessary compiler specific files from libcmt.lib and the lib dir.
     333 ifeq ($(KBUILD_TARGET),win)
     334   SUPR3HardenedStatic_VBOX_LIBC_OBJS = chkstk.obj
     335   ifeq ($(KBUILD_TARGET_ARCH),x86)
     336    SUPR3HardenedStatic_VBOX_LIBC_OBJS += alloca16.obj
     337   endif
     338  SUPR3HardenedStatic_SOURCES.win += $(addprefix $(SUPR3HardenedStatic_0_OUTDIR)/,$(SUPR3HardenedStatic_VBOX_LIBC_OBJS))
     339
     340  $(addprefix $$(SUPR3HardenedStatic_0_OUTDIR)/,$(SUPR3HardenedStatic_VBOX_LIBC_OBJS)): \
     341                $$(PATH_TOOL_$(TEMPLATE_VBOXR3EXE_TOOL.win.$(KBUILD_TARGET_ARCH))_LIB)/libcmt.lib | $$(dir $$@)
     342        $(TOOL_$(TEMPLATE_VBOXR3HARDENEDEXE_TOOL.win.$(KBUILD_TARGET_ARCH))_AR) "$<" \
     343                /EXTRACT:`$(TOOL_$(TEMPLATE_VBOXR3HARDENEDEXE_TOOL.win.$(KBUILD_TARGET_ARCH))_AR) "$<" /LIST \
     344                          | $(SED_EXT) -n -e '/$(notdir $@)/p'` \
     345                "/OUT:$@"
     346 endif
     347endif
     348
     349
     350#
     351# VBoxSupLib - Windows DLL for catching thread creation and termination.
     352#
     353VBoxSupLib_TEMPLATE = $(if "$(KBUILD_TARGET)" == "win",VBOXR3HARDENEDLIB,VBOXR3)
     354VBoxSupLib_LDFLAGS.win.amd64 = -Entry:DllMainEntrypoint
     355VBoxSupLib_LDFLAGS.win.x86   = -Entry:DllMainEntrypoint
     356VBoxSupLib_DEFS = \
     357        $(if $(VBOX_WITHOUT_DEBUGGER_CHECKS),VBOX_WITHOUT_DEBUGGER_CHECKS,)
     358VBoxSupLib_SOURCES = \
     359        $(KBUILD_TARGET)/VBoxSupLib-$(KBUILD_TARGET).cpp
     360VBoxSupLib_LIBS.win = \
     361        $(SUPR3HardenedStatic_1_INS_TARGET)
     362
    116363
    117364#
     
    263510 VBoxDrv_DEBUG_INST.darwin= $(patsubst %/,%,$(INST_VBOXDRV))
    264511 VBoxDrv_SDKS.win         = ReorderCompilerIncs $(VBOX_WINDDK) $(VBOX_WINPSDK)INCS
     512 ifdef VBOX_WITH_HARDENING
     513  VBoxDrv_SDKS.win       += VBoxOpenSslHardened
     514 endif
    265515
    266516 VBoxDrv_DEFS            := IN_RT_R0 IN_SUP_R0 SUPDRV_WITH_RELEASE_LOGGER VBOX_SVN_REV=$(VBOX_SVN_REV)
    267517 ifdef VBOX_WITH_DTRACE_R0DRV
    268518  VBoxDrv_DEFS           += VBOX_WITH_DTRACE VBOX_WITH_DTRACE_R0DRV
     519 endif
     520 ifdef VBOX_WITHOUT_DEBUGGER_CHECKS
     521  VBoxDrv_DEFS           += VBOX_WITHOUT_DEBUGGER_CHECKS
    269522 endif
    270523 #VBoxDrv_DEFS.debug      += DEBUG_DARWIN_GIP
     
    284537  VBoxDrv_DEFS.win       += VBOX_WITHOUT_NATIVE_R0_LOADER
    285538 endif
     539 ifdef VBOX_WITH_VISTA_NO_SP
     540  VBoxDrv_DEFS.win       += VBOX_WITH_VISTA_NO_SP
     541 endif
    286542
    287543 VBoxDrv_INCS             = . $(VBoxDrv_0_OUTDIR)
     
    292548 VBoxDrv_LIBS.linux.debug = $(VBoxDrv_LIBS) $(VBOX_GCC_LIBGCC)
    293549 VBoxDrv_LIBS.win         = \
     550        $(PATH_STAGE_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB) \
    294551        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/ntoskrnl.lib \
    295         $(PATH_SDK_$(VBOX_WINDDK)_LIB)/hal.lib \
    296         $(PATH_STAGE_LIB)/RuntimeR0Drv$(VBOX_SUFF_LIB)
     552        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/hal.lib
    297553
    298554 #VBoxDrv_LDFLAGS.darwin    = -v -Wl,-whyload -Wl,-v -Wl,-whatsloaded
     
    314570        win/SUPDrvA-win.asm \
    315571        win/VBoxDrv.rc
     572 ifdef VBOX_WITH_HARDENING
     573  VBoxDrv_SOURCES.win    += \
     574        win/SUPHardenedVerifyImage-win.cpp \
     575        win/SUPHardenedVerifyProcess-win.cpp \
     576        $(VBOX_SUP_WIN_CERTS_FILE)
     577 endif
    316578 VBoxDrv_SOURCES          = \
    317579        SUPDrv.d \
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r51718 r51770  
    464464     * Initialize it.
    465465     */
    466     memset(pDevExt, 0, sizeof(*pDevExt));
     466    memset(pDevExt, 0, sizeof(*pDevExt)); /* Does not wipe OS specific tail section of the structure. */
     467    pDevExt->Spinlock = NIL_RTSPINLOCK;
     468    pDevExt->hGipSpinlock = NIL_RTSPINLOCK;
     469    pDevExt->hSessionHashTabSpinlock = NIL_RTSPINLOCK;
    467470    rc = RTSpinlockCreate(&pDevExt->Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "SUPDrvDevExt");
    468471    if (RT_SUCCESS(rc))
    469     {
    470472        rc = RTSpinlockCreate(&pDevExt->hGipSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "SUPDrvGip");
     473    if (RT_SUCCESS(rc))
     474        rc = RTSpinlockCreate(&pDevExt->hSessionHashTabSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "SUPDrvSession");
     475
     476    if (RT_SUCCESS(rc))
     477#ifdef SUPDRV_USE_MUTEX_FOR_LDR
     478        rc = RTSemMutexCreate(&pDevExt->mtxLdr);
     479#else
     480        rc = RTSemFastMutexCreate(&pDevExt->mtxLdr);
     481#endif
     482    if (RT_SUCCESS(rc))
     483    {
     484        rc = RTSemFastMutexCreate(&pDevExt->mtxComponentFactory);
    471485        if (RT_SUCCESS(rc))
    472486        {
    473487#ifdef SUPDRV_USE_MUTEX_FOR_LDR
    474             rc = RTSemMutexCreate(&pDevExt->mtxLdr);
     488            rc = RTSemMutexCreate(&pDevExt->mtxGip);
    475489#else
    476             rc = RTSemFastMutexCreate(&pDevExt->mtxLdr);
     490            rc = RTSemFastMutexCreate(&pDevExt->mtxGip);
    477491#endif
    478492            if (RT_SUCCESS(rc))
    479493            {
    480                 rc = RTSemFastMutexCreate(&pDevExt->mtxComponentFactory);
     494                rc = supdrvGipCreate(pDevExt);
    481495                if (RT_SUCCESS(rc))
    482496                {
    483 #ifdef SUPDRV_USE_MUTEX_FOR_LDR
    484                     rc = RTSemMutexCreate(&pDevExt->mtxGip);
    485 #else
    486                     rc = RTSemFastMutexCreate(&pDevExt->mtxGip);
    487 #endif
     497                    rc = supdrvTracerInit(pDevExt);
    488498                    if (RT_SUCCESS(rc))
    489499                    {
    490                         rc = supdrvGipCreate(pDevExt);
    491                         if (RT_SUCCESS(rc))
    492                         {
    493                             rc = supdrvTracerInit(pDevExt);
    494                             if (RT_SUCCESS(rc))
    495                             {
    496                                 pDevExt->pLdrInitImage  = NULL;
    497                                 pDevExt->hLdrInitThread = NIL_RTNATIVETHREAD;
    498                                 pDevExt->u32Cookie      = BIRD;  /** @todo make this random? */
    499                                 pDevExt->cbSession      = (uint32_t)cbSession;
    500 
    501                                 /*
    502                                  * Fixup the absolute symbols.
    503                                  *
    504                                  * Because of the table indexing assumptions we'll have a little #ifdef orgy
    505                                  * here rather than distributing this to OS specific files. At least for now.
    506                                  */
     500                        pDevExt->pLdrInitImage  = NULL;
     501                        pDevExt->hLdrInitThread = NIL_RTNATIVETHREAD;
     502                        pDevExt->u32Cookie      = BIRD;  /** @todo make this random? */
     503                        pDevExt->cbSession      = (uint32_t)cbSession;
     504
     505                        /*
     506                         * Fixup the absolute symbols.
     507                         *
     508                         * Because of the table indexing assumptions we'll have a little #ifdef orgy
     509                         * here rather than distributing this to OS specific files. At least for now.
     510                         */
    507511#ifdef RT_OS_DARWIN
    508512# if ARCH_BITS == 32
    509                                 if (SUPR0GetPagingMode() >= SUPPAGINGMODE_AMD64)
    510                                 {
    511                                     g_aFunctions[0].pfn = (void *)1;                    /* SUPR0AbsIs64bit */
    512                                     g_aFunctions[1].pfn = (void *)0x80;                 /* SUPR0Abs64bitKernelCS - KERNEL64_CS, seg.h */
    513                                     g_aFunctions[2].pfn = (void *)0x88;                 /* SUPR0Abs64bitKernelSS - KERNEL64_SS, seg.h */
    514                                     g_aFunctions[3].pfn = (void *)0x88;                 /* SUPR0Abs64bitKernelDS - KERNEL64_SS, seg.h */
    515                                 }
    516                                 else
    517                                     g_aFunctions[0].pfn = g_aFunctions[1].pfn = g_aFunctions[2].pfn = g_aFunctions[4].pfn = (void *)0;
    518                                 g_aFunctions[4].pfn = (void *)0x08;                     /* SUPR0AbsKernelCS - KERNEL_CS, seg.h */
    519                                 g_aFunctions[5].pfn = (void *)0x10;                     /* SUPR0AbsKernelSS - KERNEL_DS, seg.h */
    520                                 g_aFunctions[6].pfn = (void *)0x10;                     /* SUPR0AbsKernelDS - KERNEL_DS, seg.h */
    521                                 g_aFunctions[7].pfn = (void *)0x10;                     /* SUPR0AbsKernelES - KERNEL_DS, seg.h */
    522                                 g_aFunctions[8].pfn = (void *)0x10;                     /* SUPR0AbsKernelFS - KERNEL_DS, seg.h */
    523                                 g_aFunctions[9].pfn = (void *)0x48;                     /* SUPR0AbsKernelGS - CPU_DATA_GS, seg.h */
     513                        if (SUPR0GetPagingMode() >= SUPPAGINGMODE_AMD64)
     514                        {
     515                            g_aFunctions[0].pfn = (void *)1;                    /* SUPR0AbsIs64bit */
     516                            g_aFunctions[1].pfn = (void *)0x80;                 /* SUPR0Abs64bitKernelCS - KERNEL64_CS, seg.h */
     517                            g_aFunctions[2].pfn = (void *)0x88;                 /* SUPR0Abs64bitKernelSS - KERNEL64_SS, seg.h */
     518                            g_aFunctions[3].pfn = (void *)0x88;                 /* SUPR0Abs64bitKernelDS - KERNEL64_SS, seg.h */
     519                        }
     520                        else
     521                            g_aFunctions[0].pfn = g_aFunctions[1].pfn = g_aFunctions[2].pfn = g_aFunctions[4].pfn = (void *)0;
     522                        g_aFunctions[4].pfn = (void *)0x08;                     /* SUPR0AbsKernelCS - KERNEL_CS, seg.h */
     523                        g_aFunctions[5].pfn = (void *)0x10;                     /* SUPR0AbsKernelSS - KERNEL_DS, seg.h */
     524                        g_aFunctions[6].pfn = (void *)0x10;                     /* SUPR0AbsKernelDS - KERNEL_DS, seg.h */
     525                        g_aFunctions[7].pfn = (void *)0x10;                     /* SUPR0AbsKernelES - KERNEL_DS, seg.h */
     526                        g_aFunctions[8].pfn = (void *)0x10;                     /* SUPR0AbsKernelFS - KERNEL_DS, seg.h */
     527                        g_aFunctions[9].pfn = (void *)0x48;                     /* SUPR0AbsKernelGS - CPU_DATA_GS, seg.h */
    524528# else /* 64-bit darwin: */
    525                                 g_aFunctions[0].pfn = (void *)1;                        /* SUPR0AbsIs64bit */
    526                                 g_aFunctions[1].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0Abs64bitKernelCS */
    527                                 g_aFunctions[2].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0Abs64bitKernelSS */
    528                                 g_aFunctions[3].pfn = (void *)0;                        /* SUPR0Abs64bitKernelDS */
    529                                 g_aFunctions[4].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0AbsKernelCS */
    530                                 g_aFunctions[5].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0AbsKernelSS */
    531                                 g_aFunctions[6].pfn = (void *)0;                        /* SUPR0AbsKernelDS */
    532                                 g_aFunctions[7].pfn = (void *)0;                        /* SUPR0AbsKernelES */
    533                                 g_aFunctions[8].pfn = (void *)0;                        /* SUPR0AbsKernelFS */
    534                                 g_aFunctions[9].pfn = (void *)0;                        /* SUPR0AbsKernelGS */
     529                        g_aFunctions[0].pfn = (void *)1;                        /* SUPR0AbsIs64bit */
     530                        g_aFunctions[1].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0Abs64bitKernelCS */
     531                        g_aFunctions[2].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0Abs64bitKernelSS */
     532                        g_aFunctions[3].pfn = (void *)0;                        /* SUPR0Abs64bitKernelDS */
     533                        g_aFunctions[4].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0AbsKernelCS */
     534                        g_aFunctions[5].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0AbsKernelSS */
     535                        g_aFunctions[6].pfn = (void *)0;                        /* SUPR0AbsKernelDS */
     536                        g_aFunctions[7].pfn = (void *)0;                        /* SUPR0AbsKernelES */
     537                        g_aFunctions[8].pfn = (void *)0;                        /* SUPR0AbsKernelFS */
     538                        g_aFunctions[9].pfn = (void *)0;                        /* SUPR0AbsKernelGS */
    535539
    536540# endif
    537541#else  /* !RT_OS_DARWIN */
    538542# if ARCH_BITS == 64
    539                                 g_aFunctions[0].pfn = (void *)1;                        /* SUPR0AbsIs64bit */
    540                                 g_aFunctions[1].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0Abs64bitKernelCS */
    541                                 g_aFunctions[2].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0Abs64bitKernelSS */
    542                                 g_aFunctions[3].pfn = (void *)(uintptr_t)ASMGetDS();    /* SUPR0Abs64bitKernelDS */
     543                        g_aFunctions[0].pfn = (void *)1;                        /* SUPR0AbsIs64bit */
     544                        g_aFunctions[1].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0Abs64bitKernelCS */
     545                        g_aFunctions[2].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0Abs64bitKernelSS */
     546                        g_aFunctions[3].pfn = (void *)(uintptr_t)ASMGetDS();    /* SUPR0Abs64bitKernelDS */
    543547# else
    544                                 g_aFunctions[0].pfn = g_aFunctions[1].pfn = g_aFunctions[2].pfn = g_aFunctions[4].pfn = (void *)0;
     548                        g_aFunctions[0].pfn = g_aFunctions[1].pfn = g_aFunctions[2].pfn = g_aFunctions[4].pfn = (void *)0;
    545549# endif
    546                                 g_aFunctions[4].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0AbsKernelCS */
    547                                 g_aFunctions[5].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0AbsKernelSS */
    548                                 g_aFunctions[6].pfn = (void *)(uintptr_t)ASMGetDS();    /* SUPR0AbsKernelDS */
    549                                 g_aFunctions[7].pfn = (void *)(uintptr_t)ASMGetES();    /* SUPR0AbsKernelES */
    550                                 g_aFunctions[8].pfn = (void *)(uintptr_t)ASMGetFS();    /* SUPR0AbsKernelFS */
    551                                 g_aFunctions[9].pfn = (void *)(uintptr_t)ASMGetGS();    /* SUPR0AbsKernelGS */
     550                        g_aFunctions[4].pfn = (void *)(uintptr_t)ASMGetCS();    /* SUPR0AbsKernelCS */
     551                        g_aFunctions[5].pfn = (void *)(uintptr_t)ASMGetSS();    /* SUPR0AbsKernelSS */
     552                        g_aFunctions[6].pfn = (void *)(uintptr_t)ASMGetDS();    /* SUPR0AbsKernelDS */
     553                        g_aFunctions[7].pfn = (void *)(uintptr_t)ASMGetES();    /* SUPR0AbsKernelES */
     554                        g_aFunctions[8].pfn = (void *)(uintptr_t)ASMGetFS();    /* SUPR0AbsKernelFS */
     555                        g_aFunctions[9].pfn = (void *)(uintptr_t)ASMGetGS();    /* SUPR0AbsKernelGS */
    552556#endif /* !RT_OS_DARWIN */
    553                                 return VINF_SUCCESS;
    554                             }
    555 
    556                             supdrvGipDestroy(pDevExt);
    557                         }
     557                        return VINF_SUCCESS;
     558                    }
     559
     560                    supdrvGipDestroy(pDevExt);
     561                }
    558562
    559563#ifdef SUPDRV_USE_MUTEX_FOR_GIP
    560                         RTSemMutexDestroy(pDevExt->mtxGip);
    561                         pDevExt->mtxGip = NIL_RTSEMMUTEX;
     564                RTSemMutexDestroy(pDevExt->mtxGip);
     565                pDevExt->mtxGip = NIL_RTSEMMUTEX;
    562566#else
    563                         RTSemFastMutexDestroy(pDevExt->mtxGip);
    564                         pDevExt->mtxGip = NIL_RTSEMFASTMUTEX;
    565 #endif
    566                     }
    567                     RTSemFastMutexDestroy(pDevExt->mtxComponentFactory);
    568                     pDevExt->mtxComponentFactory = NIL_RTSEMFASTMUTEX;
    569                 }
    570 #ifdef SUPDRV_USE_MUTEX_FOR_LDR
    571                 RTSemMutexDestroy(pDevExt->mtxLdr);
    572                 pDevExt->mtxLdr = NIL_RTSEMMUTEX;
    573 #else
    574                 RTSemFastMutexDestroy(pDevExt->mtxLdr);
    575                 pDevExt->mtxLdr = NIL_RTSEMFASTMUTEX;
     567                RTSemFastMutexDestroy(pDevExt->mtxGip);
     568                pDevExt->mtxGip = NIL_RTSEMFASTMUTEX;
    576569#endif
    577570            }
    578             RTSpinlockDestroy(pDevExt->hGipSpinlock);
    579             pDevExt->hGipSpinlock = NIL_RTSPINLOCK;
    580         }
    581         RTSpinlockDestroy(pDevExt->Spinlock);
    582         pDevExt->Spinlock = NIL_RTSPINLOCK;
    583     }
     571            RTSemFastMutexDestroy(pDevExt->mtxComponentFactory);
     572            pDevExt->mtxComponentFactory = NIL_RTSEMFASTMUTEX;
     573        }
     574#ifdef SUPDRV_USE_MUTEX_FOR_LDR
     575        RTSemMutexDestroy(pDevExt->mtxLdr);
     576        pDevExt->mtxLdr = NIL_RTSEMMUTEX;
     577#else
     578        RTSemFastMutexDestroy(pDevExt->mtxLdr);
     579        pDevExt->mtxLdr = NIL_RTSEMFASTMUTEX;
     580#endif
     581    }
     582
     583    RTSpinlockDestroy(pDevExt->Spinlock);
     584    pDevExt->Spinlock = NIL_RTSPINLOCK;
     585    RTSpinlockDestroy(pDevExt->hGipSpinlock);
     586    pDevExt->hGipSpinlock = NIL_RTSPINLOCK;
     587    RTSpinlockDestroy(pDevExt->hSessionHashTabSpinlock);
     588    pDevExt->hSessionHashTabSpinlock = NIL_RTSPINLOCK;
     589
    584590#ifdef SUPDRV_WITH_RELEASE_LOGGER
    585591    RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
     
    622628    RTSemFastMutexDestroy(pDevExt->mtxComponentFactory);
    623629    pDevExt->mtxComponentFactory = NIL_RTSEMFASTMUTEX;
     630    RTSpinlockDestroy(pDevExt->hSessionHashTabSpinlock);
     631    pDevExt->hSessionHashTabSpinlock = NIL_RTSPINLOCK;
    624632
    625633    /*
     
    700708                pSession->u32Cookie         = BIRD_INV;
    701709                pSession->fUnrestricted     = fUnrestricted;
     710                /*pSession->fInHashTable      = false; */
    702711                pSession->cRefs             = 1;
    703                 /*pSession->pLdrUsage         = NULL;
    704                 pSession->pVM               = NULL;
    705                 pSession->pUsage            = NULL;
    706                 pSession->pGip              = NULL;
    707                 pSession->fGipReferenced    = false;
    708                 pSession->Bundle.cUsed      = 0; */
    709                 pSession->Uid               = NIL_RTUID;
    710                 pSession->Gid               = NIL_RTGID;
     712                /*pSession->pCommonNextHash   = NULL;
     713                pSession->ppOsSessionPtr    = NULL; */
    711714                if (fUser)
    712715                {
     
    719722                    pSession->R0Process     = NIL_RTR0PROCESS;
    720723                }
     724                /*pSession->pLdrUsage         = NULL;
     725                pSession->pVM               = NULL;
     726                pSession->pUsage            = NULL;
     727                pSession->pGip              = NULL;
     728                pSession->fGipReferenced    = false;
     729                pSession->Bundle.cUsed      = 0; */
     730                pSession->Uid               = NIL_RTUID;
     731                pSession->Gid               = NIL_RTGID;
    721732                /*pSession->uTracerData       = 0;*/
    722733                pSession->hTracerCaller     = NIL_RTNATIVETHREAD;
     
    746757
    747758/**
    748  * Shared code for cleaning up a session (but not quite freeing it).
    749  *
    750  * This is primarily intended for MAC OS X where we have to clean up the memory
    751  * stuff before the file handle is closed.
    752  *
    753  * @param   pDevExt     Device extension.
     759 * Cleans up the session in the context of the process to which it belongs, the
     760 * caller will free the session and the session spinlock.
     761 *
     762 * This should normally occur when the session is closed or as the process
     763 * exits.  Careful reference counting in the OS specfic code makes sure that
     764 * there cannot be any races between process/handle cleanup callbacks and
     765 * threads doing I/O control calls.
     766 *
     767 * @param   pDevExt     The device extension.
    754768 * @param   pSession    Session data.
    755  *                      This data will be freed by this routine.
    756769 */
    757770static void supdrvCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     
    760773    PSUPDRVBUNDLE       pBundle;
    761774    LogFlow(("supdrvCleanupSession: pSession=%p\n", pSession));
     775
     776    Assert(!pSession->fInHashTable);
     777    Assert(!pSession->ppOsSessionPtr);
     778    AssertReleaseMsg(pSession->R0Process == RTR0ProcHandleSelf() || pSession->R0Process == NIL_RTR0PROCESS,
     779                     ("R0Process=%p cur=%p; Process=%u curpid=%u\n", RTR0ProcHandleSelf(), RTProcSelf()));
    762780
    763781    /*
     
    964982
    965983/**
    966  * Shared code for cleaning up a session.
     984 * Common code for freeing a session when the reference count reaches zero.
    967985 *
    968986 * @param   pDevExt     Device extension.
     
    970988 *                      This data will be freed by this routine.
    971989 */
    972 static void supdrvCloseSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     990static void supdrvDestroySession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
    973991{
    974992    VBOXDRV_SESSION_CLOSE(pSession);
     
    978996     */
    979997    supdrvCleanupSession(pDevExt, pSession);
     998    supdrvOSCleanupSession(pDevExt, pSession);
    980999
    9811000    /*
     
    9861005    pSession->pDevExt = NULL;
    9871006    RTMemFree(pSession);
    988     LogFlow(("supdrvCloseSession: returns\n"));
     1007    LogFlow(("supdrvDestroySession: returns\n"));
     1008}
     1009
     1010
     1011/**
     1012 * Inserts the session into the global hash table.
     1013 *
     1014 * @retval  VINF_SUCCESS on success.
     1015 * @retval  VERR_WRONG_ORDER if the session was already inserted (asserted).
     1016 * @retval  VERR_INVALID_PARAMETER if the session handle is invalid or a ring-0
     1017 *          session (asserted).
     1018 * @retval  VERR_DUPLICATE if there is already a session for that pid.
     1019 *
     1020 * @param   pDevExt         The device extension.
     1021 * @param   pSession        The session.
     1022 * @param   ppOsSessionPtr  Pointer to the OS session pointer, if any is
     1023 *                          available and used.  This will set to point to the
     1024 *                          session while under the protection of the session
     1025 *                          hash table spinlock.  It will also be kept in
     1026 *                          PSUPDRVSESSION::ppOsSessionPtr for lookup and
     1027 *                          cleanup use.
     1028 * @param   pvUser          Argument for supdrvOSSessionHashTabInserted.
     1029 */
     1030int VBOXCALL supdrvSessionHashTabInsert(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVSESSION *ppOsSessionPtr,
     1031                                        void *pvUser)
     1032{
     1033    PSUPDRVSESSION  pCur;
     1034    unsigned        iHash;
     1035
     1036    /*
     1037     * Validate input.
     1038     */
     1039    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
     1040    AssertReturn(pSession->R0Process != NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
     1041
     1042    /*
     1043     * Calculate the hash table index and acquire the spinlock.
     1044     */
     1045    iHash = SUPDRV_SESSION_HASH(pSession->Process);
     1046
     1047    RTSpinlockAcquire(pDevExt->hSessionHashTabSpinlock);
     1048
     1049    /*
     1050     * If there are a collisions, we need to carefully check if we got a
     1051     * duplicate.  There can only be one open session per process.
     1052     */
     1053    pCur = pDevExt->apSessionHashTab[iHash];
     1054    if (pCur)
     1055    {
     1056        while (pCur && pCur->Process != pSession->Process)
     1057            pCur = pCur->pCommonNextHash;
     1058
     1059        if (pCur)
     1060        {
     1061            RTSpinlockRelease(pDevExt->hSessionHashTabSpinlock);
     1062            if (pCur == pSession)
     1063            {
     1064                Assert(pSession->fInHashTable);
     1065                AssertFailed();
     1066                return VERR_WRONG_ORDER;
     1067            }
     1068            Assert(!pSession->fInHashTable);
     1069            if (pCur->R0Process == pSession->R0Process)
     1070                return VERR_RESOURCE_IN_USE;
     1071            return VERR_DUPLICATE;
     1072        }
     1073    }
     1074    Assert(!pSession->fInHashTable);
     1075    Assert(!pSession->ppOsSessionPtr);
     1076
     1077    /*
     1078     * Insert it, doing a callout to the OS specific code in case it has
     1079     * anything it wishes to do while we're holding the spinlock.
     1080     */
     1081    pSession->pCommonNextHash = pDevExt->apSessionHashTab[iHash];
     1082    pDevExt->apSessionHashTab[iHash] = pSession;
     1083    pSession->fInHashTable    = true;
     1084    ASMAtomicIncS32(&pDevExt->cSessions);
     1085
     1086    pSession->ppOsSessionPtr = ppOsSessionPtr;
     1087    if (ppOsSessionPtr)
     1088        ASMAtomicWritePtr(ppOsSessionPtr, pSession);
     1089
     1090    supdrvOSSessionHashTabInserted(pDevExt, pSession, pvUser);
     1091
     1092    /*
     1093     * Retain a reference for the pointer in the session table.
     1094     */
     1095    ASMAtomicIncU32(&pSession->cRefs);
     1096
     1097    RTSpinlockRelease(pDevExt->hSessionHashTabSpinlock);
     1098    return VINF_SUCCESS;
     1099}
     1100
     1101
     1102/**
     1103 * Removes the session from the global hash table.
     1104 *
     1105 * @retval  VINF_SUCCESS on success.
     1106 * @retval  VERR_NOT_FOUND if the session was already removed (asserted).
     1107 * @retval  VERR_INVALID_PARAMETER if the session handle is invalid or a ring-0
     1108 *          session (asserted).
     1109 *
     1110 * @param   pDevExt     The device extension.
     1111 * @param   pSession    The session. The caller is expected to have a reference
     1112 *                      to this so it won't croak on us when we release the hash
     1113 *                      table reference.
     1114 * @param   pvUser      OS specific context value for the
     1115 *                      supdrvOSSessionHashTabInserted callback.
     1116 */
     1117int VBOXCALL supdrvSessionHashTabRemove(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     1118{
     1119    PSUPDRVSESSION  pCur;
     1120    unsigned        iHash;
     1121    int32_t         cRefs;
     1122
     1123    /*
     1124     * Validate input.
     1125     */
     1126    AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER);
     1127    AssertReturn(pSession->R0Process != NIL_RTR0PROCESS, VERR_INVALID_PARAMETER);
     1128
     1129    /*
     1130     * Calculate the hash table index and acquire the spinlock.
     1131     */
     1132    iHash = SUPDRV_SESSION_HASH(pSession->Process);
     1133
     1134    RTSpinlockAcquire(pDevExt->hSessionHashTabSpinlock);
     1135
     1136    /*
     1137     * Unlink it.
     1138     */
     1139    pCur = pDevExt->apSessionHashTab[iHash];
     1140    if (pCur == pSession)
     1141        pDevExt->apSessionHashTab[iHash] = pSession->pCommonNextHash;
     1142    else
     1143    {
     1144        PSUPDRVSESSION pPrev = pCur;
     1145        while (pCur && pCur != pSession)
     1146        {
     1147            pPrev = pCur;
     1148            pCur  = pCur->pCommonNextHash;
     1149        }
     1150        if (pCur)
     1151            pPrev->pCommonNextHash = pCur->pCommonNextHash;
     1152        else
     1153        {
     1154            Assert(!pSession->fInHashTable);
     1155            RTSpinlockRelease(pDevExt->hSessionHashTabSpinlock);
     1156            return VERR_NOT_FOUND;
     1157        }
     1158    }
     1159
     1160    pSession->pCommonNextHash = NULL;
     1161    pSession->fInHashTable    = false;
     1162
     1163    ASMAtomicDecU32(&pDevExt->cSessions);
     1164
     1165    /*
     1166     * Clear OS specific session pointer if available and do the OS callback.
     1167     */
     1168    if (pSession->ppOsSessionPtr)
     1169    {
     1170        ASMAtomicCmpXchgPtr(pSession->ppOsSessionPtr, NULL, pSession);
     1171        pSession->ppOsSessionPtr = NULL;
     1172    }
     1173
     1174    supdrvOSSessionHashTabRemoved(pDevExt, pSession, pvUser);
     1175
     1176    RTSpinlockRelease(pDevExt->hSessionHashTabSpinlock);
     1177
     1178    /*
     1179     * Drop the reference the hash table had to the session.  This shouldn't
     1180     * be the last reference!
     1181     */
     1182    cRefs = ASMAtomicDecU32(&pSession->cRefs);
     1183    Assert(cRefs > 0 && cRefs < _1M);
     1184    if (cRefs == 0)
     1185        supdrvDestroySession(pDevExt, pSession);
     1186
     1187    return VINF_SUCCESS;
     1188}
     1189
     1190
     1191/**
     1192 * Looks up the session for the current process in the global hash table or in
     1193 * OS specific pointer.
     1194 *
     1195 * @returns Pointer to the session with a reference that the caller must
     1196 *          release.  If no valid session was found, NULL is returned.
     1197 *
     1198 * @param   pDevExt         The device extension.
     1199 * @param   Process         The process ID.
     1200 * @param   R0Process       The ring-0 process handle.
     1201 * @param   ppOsSessionPtr  The OS session pointer if available.  If not NULL,
     1202 *                          this is used instead of the hash table.  For
     1203 *                          additional safety it must then be equal to the
     1204 *                          SUPDRVSESSION::ppOsSessionPtr member.
     1205 *                          This can be NULL even if the OS has a session
     1206 *                          pointer.
     1207 */
     1208PSUPDRVSESSION VBOXCALL supdrvSessionHashTabLookup(PSUPDRVDEVEXT pDevExt, RTPROCESS Process, RTR0PROCESS R0Process,
     1209                                                   PSUPDRVSESSION *ppOsSessionPtr)
     1210{
     1211    PSUPDRVSESSION  pCur;
     1212    unsigned        iHash;
     1213
     1214    /*
     1215     * Validate input.
     1216     */
     1217    AssertReturn(R0Process != NIL_RTR0PROCESS, NULL);
     1218
     1219    /*
     1220     * Calculate the hash table index and acquire the spinlock.
     1221     */
     1222    iHash = SUPDRV_SESSION_HASH(Process);
     1223
     1224    RTSpinlockAcquire(pDevExt->hSessionHashTabSpinlock);
     1225
     1226    /*
     1227     * If an OS session pointer is provided, always use it.
     1228     */
     1229    if (ppOsSessionPtr)
     1230    {
     1231        pCur = *ppOsSessionPtr;
     1232        if (   pCur
     1233            && (   pCur->ppOsSessionPtr != ppOsSessionPtr
     1234                || pCur->Process        != Process
     1235                || pCur->R0Process      != R0Process) )
     1236            pCur = NULL;
     1237    }
     1238    else
     1239    {
     1240        /*
     1241         * Otherwise, do the hash table lookup.
     1242         */
     1243        pCur = pDevExt->apSessionHashTab[iHash];
     1244        while (   pCur
     1245               && (   pCur->Process   != Process
     1246                   || pCur->R0Process != R0Process) )
     1247            pCur = pCur->pCommonNextHash;
     1248    }
     1249
     1250    /*
     1251     * Retain the session.
     1252     */
     1253    if (pCur)
     1254    {
     1255        uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
     1256        Assert(cRefs > 1 && cRefs < _1M);
     1257    }
     1258
     1259    RTSpinlockRelease(pDevExt->hSessionHashTabSpinlock);
     1260
     1261    return pCur;
    9891262}
    9901263
     
    10231296    AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pSession));
    10241297    if (cRefs == 0)
    1025         supdrvCloseSession(pSession->pDevExt, pSession);
     1298        supdrvDestroySession(pSession->pDevExt, pSession);
    10261299    return cRefs;
    10271300}
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r49965 r51770  
    5959#       define _interlockedbittestandreset64  _interlockedbittestandreset64_StupidDDKVsCompilerCrap
    6060#       pragma warning(disable : 4163)
    61 #       include <ntddk.h>
     61#       include <iprt/nt/nt.h>
    6262#       pragma warning(default : 4163)
    6363#       undef  _InterlockedExchange
     
    7070#       undef  _interlockedbittestandreset64
    7171#   else
    72 #       include <ntddk.h>
     72#       include <iprt/nt/nt.h>
    7373#   endif
    7474#   include <memory.h>
     
    177177 */
    178178#define OSDBGPRINT(a) SUPR0Printf a
     179
     180/** Debug printf macro shared with the ring-3 part. */
     181#ifdef DEBUG_bird
     182# define SUP_DPRINTF(a) SUPR0Printf a
     183#else
     184# define SUP_DPRINTF(a) do { } while (0)
     185#endif
    179186
    180187
     
    435442    /** Set if is an unrestricted session, clear if restricted. */
    436443    bool                            fUnrestricted;
    437     /* Reference counter. */
     444
     445    /** Set if we're in the hash table, clear if not.  Protected by the hash
     446     * table spinlock. */
     447    bool                            fInHashTable;
     448    /** Reference counter. */
    438449    uint32_t volatile               cRefs;
     450    /** Pointer to the next session with the same hash (common hash table).
     451     *  Protected by the hash table spinlock. */
     452    PSUPDRVSESSION                  pCommonNextHash;
     453    /** Pointer to the OS specific session pointer, if available and in use.
     454     * This is atomically set and cleared as the session is inserted and removed
     455     * from the hash table (protected by the session hash table spinlock). */
     456    PSUPDRVSESSION                 *ppOsSessionPtr;
     457    /** The process (id) of the session. */
     458    RTPROCESS                       Process;
     459    /** Which process this session is associated with.
     460     * This is NIL_RTR0PROCESS for kernel sessions and valid for user ones. */
     461    RTR0PROCESS                     R0Process;
    439462
    440463    /** The VM associated with the session. */
     
    446469    PSUPDRVLDRUSAGE volatile        pLdrUsage;
    447470
    448     /** Spinlock protecting the bundles and the GIP members. */
     471    /** Spinlock protecting the bundles, the GIP members and the
     472     * fProcessCleanupDone flag.  It continues to be valid until the last
     473     * reference to the session is released. */
    449474    RTSPINLOCK                      Spinlock;
    450475    /** The ring-3 mapping of the GIP (readonly). */
     
    461486    /** The group id of the session. (Set by the OS part.) */
    462487    RTGID                           Gid;
    463     /** The process (id) of the session. */
    464     RTPROCESS                       Process;
    465     /** Which process this session is associated with.
    466      * This is NIL_RTR0PROCESS for kernel sessions and valid for user ones. */
    467     RTR0PROCESS                     R0Process;
    468488    /** Per session tracer specfic data. */
    469489    uintptr_t                       uTracerData;
     
    498518    PSUPDRVSESSION                  pNextHash;
    499519# endif
     520# if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING)
     521    /** Pointer to the process protection structure for this session. */
     522    struct SUPDRVNTPROTECT         *pNtProtect;
     523# endif
    500524#endif /* !SUPDRV_AGNOSTIC */
    501525} SUPDRVSESSION;
     
    613637    RTLISTANCHOR                    aTrackerUmodHash[128];
    614638
     639    /** @name Session Handle Table.
     640     * @{ */
     641    /** Spinlock protecting apSessionHashTab, cSessions,
     642     * SUPDRVSESSION::ppOsSessionPtr, SUPDRVSESSION::pCommonNextHash, and possibly
     643     * others depending on the OS. */
     644    RTSPINLOCK                      hSessionHashTabSpinlock;
     645    /** Session hash table hash table.  The size of this table must make sense in
     646     * comparison to GVMM_MAX_HANDLES. */
     647    PSUPDRVSESSION                  apSessionHashTab[HC_ARCH_BITS == 64 ? 8191 : 127];
     648    /** The number of open sessions. */
     649    int32_t                         cSessions;
     650    /** @} */
     651
    615652    /*
    616      * Note! The non-agnostic bits must be a the very end of the structure!
     653     * Note! The non-agnostic bits must be at the very end of the structure!
    617654     */
    618655#ifndef SUPDRV_AGNOSTIC
     
    626663} SUPDRVDEVEXT;
    627664
     665/** Calculates the index into g_apSessionHashTab.*/
     666#define SUPDRV_SESSION_HASH(a_pid)     ( (a_pid) % RT_ELEMENTS(((SUPDRVDEVEXT *)NULL)->apSessionHashTab) )
     667
    628668
    629669RT_C_DECLS_BEGIN
     
    632672*   OS Specific Functions                                                      *
    633673*******************************************************************************/
     674/**
     675 * Called to clean up the session structure before it's freed.
     676 *
     677 * @param   pDevExt             The device globals.
     678 * @param   pSession            The session that's being cleaned up.
     679 */
     680void VBOXCALL   supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
     681
     682/**
     683 * Called to let the OS specfic code perform additional insertion work while
     684 * still under the protection of the hash table spinlock.
     685 *
     686 * @param   pDevExt             The device globals.
     687 * @param   pSession            The session that was inserted.
     688 * @param   pvUser              User context specified to the insert call.
     689 */
     690void VBOXCALL   supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser);
     691
     692/**
     693 * Called to let the OS specfic code perform additional removal work while still
     694 * under the protection of the hash table spinlock.
     695 *
     696 * @param   pDevExt             The device globals.
     697 * @param   pSession            The session that was removed.
     698 * @param   pvUser              User context specified to the remove call.
     699 */
     700void VBOXCALL   supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser);
     701
    634702void VBOXCALL   supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession);
    635703bool VBOXCALL   supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc);
     
    763831void VBOXCALL   supdrvDeleteDevExt(PSUPDRVDEVEXT pDevExt);
    764832int  VBOXCALL   supdrvCreateSession(PSUPDRVDEVEXT pDevExt, bool fUser, bool fUnrestricted,  PSUPDRVSESSION *ppSession);
     833int  VBOXCALL   supdrvSessionHashTabInsert(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVSESSION *ppOsSessionPtr, void *pvUser);
     834int  VBOXCALL   supdrvSessionHashTabRemove(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser);
     835PSUPDRVSESSION VBOXCALL supdrvSessionHashTabLookup(PSUPDRVDEVEXT pDevExt, RTPROCESS Process, RTR0PROCESS R0Process,
     836                                                   PSUPDRVSESSION *ppOsSessionPtr);
    765837uint32_t VBOXCALL supdrvSessionRetain(PSUPDRVSESSION pSession);
    766838uint32_t VBOXCALL supdrvSessionRelease(PSUPDRVSESSION pSession);
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r49965 r51770  
    15421542     * Verify that the image file and parent directories are sane.
    15431543     */
    1544     rc = supR3HardenedVerifyFile(szExecPath, RTHCUINTPTR_MAX, pErrInfo);
     1544    rc = supR3HardenedVerifyFile(szExecPath, RTHCUINTPTR_MAX, false /*fMaybe3rdParty*/, pErrInfo);
    15451545    if (RT_FAILURE(rc))
    15461546        return rc;
     
    15861586     */
    15871587#ifdef VBOX_WITH_HARDENING
    1588     int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
     1588    int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, true /*fMaybe3rdParty*/, pErrInfo);
    15891589    if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
    15901590        LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
  • trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h

    r49634 r51770  
    104104 */
    105105#if defined(IN_SUP_HARDENED_R3) && defined(RT_OS_WINDOWS)
     106# define SUP_HARDENED_NEED_CRT_FUNCTIONS
     107DECLHIDDEN(int)    suplibHardenedMemComp(void const *pvDst, const void *pvSrc, size_t cbToComp);
    106108DECLHIDDEN(void *) suplibHardenedMemCopy(void *pvDst, const void *pvSrc, size_t cbToCopy);
     109DECLHIDDEN(void *) suplibHardenedMemSet(void *pvDst, int ch, size_t cbToSet);
    107110DECLHIDDEN(char *) suplibHardenedStrCopy(char *pszDst, const char *pszSrc);
    108111DECLHIDDEN(size_t) suplibHardenedStrLen(const char *psz);
     
    112115DECLHIDDEN(int)    suplibHardenedStrICmp(const char *psz1, const char *psz2);
    113116#else
     117# undef SUP_HARDENED_NEED_CRT_FUNCTIONS
     118# define suplibHardenedMemComp memcmp
    114119# define suplibHardenedMemCopy memcpy
     120# define suplibHardenedMemSet  memset
    115121# define suplibHardenedStrCopy strcpy
    116122# define suplibHardenedStrLen  strlen
     
    120126# define suplibHardenedStrICmp stricmp
    121127#endif
    122 DECLNORETURN(void) suplibHardenedExit(RTEXITCODE rcExit);
     128DECLNORETURN(void)  suplibHardenedExit(RTEXITCODE rcExit);
     129DECLHIDDEN(void)    suplibHardenedPrintF(const char *pszFormat, ...);
     130DECLHIDDEN(void)    suplibHardenedPrintFV(const char *pszFormat, va_list va);
     131
    123132/** @} */
     133
     134/** Debug output macro. */
     135#ifdef DEBUG_bird
     136# ifdef IN_SUP_HARDENED_R3
     137#  define SUP_DPRINTF(a)    suplibHardenedPrintF a
     138# else
     139#  define SUP_DPRINTF(a)    RTLogPrintf a
     140# endif
     141#else
     142# define SUP_DPRINTF(a)     do { } while (0)
     143#endif
    124144
    125145
     
    135155    kSupIFT_Exe,
    136156    kSupIFT_Dll,
     157    kSupIFT_Rc,
    137158    kSupIFT_Sys,
    138159    kSupIFT_Script,
     
    276297typedef FNSUPR3PREINIT *PFNSUPR3PREINIT;
    277298
     299/** The current SUPR3HardenedMain state / location. */
     300typedef enum SUPR3HARDENEDMAINSTATE
     301{
     302    SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED = 0,
     303    SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY,
     304    SUPR3HARDENEDMAINSTATE_INIT_RUNTIME,
     305    SUPR3HARDENEDMAINSTATE_GET_TRUSTED_MAIN,
     306    SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN,
     307    SUPR3HARDENEDMAINSTATE_END
     308} SUPR3HARDENEDMAINSTATE;
     309
    278310
    279311/*******************************************************************************
     
    288320extern DECLHIDDEN(PSUPQUERYFUNCS)       g_pSupFunctions;
    289321#endif
     322extern DECLHIDDEN(SUPR3HARDENEDMAINSTATE) g_enmSupR3HardenedMainState;
    290323
    291324
     
    360393 */
    361394DECLHIDDEN(int)     supR3HardenedError(int rc, bool fFatal, const char *pszFormat, ...);
     395
    362396DECLHIDDEN(int)     supR3HardenedVerifyAll(bool fFatal, bool fLeaveFilesOpen, const char *pszProgName);
    363397DECLHIDDEN(int)     supR3HardenedVerifyFixedDir(SUPINSTDIR enmDir, bool fFatal);
    364398DECLHIDDEN(int)     supR3HardenedVerifyFixedFile(const char *pszFilename, bool fFatal);
    365399DECLHIDDEN(int)     supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
    366 DECLHIDDEN(int)     supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, PRTERRINFO pErrInfo);
     400DECLHIDDEN(int)     supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
     401                                            PRTERRINFO pErrInfo);
    367402DECLHIDDEN(void)    supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData);
    368403DECLHIDDEN(int)     supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData);
    369404
     405#ifdef RT_OS_WINDOWS
     406DECLHIDDEN(void)    supR3HardenedWinInit(uint32_t fFlags);
     407DECLHIDDEN(void)    supR3HardenedWinInitVersion(void);
     408DECLHIDDEN(void)    supR3HardenedWinVerifyProcess(void);
     409DECLHIDDEN(void)    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(void);
     410DECLHIDDEN(bool)    supR3HardenedWinIsReSpawnNeeded(int cArgs, char **papszArgs);
     411DECLHIDDEN(int)     supR3HardenedWinReSpawn(void);
     412DECLHIDDEN(void *)  supR3HardenedWinLoadLibrary(const char *pszName, bool fSystem32Only);
     413extern RTUTF16      g_wszSupLibHardenedExePath[1024];
     414# ifdef RTPATH_MAX
     415extern char         g_szSupLibHardenedExePath[RTPATH_MAX];
     416# endif
     417#endif
    370418
    371419SUPR3DECL(int)      supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages);
  • trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp

    r49634 r51770  
    781781     * Verify the image file.
    782782     */
    783     int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
     783    int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, true /*fMaybe3rdParty*/, pErrInfo);
    784784    if (RT_FAILURE(rc))
    785785    {
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp

    r49500 r51770  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    121121*******************************************************************************/
    122122/** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */
    123 static SUPPREINITDATA g_SupPreInitData;
     123static SUPPREINITDATA   g_SupPreInitData;
    124124/** The program executable path. */
    125 static char g_szSupLibHardenedExePath[RTPATH_MAX];
     125#ifndef RT_OS_WINDOWS
     126static
     127#endif
     128char                    g_szSupLibHardenedExePath[RTPATH_MAX];
    126129/** The program directory path. */
    127 static char g_szSupLibHardenedDirPath[RTPATH_MAX];
     130static char             g_szSupLibHardenedDirPath[RTPATH_MAX];
    128131
    129132/** The program name. */
    130 static const char *g_pszSupLibHardenedProgName;
     133static const char      *g_pszSupLibHardenedProgName;
    131134
    132135#ifdef SUP_HARDENED_SUID
    133136/** The real UID at startup. */
    134 static uid_t g_uid;
     137static uid_t            g_uid;
    135138/** The real GID at startup. */
    136 static gid_t g_gid;
     139static gid_t            g_gid;
    137140# ifdef RT_OS_LINUX
    138 static uint32_t g_uCaps;
     141static uint32_t         g_uCaps;
    139142# endif
    140143#endif
     144
     145/** The current SUPR3HardenedMain state / location. */
     146SUPR3HARDENEDMAINSTATE  g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED;
    141147
    142148
     
    148154#endif
    149155static PFNSUPTRUSTEDERROR supR3HardenedMainGetTrustedError(const char *pszProgName);
    150 
    151 
    152 #ifdef RT_OS_WINDOWS
    153 /*
    154  * No CRT here, thank you.
    155  */
    156 
    157 /** memcpy */
    158 DECLHIDDEN(void *) suplibHardenedMemCopy(void *pvDst, const void *pvSrc, size_t cbToCopy)
    159 {
    160     size_t         *puDst = (size_t *)pvDst;
    161     size_t const   *puSrc = (size_t const *)pvSrc;
    162     while (cbToCopy >= sizeof(size_t))
    163     {
    164         *puDst++ = *puSrc++;
    165         cbToCopy -= sizeof(size_t);
    166     }
    167 
    168     uint8_t        *pbDst = (uint8_t *)puDst;
    169     uint8_t const  *pbSrc = (uint8_t const *)puSrc;
    170     while (cbToCopy > 0)
    171     {
    172         *pbDst++ = *pbSrc++;
    173         cbToCopy--;
    174     }
    175 
    176     return pvDst;
    177 }
    178 
    179 
    180 /** strcpy */
    181 DECLHIDDEN(char *) suplibHardenedStrCopy(char *pszDst, const char *pszSrc)
    182 {
    183     char *pszRet = pszDst;
    184     char ch;
    185     do
    186     {
    187         ch = *pszSrc++;
    188         *pszDst++ = ch;
    189     } while (ch);
    190     return pszRet;
    191 }
    192 
    193 
    194 /** strlen */
    195 DECLHIDDEN(size_t) suplibHardenedStrLen(const char *psz)
    196 {
    197     const char *pszStart = psz;
    198     while (*psz)
    199         psz++;
    200     return psz - pszStart;
    201 }
    202 
    203 
    204 /** strcat */
    205 DECLHIDDEN(char *) suplibHardenedStrCat(char *pszDst, const char *pszSrc)
    206 {
    207     char *pszRet = pszDst;
    208     while (*pszDst)
    209         pszDst++;
    210     suplibHardenedStrCopy(pszDst, pszSrc);
    211     return pszRet;
    212 }
    213 
    214 
    215 # ifdef RT_OS_WINDOWS
    216 /** stricmp */
    217 DECLHIDDEN(int) suplibHardenedStrICmp(const char *psz1, const char *psz2)
    218 {
    219     const char *pszOrg1 = psz1;
    220     const char *pszOrg2 = psz2;
    221 
    222     for (;;)
    223     {
    224         char ch1 = *psz1++;
    225         char ch2 = *psz1++;
    226         if (ch1 != ch2)
    227         {
    228             int rc = CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE, pszOrg1, -1, pszOrg2, -1);
    229 #  ifdef VBOX_STRICT
    230             if (rc == 0)
    231                 __debugbreak();
    232 #  endif
    233             return rc - 2;
    234         }
    235         if (ch1 == 0)
    236             return 0;
    237     }
    238 }
    239 # endif
    240 
    241 
    242 /** strcmp */
    243 DECLHIDDEN(int) suplibHardenedStrCmp(const char *psz1, const char *psz2)
    244 {
    245     for (;;)
    246     {
    247         char ch1 = *psz1++;
    248         char ch2 = *psz1++;
    249         if (ch1 != ch2)
    250             return ch1 < ch2 ? -1 : 1;
    251         if (ch1 == 0)
    252             return 0;
    253     }
    254 }
    255 
    256 
    257 /** strncmp */
    258 DECLHIDDEN(int) suplibHardenedStrNCmp(const char *psz1, const char *psz2, size_t cchMax)
    259 {
    260     while (cchMax-- > 0)
    261     {
    262         char ch1 = *psz1++;
    263         char ch2 = *psz1++;
    264         if (ch1 != ch2)
    265             return ch1 < ch2 ? -1 : 1;
    266         if (ch1 == 0)
    267             break;
    268     }
    269     return 0;
    270 }
    271 
    272 #endif /* RT_OS_WINDOWS */
    273156
    274157
     
    423306    do
    424307    {
    425         unsigned iDigit = uValue & fDigitMask;
     308        *psz-- = pchDigits[uValue & fDigitMask];
    426309        uValue >>= cShift;
    427 
    428         *psz-- = uValue % 10;
    429         uValue /= 10;
    430310    } while (uValue > 0);
    431311
    432312    if ((fFlags & RTSTR_F_SPECIAL) && uBase == 16)
    433313    {
    434         *psz-- = 'x';
     314        *psz-- = !(fFlags & RTSTR_F_CAPITAL) ? 'x' : 'X';
    435315        *psz-- = '0';
    436316    }
     
    442322
    443323/**
     324 * Writes a wide character string to standard error.
     325 *
     326 * @param   pwsz                The string.
     327 */
     328static void suplibHardenedPrintWideStr(PCRTUTF16 pwsz)
     329{
     330    for (;;)
     331    {
     332        RTUTF16 wc = *pwsz++;
     333        if (!wc)
     334            return;
     335        if (   (wc < 0x7f && wc >= 0x20)
     336            || wc == '\n'
     337            || wc == '\r')
     338            suplibHardenedPrintChr((char)wc);
     339        else
     340        {
     341            suplibHardenedPrintStrN(RT_STR_TUPLE("\\x"));
     342            suplibHardenedPrintHexOctal(wc, 16, 0);
     343        }
     344    }
     345}
     346
     347#ifdef IPRT_NO_CRT
     348
     349/** Buffer structure used by suplibHardenedOutput. */
     350struct SUPLIBHARDENEDOUTPUTBUF
     351{
     352    size_t off;
     353    char   szBuf[2048];
     354};
     355
     356/** Callback for RTStrFormatV, see FNRTSTROUTPUT. */
     357static DECLCALLBACK(size_t) suplibHardenedOutput(void *pvArg, const char *pachChars, size_t cbChars)
     358{
     359    SUPLIBHARDENEDOUTPUTBUF *pBuf = (SUPLIBHARDENEDOUTPUTBUF *)pvArg;
     360    size_t cbTodo = cbChars;
     361    for (;;)
     362    {
     363        size_t cbSpace = sizeof(pBuf->szBuf) - pBuf->off - 1;
     364
     365        /* Flush the buffer? */
     366        if (   cbSpace == 0
     367            || (cbTodo == 0 && pBuf->off))
     368        {
     369            suplibHardenedPrintStrN(pBuf->szBuf, pBuf->off);
     370# ifdef RT_OS_WINDOWS
     371            OutputDebugString(pBuf->szBuf);
     372# endif
     373            pBuf->off = 0;
     374            cbSpace = sizeof(pBuf->szBuf) - 1;
     375        }
     376
     377        /* Copy the string into the buffer. */
     378        if (cbTodo == 1)
     379        {
     380            pBuf->szBuf[pBuf->off++] = *pachChars;
     381            break;
     382        }
     383        if (cbSpace >= cbTodo)
     384        {
     385            memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbTodo);
     386            pBuf->off += cbTodo;
     387            break;
     388        }
     389        memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbSpace);
     390        pBuf->off += cbSpace;
     391        cbTodo -= cbSpace;
     392    }
     393    pBuf->szBuf[pBuf->off] = '\0';
     394
     395    return cbChars;
     396}
     397
     398#endif /* IPRT_NO_CRT */
     399
     400/**
    444401 * Simple printf to standard error.
    445402 *
     
    449406DECLHIDDEN(void) suplibHardenedPrintFV(const char *pszFormat, va_list va)
    450407{
     408#ifdef IPRT_NO_CRT
     409    /*
     410     * Use buffered output here to avoid character mixing on the windows
     411     * console and to enable us to use OutputDebugString.
     412     */
     413    SUPLIBHARDENEDOUTPUTBUF Buf;
     414    Buf.off = 0;
     415    Buf.szBuf[0] = '\0';
     416    RTStrFormatV(suplibHardenedOutput, &Buf, NULL, NULL, pszFormat, va);
     417
     418#else /* !IPRT_NO_CRT */
    451419    /*
    452420     * Format loop.
     
    544512
    545513                case 's':
    546                 {
    547                     const char *pszStr = va_arg(va, const char *);
    548                     if (!RT_VALID_PTR(pszStr))
    549                         pszStr = "<NULL>";
    550                     suplibHardenedPrintStr(pszStr);
     514                    if (chArgSize == 'l')
     515                    {
     516                        PCRTUTF16 pwszStr = va_arg(va, PCRTUTF16 );
     517                        if (RT_VALID_PTR(pwszStr))
     518                            suplibHardenedPrintWideStr(pwszStr);
     519                        else
     520                            suplibHardenedPrintStr("<NULL>");
     521                    }
     522                    else
     523                    {
     524                        const char *pszStr = va_arg(va, const char *);
     525                        if (!RT_VALID_PTR(pszStr))
     526                            pszStr = "<NULL>";
     527                        suplibHardenedPrintStr(pszStr);
     528                    }
    551529                    break;
    552                 }
    553530
    554531                case 'd':
     
    617594                }
    618595
     596                case 'R':
     597                    if (pszFormat[0] == 'r' && pszFormat[1] == 'c')
     598                    {
     599                        int iValue = va_arg(va, int);
     600                        if (iValue < 0)
     601                        {
     602                            suplibHardenedPrintChr('-');
     603                            iValue = -iValue;
     604                        }
     605                        suplibHardenedPrintDecimal(iValue);
     606                        pszFormat += 2;
     607                        break;
     608                    }
     609                    /* fall thru */
    619610
    620611                /*
     
    636627    if (pszLast != pszFormat)
    637628        suplibHardenedPrintStrN(pszLast, pszFormat - pszLast);
     629#endif /* !IPRT_NO_CRT */
    638630}
    639631
     
    652644    va_end(va);
    653645}
    654 
    655646
    656647
     
    863854
    864855#elif defined(RT_OS_WINDOWS)
    865     HMODULE hExe = GetModuleHandle(NULL);
    866     if (!GetModuleFileName(hExe, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath)))
    867         supR3HardenedFatal("supR3HardenedExecDir: GetModuleFileName failed, rc=%d\n", GetLastError());
     856    int cbRet = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/,
     857                                    g_wszSupLibHardenedExePath, -1,
     858                                    g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath),
     859                                    NULL /*pchDefChar*/, NULL /* pfUsedDefChar */);
     860    if (!cbRet)
     861        supR3HardenedFatal("supR3HardenedExecDir: WideCharToMultiByte failed, rc=%d\n", GetLastError());
    868862#else
    869863# error needs porting.
     
    956950            break;
    957951
     952        case kSupInitOp_Misc:
    958953        case kSupInitOp_IPRT:
    959954        case kSupInitOp_Integrity:
     
    988983#endif
    989984    {
    990         PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName);
    991         if (pfnTrustedError)
    992             pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va);
     985        static volatile bool s_fRecursive = false; /* Loader hooks may cause recursion. */
     986        if (!s_fRecursive)
     987        {
     988            s_fRecursive = true;
     989
     990            PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName);
     991            if (pfnTrustedError)
     992                pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va);
     993
     994            s_fRecursive = false;
     995        }
    993996    }
    994997
     
    10821085            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
    10831086                                  "Kernel memory allocation/mapping failed");
     1087        case VERR_SUPDRV_HARDENING_EVIL_HANDLE:
     1088            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPDRV_HARDENING_EVIL_HANDLE");
     1089        case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0:
     1090            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0");
     1091        case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1:
     1092            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1");
     1093        case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2:
     1094            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2");
    10841095        default:
    10851096            supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
     
    13251336     */
    13261337#if defined(RT_OS_WINDOWS)
    1327     /** @todo consider using LOAD_WITH_ALTERED_SEARCH_PATH here! */
    1328     HMODULE hMod = LoadLibraryEx(szPath, NULL /*hFile*/, 0 /* dwFlags */);
     1338    HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
    13291339    if (!hMod)
    13301340        supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_MODULE_NOT_FOUND,
    1331                               "LoadLibraryEx(\"%s\",,) failed (rc=%d)",
     1341                              "LoadLibrary \"%s\" failed (rc=%d)",
    13321342                              szPath, GetLastError());
    13331343    PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3InitEx"));
     
    14081418     */
    14091419#if defined(RT_OS_WINDOWS)
    1410     /** @todo consider using LOAD_WITH_ALTERED_SEARCH_PATH here! */
    1411     HMODULE hMod = LoadLibraryEx(szPath, NULL /*hFile*/, 0 /* dwFlags */);
     1420    HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
    14121421    if (!hMod)
    14131422        return NULL;
     
    14521461     */
    14531462#if defined(RT_OS_WINDOWS)
    1454     /** @todo consider using LOAD_WITH_ALTERED_SEARCH_PATH here! */
    1455     HMODULE hMod = LoadLibraryEx(szPath, NULL /*hFile*/, 0 /* dwFlags */);
     1463    HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
    14561464    if (!hMod)
    1457         supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibraryEx(\"%s\",,) failed, rc=%d\n",
     1465        supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibrary \"%s\" failed, rc=%d\n",
    14581466                            szPath, GetLastError());
    14591467    FARPROC pfn = GetProcAddress(hMod, SUP_HARDENED_SYM("TrustedMain"));
     
    15361544
    15371545    /*
    1538      * Validate the installation.
    1539      */
     1546     * Validate the installation.  On Windows we leave the files open so they
     1547     * cannot be tampered with after they've been verified.  We also check
     1548     * install loader hooks and check the process integrity.
     1549     */
     1550#ifndef RT_OS_WINDOWS
    15401551    supR3HardenedVerifyAll(true /* fFatal */, false /* fLeaveFilesOpen */, pszProgName);
     1552#else
     1553    supR3HardenedWinInit(fFlags);
     1554    supR3HardenedVerifyAll(true /* fFatal */, true /* fLeaveFilesOpen */, pszProgName);
     1555    supR3HardenedWinVerifyProcess();
     1556#endif
     1557
     1558#ifdef RT_OS_WINDOWS
     1559    /*
     1560     * On Windows we'll respawn the process with a special vboxdrv arrangement
     1561     * in place to monitor access to the process for its inception.
     1562     */
     1563    if (   !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
     1564        && supR3HardenedWinIsReSpawnNeeded(argc, argv))
     1565        return supR3HardenedWinReSpawn();
     1566#endif
    15411567
    15421568    /*
     
    15451571    if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
    15461572        supR3HardenedMainOpenDevice();
     1573#ifdef RT_OS_WINDOWS
     1574    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation();
     1575    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY;
     1576#endif
    15471577
    15481578    /*
     
    15681598     * call RTR3InitEx.
    15691599     */
     1600    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_INIT_RUNTIME;
    15701601    supR3HardenedMainInitRuntime(fFlags);
    15711602
     
    15741605     * and pass control to it.
    15751606     */
     1607    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_GET_TRUSTED_MAIN;
    15761608    PFNSUPTRUSTEDMAIN pfnTrustedMain = supR3HardenedMainGetTrustedMain(pszProgName);
     1609    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN;
    15771610    return pfnTrustedMain(argc, argv, envp);
    15781611}
    15791612
    1580 
    1581 #ifdef RT_OS_WINDOWS
    1582 
    1583 extern "C" int main(int argc, char **argv, char **envp);
    1584 
    1585 /**
    1586  * The executable entry point.
    1587  */
    1588 extern "C" void __stdcall suplibHardenedWindowsMain(void)
    1589 {
    1590     RTEXITCODE  rcExit = RTEXITCODE_FAILURE;
    1591 
    1592     /*
    1593      * Convert the arguments to UTF-8.
    1594      */
    1595     int    cArgs;
    1596     PWSTR *papwszArgs = CommandLineToArgvW(GetCommandLineW(), &cArgs); /** @todo fix me! */
    1597     if (papwszArgs)
    1598     {
    1599         char **papszArgs = (char **)HeapAlloc(GetProcessHeap(), 0 /* dwFlags*/, (cArgs + 1) * sizeof(const char **));
    1600         if (papszArgs)
    1601         {
    1602             int iArg;
    1603             for (iArg = 0; iArg < cArgs; iArg++)
    1604             {
    1605                 int cbNeeded = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, papwszArgs[iArg], -1, NULL /*pszDst*/, 0 /*cbDst*/,
    1606                                                    NULL /*pchDefChar*/, NULL /* pfUsedDefChar */);
    1607                 if (!cbNeeded)
    1608                 {
    1609                     suplibHardenedPrintF("CommandLineToArgvW failed on argument %d: %u\n", iArg, GetLastError());
    1610                     break;
    1611                 }
    1612 
    1613                 papszArgs[iArg] = (char *)HeapAlloc(GetProcessHeap(), 0 /*dwFlags*/, cbNeeded);
    1614                 if (!papszArgs[iArg])
    1615                 {
    1616                     suplibHardenedPrintF("HeapAlloc failed");
    1617                     break;
    1618                 }
    1619 
    1620                 int cbRet = WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, papwszArgs[iArg], -1, papszArgs[iArg], cbNeeded,
    1621                                                 NULL /*pchDefChar*/, NULL /* pfUsedDefChar */);
    1622                 if (!cbRet)
    1623                 {
    1624                     suplibHardenedPrintF("CommandLineToArgvW failed on argument %d: %u\n", iArg, GetLastError());
    1625                     break;
    1626                 }
    1627             }
    1628             if (iArg == cArgs)
    1629             {
    1630                 papszArgs[iArg] = NULL;
    1631 
    1632                 /*
    1633                  * Call the main function.
    1634                  */
    1635                 rcExit = (RTEXITCODE)main(cArgs, papszArgs, NULL);
    1636             }
    1637         }
    1638         else
    1639             suplibHardenedPrintF("HeapAlloc failed\n");
    1640     }
    1641     else
    1642         suplibHardenedPrintF("CommandLineToArgvW failed\n");
    1643 
    1644     /*
    1645      * Exit the process (never return).
    1646      */
    1647     for (;;)
    1648         ExitProcess(rcExit);
    1649 }
    1650 
    1651 #endif
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp

    r49211 r51770  
    7474
    7575#include "SUPLibInternal.h"
     76#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING)
     77# define SUPHNTVI_NO_NT_STUFF
     78# include "win/SUPHardenedVerify-win.h"
     79#endif
    7680
    7781
     
    8690#endif
    8791
     92/** Compare table file names with externally supplied names. */
     93#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     94# define SUP_COMP_FILENAME  suplibHardenedStrICmp
     95#else
     96# define SUP_COMP_FILENAME  suplibHardenedStrCmp
     97#endif
     98
    8899
    89100/*******************************************************************************
     
    107118
    108119#ifdef VBOX_WITH_RAW_MODE
    109     {   kSupIFT_Dll,  kSupID_AppPrivArch,       false, "VMMGC.gc" },
    110     {   kSupIFT_Dll,  kSupID_AppPrivArch,       false, "VBoxDDGC.gc" },
    111     {   kSupIFT_Dll,  kSupID_AppPrivArch,       false, "VBoxDD2GC.gc" },
     120    {   kSupIFT_Rc,   kSupID_AppPrivArch,       false, "VMMGC.gc" },
     121    {   kSupIFT_Rc,   kSupID_AppPrivArch,       false, "VBoxDDGC.gc" },
     122    {   kSupIFT_Rc,   kSupID_AppPrivArch,       false, "VBoxDD2GC.gc" },
    112123#endif
    113124
     
    154165    {   kSupIFT_Exe,  kSupID_AppBin,            false, "VBoxSVC" SUPLIB_EXE_SUFF },
    155166 #ifdef RT_OS_WINDOWS
    156     {   kSupIFT_Dll,  kSupID_AppPrivArchComp,   false, "VBoxC" SUPLIB_DLL_SUFF },
     167    {   kSupIFT_Dll,  kSupID_SharedLib,         false, "VBoxC" SUPLIB_DLL_SUFF },
    157168 #else
    158169    {   kSupIFT_Exe,  kSupID_AppPrivArch,       false, "VBoxXPCOMIPCD" SUPLIB_EXE_SUFF },
     
    347358                                 FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
    348359                                 NULL,
    349                                  OPEN_ALWAYS,
     360                                 OPEN_EXISTING,
    350361                                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
    351362                                 NULL);
     
    466477        if (RT_SUCCESS(rc))
    467478        {
    468 #if defined(RT_OS_WINDOWS)
     479#if defined(RT_OS_WINDOWS) /** @todo Need to use WCHAR on windows! */
    469480            HANDLE hFile = CreateFile(szPath,
    470481                                      GENERIC_READ,
    471482                                      FILE_SHARE_READ,
    472483                                      NULL,
    473                                       OPEN_ALWAYS,
     484                                      OPEN_EXISTING,
    474485                                      FILE_ATTRIBUTE_NORMAL,
    475486                                      NULL);
    476487            if (hFile != INVALID_HANDLE_VALUE)
    477488            {
    478                 /** @todo Check the type, and verify the signature (separate function so we can skip it). */
     489# if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_R3_STATIC) /* Latter: Not in VBoxCpuReport and friends. */
     490
     491                char szErr[1024];
     492                RTERRINFO ErrInfo;
     493                RTErrInfoInit(&ErrInfo, szErr, sizeof(szErr));
     494
     495                uint32_t fFlags = SUPHNTVI_F_REQUIRE_BUILD_CERT;
     496                if (pFile->enmType == kSupIFT_Rc)
     497                    fFlags |= SUPHNTVI_F_RC_IMAGE;
     498
     499                rc = supHardenedWinVerifyImageByHandleNoName(hFile, fFlags, &ErrInfo);
     500                if (RT_FAILURE(rc))
     501                {
     502                    rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: '%s': Image verify error rc=%Rrc: %s\n",
     503                                            szPath, rc, szErr);
     504                    CloseHandle(hFile);
     505                }
     506                else
     507#endif
    479508                {
    480509                    /* it's valid. */
     
    491520                if (!pFile->fOptional || err != ERROR_FILE_NOT_FOUND)
    492521                    rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
    493                                             "supR3HardenedVerifyFileInternal: Failed to open \"%s\": err=%d\n",
    494                                             szPath, err);
     522                                            "supR3HardenedVerifyFileInternal: Failed to open '%s': err=%d\n", szPath, err);
    495523            }
    496524#else /* UNIXY */
     
    581609    if (RT_FAILURE(rc))
    582610        return rc;
    583 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    584     if (suplibHardenedStrICmp(szName, pszFilename))
    585 #else
    586     if (suplibHardenedStrCmp(szName, pszFilename))
    587 #endif
     611    if (SUP_COMP_FILENAME(szName, pszFilename))
    588612    {
    589613        /*
     
    596620        if (    GetFullPathName(szName, RT_ELEMENTS(szName2), &szName2[0], &pszIgnored)
    597621            &&  GetFullPathName(pszFilename, RT_ELEMENTS(szName), &szName[0], &pszIgnored))
    598             if (!suplibHardenedStrICmp(szName2, szName))
     622            if (!SUP_COMP_FILENAME(szName2, szName))
    599623                rc = VINF_SUCCESS;
    600624#else
     
    603627        if (    realpath(szName, szName2) != NULL
    604628            &&  realpath(pszFilename, szName) != NULL)
    605             if (!suplibHardenedStrCmp(szName2, szName))
     629            if (!SUP_COMP_FILENAME(szName2, szName))
    606630                rc = VINF_SUCCESS;
    607631#endif
     
    645669    const char *pszName = supR3HardenedPathFilename(pszFilename);
    646670    for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
    647         if (!suplibHardenedStrCmp(pszName, g_aSupInstallFiles[iFile].pszFile))
     671        if (!SUP_COMP_FILENAME(pszName, g_aSupInstallFiles[iFile].pszFile))
    648672        {
    649673            int rc = supR3HardenedVerifySameFile(iFile, pszFilename, fFatal);
     
    904928     */
    905929#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    906     if (   RT_C_IS_ALPHA(pszSrc[0])
     930    if (   !RT_C_IS_ALPHA(pszSrc[0])
    907931        || pszSrc[1] != ':'
    908932        || !RTPATH_IS_SLASH(pszSrc[2]))
     
    14421466 *                              as we ended up with when verifying the path.
    14431467 *                              RTHCUINTPTR_MAX means NIL here.
     1468 * @param   fMaybe3rdParty      Set if the file is could be a supplied by a
     1469 *                              third party.  Different validation rules may
     1470 *                              apply to 3rd party code on some platforms.
    14441471 * @param   pErrInfo            Where to return extended error information.
    14451472 *                              Optional.
    14461473 */
    1447 DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, PRTERRINFO pErrInfo)
     1474DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile,
     1475                                        bool fMaybe3rdParty, PRTERRINFO pErrInfo)
    14481476{
    14491477    /*
     
    14771505
    14781506    /*
    1479      * Verify the file.
     1507     * Verify the file handle against the last component, if specified.
    14801508     */
    14811509    if (hNativeFile != RTHCUINTPTR_MAX)
    1482         return supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
     1510    {
     1511        rc = supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
     1512        if (RT_FAILURE(rc))
     1513            return rc;
     1514    }
     1515
     1516#ifdef RT_OS_WINDOWS
     1517    /*
     1518     * The files shall be signed on windows, verify that.
     1519     */
     1520    HANDLE hVerify;
     1521    if (hNativeFile == RTHCUINTPTR_MAX)
     1522        hVerify = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     1523    else if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)hNativeFile, GetCurrentProcess(), &hVerify,
     1524                              GENERIC_READ, false /*bInheritHandle*/, 0 /*dwOptions*/))
     1525        hVerify = INVALID_HANDLE_VALUE;
     1526    if (hVerify != INVALID_HANDLE_VALUE)
     1527    {
     1528        uint32_t fFlags = SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING;
     1529        if (!fMaybe3rdParty)
     1530            fFlags = SUPHNTVI_F_REQUIRE_BUILD_CERT;
     1531        const char *pszSuffix = RTPathSuffix(pszFilename);
     1532        if (   pszSuffix
     1533            &&                   pszSuffix[0]  == '.'
     1534            && (   RT_C_TO_LOWER(pszSuffix[1]) == 'r'
     1535                || RT_C_TO_LOWER(pszSuffix[1]) == 'g')
     1536            &&     RT_C_TO_LOWER(pszSuffix[2]) == 'c'
     1537            &&                   pszSuffix[3]  == '\0' )
     1538            fFlags |= SUPHNTVI_F_RC_IMAGE;
     1539# ifndef IN_SUP_R3_STATIC /* Not in VBoxCpuReport and friends. */
     1540        rc = supHardenedWinVerifyImageByHandleNoName(hVerify, fFlags, pErrInfo);
     1541# endif
     1542        CloseHandle(hVerify);
     1543    }
     1544    else
     1545        rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(GetLastError()),
     1546                           "Error %u trying to open (or duplicate handle for) '%s'", GetLastError(), pszFilename);
     1547    if (RT_FAILURE(rc))
     1548        return rc;
     1549#endif
     1550
    14831551    return VINF_SUCCESS;
    14841552}
  • trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp

    r51769 r51770  
    782782
    783783
     784void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     785{
     786    NOREF(pDevExt);
     787    NOREF(pSession);
     788}
     789
     790
     791void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     792{
     793    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     794}
     795
     796
     797void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     798{
     799    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     800}
     801
     802
    784803/**
    785804 * Initializes any OS specific object creator fields.
  • trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c

    r49718 r51770  
    496496
    497497
     498void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     499{
     500    NOREF(pDevExt);
     501    NOREF(pSession);
     502}
     503
     504
     505void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     506{
     507    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     508}
     509
     510
     511void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     512{
     513    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     514}
     515
     516
    498517void VBOXCALL   supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
    499518{
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r50008 r51770  
    809809
    810810
     811void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     812{
     813    NOREF(pDevExt);
     814    NOREF(pSession);
     815}
     816
     817
     818void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     819{
     820    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     821}
     822
     823
     824void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     825{
     826    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     827}
     828
     829
    811830/**
    812831 * Initializes any OS specific object creator fields.
  • trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp

    r49634 r51770  
    364364
    365365
     366void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     367{
     368    NOREF(pDevExt);
     369    NOREF(pSession);
     370}
     371
     372
     373void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     374{
     375    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     376}
     377
     378
     379void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     380{
     381    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     382}
     383
     384
    366385void VBOXCALL   supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
    367386{
  • trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c

    r50664 r51770  
    903903
    904904
     905void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     906{
     907    NOREF(pDevExt);
     908    NOREF(pSession);
     909}
     910
     911
     912void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     913{
     914    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     915}
     916
     917
     918void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     919{
     920    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     921}
     922
     923
    905924/**
    906925 * Initializes any OS specific object creator fields.
  • trunk/src/VBox/HostDrivers/Support/testcase/Makefile.kmk

    r43386 r51770  
    55
    66#
    7 # Copyright (C) 2006-2012 Oracle Corporation
     7# Copyright (C) 2006-2014 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
  • trunk/src/VBox/HostDrivers/Support/testcase/tstNtQueryStuff.cpp

    r48952 r51770  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include <ntstatus.h>
    32 #define WIN32_NO_STATUS
    33 #include <Windows.h>
    34 #include <winternl.h>
    35 
    36 typedef enum
    37 {
    38     MemoryBasicInformation = 0,
    39     MemoryWorkingSetList,
    40     MemorySectionName,
    41     MemoryBasicVlmInformation
    42 } MEMORY_INFORMATION_CLASS;
    43 
    44 typedef struct
    45 {
    46     UNICODE_STRING  SectionFileName;
    47     WCHAR           NameBuffer[ANYSIZE_ARRAY];
    48 } MEMORY_SECTION_NAME;
    49 
    50 extern "C"
    51 NTSYSAPI NTSTATUS NTAPI NtQueryVirtualMemory(IN HANDLE hProcess,
    52                                              IN LPCVOID pvWhere,
    53                                              IN MEMORY_INFORMATION_CLASS MemoryInfo,
    54                                              OUT PVOID pvBuf,
    55                                              IN SIZE_T cbBuf,
    56                                              OUT PSIZE_T pcbReturned OPTIONAL);
    57 
    58 #define ProcessDebugPort            ((PROCESSINFOCLASS)7 )
    59 #define ProcessHandleCount          ((PROCESSINFOCLASS)20)
    60 #define ProcessWow64Information     ((PROCESSINFOCLASS)26)
    61 #define ProcessImageFileName        ((PROCESSINFOCLASS)27)
    62 #define ProcessDebugObjectHandle    ((PROCESSINFOCLASS)30)
    63 #define ProcessExecuteFlags         ((PROCESSINFOCLASS)34)
    64 #define ProcessImageFileNameWin32   ((PROCESSINFOCLASS)43)
    65 #define ProcessImageFileMapping     ((PROCESSINFOCLASS)44)
    66 
    67 
     31#include <iprt/nt/nt-and-windows.h>
    6832#include <iprt/test.h>
    6933#include <iprt/string.h>
     
    304268    if (NT_SUCCESS(rcNt))
    305269        RTTestIPrintf(RTTESTLVL_ALWAYS, "BasicInfo:\n"
    306                                         "    UniqueProcessId = %#x (%6d)\n"
     270                                        "    UniqueProcessId              = %#x (%6d)\n"
     271                                        "    InheritedFromUniqueProcessId = %#x (%6d)\n"
     272                                        "    ExitStatus      = %#x\n"
    307273                                        "    PebBaseAddress  = %p\n"
    308                                         "    Reserved1       = %p          ExitStatus?\n"
    309                                         "    Reserved2a      = %p          AffinityMask?\n"
    310                                         "    Reserved2b      = %p (%6d) BasePriority?\n"
    311                                         "    Reserved3       = %p (%6d) InheritedFromUniqueProcessId?\n"
     274                                        "    AffinityMask    = %#zx\n"
     275                                        "    BasePriority    = %#zx\n"
    312276                      ,
    313277                      BasicInfo.UniqueProcessId, BasicInfo.UniqueProcessId,
     278                      BasicInfo.InheritedFromUniqueProcessId, BasicInfo.InheritedFromUniqueProcessId,
     279                      BasicInfo.ExitStatus,
    314280                      BasicInfo.PebBaseAddress,
    315                       BasicInfo.Reserved1,
    316                       BasicInfo.Reserved2[0],
    317                       BasicInfo.Reserved2[1], BasicInfo.Reserved2[1],
    318                       BasicInfo.Reserved3, BasicInfo.Reserved3
     281                      BasicInfo.AffinityMask,
     282                      BasicInfo.BasePriority
    319283                      );
    320 
    321284
    322285    /* Debugger present? */
     
    435398
    436399
    437 int main()
     400int main(int argc, char **argv)
    438401{
    439402    RTEXITCODE rcExit = RTTestInitAndCreate("tstNtQueryStuff", &g_hTest);
     
    443406
    444407    g_hProcess = GetCurrentProcess();
    445 
    446     //tstQueryVirtualMemory();
     408    if (argc >= 2 && argv[1][0] != '-')
     409    {
     410        const char *pszPid = argv[1];
     411        uint32_t idPid = RTStrToInt32(pszPid);
     412
     413        uint32_t fAccess = PROCESS_QUERY_INFORMATION;
     414        if (argc >= 3)
     415            fAccess = RTStrToInt32(argv[2]);
     416
     417        g_hProcess = OpenProcess(fAccess, FALSE, idPid);
     418        if (g_hProcess == NULL)
     419        {
     420            RTTestIFailed("Error %u opening process %u (%s)\n", GetLastError(), idPid, pszPid);
     421            return RTTestSummaryAndDestroy(g_hTest);
     422        }
     423    }
     424
     425    tstQueryVirtualMemory();
    447426    tstQueryInformationProcess();
    448427
    449 
    450428    return RTTestSummaryAndDestroy(g_hTest);
    451429}
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r51744 r51770  
    2828*   Header Files                                                               *
    2929*******************************************************************************/
     30#define IPRT_NT_MAP_TO_ZW
    3031#define LOG_GROUP LOG_GROUP_SUP_DRV
    3132#include "../SUPDrvInternal.h"
     
    3435
    3536#include <iprt/assert.h>
     37#include <iprt/avl.h>
     38#include <iprt/ctype.h>
    3639#include <iprt/initterm.h>
    3740#include <iprt/mem.h>
    3841#include <iprt/process.h>
    3942#include <iprt/power.h>
     43#include <iprt/spinlock.h>
    4044#include <iprt/string.h>
    4145#include <VBox/log.h>
     46#include <VBox/err.h>
    4247
    4348#include <iprt/asm-amd64-x86.h>
     49
     50#ifdef VBOX_WITH_HARDENING
     51# include "SUPHardenedVerify-win.h"
     52#endif
    4453
    4554
     
    6675#define DEVICE_NAME_DOS_USR     L"\\DosDevices\\VBoxDrvU"
    6776
     77#ifdef VBOX_WITH_HARDENING
     78/** Win32 device name for hardened stub access. */
     79# define DEVICE_NAME_STUB       "\\\\.\\VBoxDrvStub"
     80/** NT device name for hardened stub access. */
     81# define DEVICE_NAME_NT_STUB    L"\\Device\\VBoxDrvStub"
     82///** Win Symlink name for hardened stub access. */
     83//# define DEVICE_NAME_DOS_STUB   L"\\DosDevices\\VBoxDrvStub"
     84
     85
     86/** Macro for checking for deflecting calls to the stub device. */
     87# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) \
     88    do { if ((a_pDevObj) == g_pDevObjStub) supdrvNtCompleteRequest(STATUS_ACCESS_DENIED, a_pIrp); } while (0)
     89#else
     90# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) do {} while (0)
     91#endif
     92
    6893/** Enables the fast I/O control code path. */
    6994#define VBOXDRV_WITH_FAST_IO
     
    7398*   Structures and Typedefs                                                    *
    7499*******************************************************************************/
    75 #if 0 //def RT_ARCH_AMD64
    76 typedef struct SUPDRVEXECMEM
    77 {
    78     PMDL pMdl;
    79     void *pvMapping;
    80     void *pvAllocation;
    81 } SUPDRVEXECMEM, *PSUPDRVEXECMEM;
    82 #endif
    83 
    84100/**
    85101 * Device extension used by VBoxDrvU.
     
    103119     ? (PSUPDRVDEVEXT)pDevObj->DeviceExtension \
    104120     : ((PSUPDRVDEVEXTUSR)pDevObj->DeviceExtension)->pMainDrvExt )
     121
     122#ifdef VBOX_WITH_HARDENING
     123
     124/**
     125 * Device extension used by VBoxDrvS.
     126 */
     127typedef struct SUPDRVDEVEXTSTUB
     128{
     129    /** Common header. */
     130    SUPDRVDEVEXTUSR     Common;
     131} SUPDRVDEVEXTSTUB;
     132/** Pointer to the VBoxDrvS device extension. */
     133typedef SUPDRVDEVEXTSTUB *PSUPDRVDEVEXTSTUB;
     134/** Value of SUPDRVDEVEXTSTUB::Common.u32Cookie. */
     135#define SUPDRVDEVEXTSTUB_COOKIE      UINT32_C(0x90abcdef)
     136
     137
     138/**
     139 * The kind of process we're protecting.
     140 */
     141typedef enum SUPDRVNTPROTECTKIND
     142{
     143    kSupDrvNtProtectKind_Invalid = 0,
     144
     145    /** Stub process protection while performing process verification.
     146     * Next: StubSpawning (or free)  */
     147    kSupDrvNtProtectKind_StubUnverified,
     148    /** Stub process protection before it creates the VM process.
     149     * Next: StubParent, StubDead. */
     150    kSupDrvNtProtectKind_StubSpawning,
     151    /** Stub process protection while having a VM process as child.
     152     * Next: StubDead  */
     153    kSupDrvNtProtectKind_StubParent,
     154    /** Dead stub process. */
     155    kSupDrvNtProtectKind_StubDead,
     156
     157    /** Potential VM process.
     158     * Next: VmProcessConfirmed, VmProcessDead. */
     159    kSupDrvNtProtectKind_VmProcessUnconfirmed,
     160    /** Confirmed VM process.
     161     * Next: VmProcessDead. */
     162    kSupDrvNtProtectKind_VmProcessConfirmed,
     163    /** Dead VM process. */
     164    kSupDrvNtProtectKind_VmProcessDead,
     165
     166    /** End of valid protection kinds. */
     167    kSupDrvNtProtectKind_End
     168} SUPDRVNTPROTECTKIND;
     169
     170/**
     171 * A NT process protection structure.
     172 */
     173typedef struct SUPDRVNTPROTECT
     174{
     175    /** The AVL node core structure.  The process ID is the pid. */
     176    AVLPVNODECORE       AvlCore;
     177    /** Magic value (SUPDRVNTPROTECT_MAGIC). */
     178    uint32_t volatile   u32Magic;
     179    /** Reference counter. */
     180    uint32_t volatile   cRefs;
     181    /** The kind of process we're protecting. */
     182    SUPDRVNTPROTECTKIND volatile enmProcessKind;
     183    /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
     184     *  NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
     185    bool                fFirstProcessCreateHandle : 1;
     186    /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
     187     *  NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
     188    bool                fFirstThreadCreateHandle : 1;
     189    /** 8.1: Hack to allow more rights to the handle returned by
     190     *  NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
     191    bool                fCsrssFirstProcessCreateHandle : 1;
     192    /** Vista, 7 & 8: Hack to allow more rights to the handle duplicated by CSR
     193     *  during process creation. Only applicable to VmProcessUnconfirmed. */
     194    bool                fCsrssFirstProcessDuplicateHandle : 1;
     195    /** 7,: Hack to allow the supid themes service duplicate handle privileges to
     196     *  our process. */
     197    bool                fThemesFirstProcessCreateHandle : 1;
     198
     199    /** The parent PID for VM processes, otherwise NULL. */
     200    HANDLE              hParentPid;
     201    /** The PID of the CSRSS process associated with this process. */
     202    HANDLE              hCsrssPid;
     203    /** Pointer to the CSRSS process structure (referenced). */
     204    PEPROCESS           pCsrssProcess;
     205    /** State dependent data. */
     206    union
     207    {
     208        /** A stub process in the StubParent state will keep a reference to a child
     209         * while it's in the VmProcessUnconfirmed state so that it can be cleaned up
     210         * correctly if things doesn't work out. */
     211        struct SUPDRVNTPROTECT *pChild;
     212        /** A process in the VmProcessUnconfirmed state will keep a weak
     213         * reference to the parent's protection structure so it can clean up the pChild
     214         * refernece the parent has to it. */
     215        struct SUPDRVNTPROTECT *pParent;
     216    } u;
     217} SUPDRVNTPROTECT;
     218/** Pointer to a NT process protection record. */
     219typedef SUPDRVNTPROTECT *PSUPDRVNTPROTECT;
     220/** The SUPDRVNTPROTECT::u32Magic value (Robert A. Heinlein). */
     221# define SUPDRVNTPROTECT_MAGIC      UINT32_C(0x19070707)
     222/** The SUPDRVNTPROTECT::u32Magic value of a dead structure. */
     223# define SUPDRVNTPROTECT_MAGIC_DEAD UINT32_C(0x19880508)
     224
     225/** Pointer to ObRegisterCallbacks. */
     226typedef NTSTATUS (NTAPI *PFNOBREGISTERCALLBACKS)(POB_CALLBACK_REGISTRATION, PVOID *);
     227/** Pointer to ObUnregisterCallbacks. */
     228typedef VOID     (NTAPI *PFNOBUNREGISTERCALLBACKS)(PVOID);
     229/** Pointer to PsSetCreateProcessNotifyRoutineEx. */
     230typedef NTSTATUS (NTAPI *PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)(PCREATE_PROCESS_NOTIFY_ROUTINE_EX, BOOLEAN);
     231/** Pointer to PsReferenceProcessFilePointer. */
     232typedef NTSTATUS (NTAPI *PFNPSREFERENCEPROCESSFILEPOINTER)(PEPROCESS, PFILE_OBJECT *);
     233/** Pointer to PsIsProtectedProcessLight. */
     234typedef BOOLEAN  (NTAPI *PFNPSISPROTECTEDPROCESSLIGHT)(PEPROCESS);
     235
     236#endif /* VBOX_WITH_HARDENINIG */
    105237
    106238
     
    123255static NTSTATUS _stdcall   VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
    124256static NTSTATUS            VBoxDrvNtErr2NtStatus(int rc);
     257#ifdef VBOX_WITH_HARDENING
     258static NTSTATUS             supdrvNtProtectInit(void);
     259static void                 supdrvNtProtectTerm(void);
     260static int                  supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid,
     261                                                  SUPDRVNTPROTECTKIND enmProcessKind, bool fLink);
     262static void                 supdrvNtProtectRelease(PSUPDRVNTPROTECT pNtProtect);
     263static PSUPDRVNTPROTECT     supdrvNtProtectLookup(HANDLE hPid);
     264static int                  supdrvNtProtectFindAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect);
     265static int                  supdrvNtProtectVerifyProcess(PSUPDRVNTPROTECT pNtProtect);
     266
     267static bool                 supdrvNtIsDebuggerAttached(void);
     268#endif
    125269
    126270
     
    175319#endif /* VBOXDRV_WITH_FAST_IO */
    176320
     321#ifdef VBOX_WITH_HARDENING
     322/** Pointer to the stub device instance. */
     323static PDEVICE_OBJECT               g_pDevObjStub = NULL;
     324/** Spinlock protecting g_NtProtectTree as well as the releasing of protection
     325 *  structures. */
     326static RTSPINLOCK                   g_hNtProtectLock = NIL_RTSPINLOCK;
     327/** AVL tree of SUPDRVNTPROTECT structures. */
     328static AVLPVTREE                    g_NtProtectTree  = NULL;
     329/** Cookie returned by ObRegisterCallbacks for the callbacks. */
     330static PVOID                        g_pvObCallbacksCookie = NULL;
     331/** Combined windows NT version number.  See SUP_MAKE_NT_VER_COMBINED. */
     332uint32_t                            g_uNtVerCombined = 0;
     333/** Pointer to ObRegisterCallbacks if available.. */
     334static PFNOBREGISTERCALLBACKS       g_pfnObRegisterCallbacks = NULL;
     335/** Pointer to ObUnregisterCallbacks if available.. */
     336static PFNOBUNREGISTERCALLBACKS     g_pfnObUnRegisterCallbacks = NULL;
     337/** Pointer to PsSetCreateProcessNotifyRoutineEx if available.. */
     338static PFNPSSETCREATEPROCESSNOTIFYROUTINEEX g_pfnPsSetCreateProcessNotifyRoutineEx = NULL;
     339/** Pointer to PsReferenceProcessFilePointer if available. */
     340static PFNPSREFERENCEPROCESSFILEPOINTER g_pfnPsReferenceProcessFilePointer = NULL;
     341/** Pointer to PsIsProtectedProcessLight. */
     342static PFNPSISPROTECTEDPROCESSLIGHT g_pfnPsIsProtectedProcessLight = NULL;
     343
     344# ifdef RT_ARCH_AMD64
     345extern "C" {
     346/** Pointer to KiServiceLinkage (used to fake missing ZwQueryVirtualMemory on
     347 *  XP64 / W2K3-64). */
     348PFNRT                               g_pfnKiServiceLinkage  = NULL;
     349/** Pointer to KiServiceInternal (used to fake missing ZwQueryVirtualMemory on
     350 *  XP64 / W2K3-64) */
     351PFNRT                               g_pfnKiServiceInternal = NULL;
     352}
     353# endif
     354#endif
     355
    177356
    178357/**
     
    192371    if (NT_SUCCESS(rcNt))
    193372    {
    194         UNICODE_STRING DosName;
    195         RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS_SYS);
    196         rcNt = IoCreateSymbolicLink(&DosName, &DevName);
     373        UNICODE_STRING DosNameSys;
     374        RtlInitUnicodeString(&DosNameSys, DEVICE_NAME_DOS_SYS);
     375        rcNt = IoCreateSymbolicLink(&DosNameSys, &DevName);
    197376        if (NT_SUCCESS(rcNt))
    198377        {
     
    204383            if (NT_SUCCESS(rcNt))
    205384            {
    206                 UNICODE_STRING DosName;
    207                 RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS_USR);
    208                 rcNt = IoCreateSymbolicLink(&DosName, &DevName);
     385                UNICODE_STRING DosNameUsr;
     386                RtlInitUnicodeString(&DosNameUsr, DEVICE_NAME_DOS_USR);
     387                rcNt = IoCreateSymbolicLink(&DosNameUsr, &DevName);
    209388                if (NT_SUCCESS(rcNt))
    210389                {
     
    213392                    pDevExtUsr->u32Cookie   = SUPDRVDEVEXTUSR_COOKIE;
    214393
    215                     /* Done. */
    216                     return rcNt;
     394#ifdef VBOX_WITH_HARDENING
     395                    /*
     396                     * Hardened stub device.
     397                     */
     398                    RtlInitUnicodeString(&DevName, DEVICE_NAME_NT_STUB);
     399                    rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXTSTUB), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjStub);
     400                    if (NT_SUCCESS(rcNt))
     401                    {
     402                        //UNICODE_STRING DosNameStub;
     403                        //RtlInitUnicodeString(&DosNameStub, DEVICE_NAME_DOS_STUB);
     404                        //rcNt = IoCreateSymbolicLink(&DosNameStub, &DevName);
     405                        if (NT_SUCCESS(rcNt))
     406                        {
     407                            PSUPDRVDEVEXTSTUB pDevExtStub = (PSUPDRVDEVEXTSTUB)g_pDevObjStub->DeviceExtension;
     408                            pDevExtStub->Common.pMainDrvExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
     409                            pDevExtStub->Common.u32Cookie   = SUPDRVDEVEXTSTUB_COOKIE;
     410#endif
     411
     412                            /* Done. */
     413                            return rcNt;
     414#ifdef VBOX_WITH_HARDENING
     415                        }
     416
     417                        /* Bail out. */
     418                        IoDeleteDevice(g_pDevObjStub);
     419                        g_pDevObjUsr = NULL;
     420                    }
     421                    IoDeleteSymbolicLink(&DosNameUsr);
     422#endif
    217423                }
    218 
    219                 /* Bail out. */
    220424                IoDeleteDevice(g_pDevObjUsr);
    221425                g_pDevObjUsr = NULL;
    222426            }
    223             IoDeleteSymbolicLink(&DosName);
     427            IoDeleteSymbolicLink(&DosNameSys);
    224428        }
    225429        IoDeleteDevice(g_pDevObjSys);
     
    241445    rcNt = IoDeleteSymbolicLink(&DosName);
    242446
    243     PSUPDRVDEVEXTUSR pDevExtUsr = (PSUPDRVDEVEXTUSR)g_pDevObjUsr->DeviceExtension;
    244     pDevExtUsr->pMainDrvExt = NULL;
    245 
     447#ifdef VBOX_WITH_HARDENING
     448    //RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS_STUB);
     449    //rcNt = IoDeleteSymbolicLink(&DosName);
     450#endif
     451
     452    if (g_pDevObjUsr)
     453    {
     454        PSUPDRVDEVEXTUSR pDevExtUsr = (PSUPDRVDEVEXTUSR)g_pDevObjUsr->DeviceExtension;
     455        pDevExtUsr->pMainDrvExt = NULL;
     456    }
     457#ifdef VBOX_WITH_HARDENING
     458    if (g_pDevObjStub)
     459    {
     460        PSUPDRVDEVEXTSTUB pDevExtStub = (PSUPDRVDEVEXTSTUB)g_pDevObjStub->DeviceExtension;
     461        pDevExtStub->Common.pMainDrvExt = NULL;
     462    }
     463#endif
     464
     465#ifdef VBOX_WITH_HARDENING
     466    IoDeleteDevice(g_pDevObjStub);
     467    g_pDevObjStub = NULL;
     468#endif
    246469    IoDeleteDevice(g_pDevObjUsr);
    247470    g_pDevObjUsr = NULL;
     
    273496
    274497    /*
    275      * Create device.
    276      * (That means creating a device object and a symbolic link so the DOS
    277      * subsystems (OS/2, win32, ++) can access the device.)
     498     * Initialize the runtime (IPRT).
    278499     */
    279     NTSTATUS rcNt = vboxdrvNtCreateDevices(pDrvObj);
    280     if (NT_SUCCESS(rcNt))
    281     {
    282         int vrc = RTR0Init(0);
    283         if (RT_SUCCESS(vrc))
    284         {
    285             Log(("VBoxDrv::DriverEntry\n"));
    286 
     500    NTSTATUS rcNt;
     501    int vrc = RTR0Init(0);
     502    if (RT_SUCCESS(vrc))
     503    {
     504        Log(("VBoxDrv::DriverEntry\n"));
     505
     506#ifdef VBOX_WITH_HARDENING
     507        /*
     508         * Initialize process protection.
     509         */
     510        rcNt = supdrvNtProtectInit();
     511        if (NT_SUCCESS(rcNt))
     512#endif
     513        {
    287514            /*
    288              * Initialize the device extension.
     515             * Create device.
     516             * (That means creating a device object and a symbolic link so the DOS
     517             * subsystems (OS/2, win32, ++) can access the device.)
    289518             */
    290             PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
    291             memset(pDevExt, 0, sizeof(*pDevExt));
    292 
    293             vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION));
    294             if (!vrc)
     519            rcNt = vboxdrvNtCreateDevices(pDrvObj);
     520            if (NT_SUCCESS(rcNt))
    295521            {
    296522                /*
    297                  * Setup the driver entry points in pDrvObj.
     523                 * Initialize the device extension.
    298524                 */
    299                 pDrvObj->DriverUnload                                   = VBoxDrvNtUnload;
    300                 pDrvObj->MajorFunction[IRP_MJ_CREATE]                   = VBoxDrvNtCreate;
    301                 pDrvObj->MajorFunction[IRP_MJ_CLEANUP]                  = VBoxDrvNtCleanup;
    302                 pDrvObj->MajorFunction[IRP_MJ_CLOSE]                    = VBoxDrvNtClose;
    303                 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = VBoxDrvNtDeviceControl;
    304                 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]  = VBoxDrvNtInternalDeviceControl;
    305                 pDrvObj->MajorFunction[IRP_MJ_READ]                     = VBoxDrvNtNotSupportedStub;
    306                 pDrvObj->MajorFunction[IRP_MJ_WRITE]                    = VBoxDrvNtNotSupportedStub;
    307 
    308                 /* more? */
     525                PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
     526                memset(pDevExt, 0, sizeof(*pDevExt));
     527
     528                vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION));
     529                if (!vrc)
     530                {
     531                    /*
     532                     * Setup the driver entry points in pDrvObj.
     533                     */
     534                    pDrvObj->DriverUnload                                   = VBoxDrvNtUnload;
     535                    pDrvObj->MajorFunction[IRP_MJ_CREATE]                   = VBoxDrvNtCreate;
     536                    pDrvObj->MajorFunction[IRP_MJ_CLEANUP]                  = VBoxDrvNtCleanup;
     537                    pDrvObj->MajorFunction[IRP_MJ_CLOSE]                    = VBoxDrvNtClose;
     538                    pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = VBoxDrvNtDeviceControl;
     539                    pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]  = VBoxDrvNtInternalDeviceControl;
     540                    pDrvObj->MajorFunction[IRP_MJ_READ]                     = VBoxDrvNtNotSupportedStub;
     541                    pDrvObj->MajorFunction[IRP_MJ_WRITE]                    = VBoxDrvNtNotSupportedStub;
    309542
    310543#ifdef VBOXDRV_WITH_FAST_IO
    311                 /* Fast I/O to speed up guest execution roundtrips. */
    312                 pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;
     544                    /* Fast I/O to speed up guest execution roundtrips. */
     545                    pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;
    313546#endif
    314547
    315                 /* Register ourselves for power state changes. */
    316                 UNICODE_STRING      CallbackName;
    317                 OBJECT_ATTRIBUTES   Attr;
    318 
    319                 RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
    320                 InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    321 
    322                 rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE);
    323                 if (rcNt == STATUS_SUCCESS)
    324                     pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback, VBoxPowerDispatchCallback,
    325                                                                  g_pDevObjSys);
    326 
    327                 Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
    328                 return STATUS_SUCCESS;
    329             }
    330 
    331             Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
    332             rcNt = VBoxDrvNtErr2NtStatus(vrc);
    333 
    334             RTR0Term();
    335         }
    336         else
    337         {
    338             Log(("RTR0Init failed with vrc=%d!\n", vrc));
    339             rcNt = VBoxDrvNtErr2NtStatus(vrc);
    340         }
    341 
    342         vboxdrvNtDestroyDevices();
     548                    /*
     549                     * Register ourselves for power state changes.  We don't
     550                     * currently care if this fails.
     551                     */
     552                    UNICODE_STRING      CallbackName;
     553                    RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
     554
     555                    OBJECT_ATTRIBUTES   Attr;
     556                    InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL);
     557
     558                    rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE);
     559                    if (rcNt == STATUS_SUCCESS)
     560                        pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback,
     561                                                                     VBoxPowerDispatchCallback,
     562                                                                     g_pDevObjSys);
     563
     564                    /*
     565                     * Done! Returning success!
     566                     */
     567                    Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
     568                    return STATUS_SUCCESS;
     569                }
     570
     571                Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
     572                rcNt = VBoxDrvNtErr2NtStatus(vrc);
     573
     574                vboxdrvNtDestroyDevices();
     575            }
     576#ifdef VBOX_WITH_HARDENING
     577            supdrvNtProtectTerm();
     578#endif
     579        }
     580        RTR0Term();
     581    }
     582    else
     583    {
     584        Log(("RTR0Init failed with vrc=%d!\n", vrc));
     585        rcNt = VBoxDrvNtErr2NtStatus(vrc);
    343586    }
    344587    if (NT_SUCCESS(rcNt))
     
    369612     */
    370613    supdrvDeleteDevExt(pDevExt);
     614#ifdef VBOX_WITH_HARDENING
     615    supdrvNtProtectTerm();
     616#endif
    371617    RTR0Term();
    372618    vboxdrvNtDestroyDevices();
     
    377623
    378624/**
     625 * For simplifying request completion into a simple return statement, extended
     626 * version.
     627 *
     628 * @returns rcNt
     629 * @param   rcNt                The status code.
     630 * @param   uInfo               Extra info value.
     631 * @param   pIrp                The IRP.
     632 */
     633DECLINLINE(NTSTATUS) supdrvNtCompleteRequestEx(NTSTATUS rcNt, ULONG_PTR uInfo, PIRP pIrp)
     634{
     635    pIrp->IoStatus.Status       = rcNt;
     636    pIrp->IoStatus.Information  = uInfo;
     637    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
     638    return rcNt;
     639}
     640
     641
     642/**
     643 * For simplifying request completion into a simple return statement.
     644 *
     645 * @returns rcNt
     646 * @param   rcNt                The status code.
     647 * @param   pIrp                The IRP.
     648 */
     649DECLINLINE(NTSTATUS) supdrvNtCompleteRequest(NTSTATUS rcNt, PIRP pIrp)
     650{
     651    return supdrvNtCompleteRequestEx(rcNt, 0 /*uInfo*/, pIrp);
     652}
     653
     654
     655/**
    379656 * Create (i.e. Open) file entry point.
    380657 *
     
    385662{
    386663    Log(("VBoxDrvNtCreate: RequestorMode=%d\n", pIrp->RequestorMode));
    387     const bool          fUnrestricted = pDevObj == g_pDevObjSys;
    388     PIO_STACK_LOCATION  pStack = IoGetCurrentIrpStackLocation(pIrp);
     664    PIO_STACK_LOCATION  pStack   = IoGetCurrentIrpStackLocation(pIrp);
    389665    PFILE_OBJECT        pFileObj = pStack->FileObject;
    390     PSUPDRVDEVEXT       pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
     666    PSUPDRVDEVEXT       pDevExt  = SUPDRVNT_GET_DEVEXT(pDevObj);
    391667
    392668    /*
     
    395671     */
    396672    if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
    397     {
    398         pIrp->IoStatus.Status       = STATUS_NOT_A_DIRECTORY;
    399         pIrp->IoStatus.Information  = 0;
    400         IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    401         return STATUS_NOT_A_DIRECTORY;
    402     }
     673        return supdrvNtCompleteRequest(STATUS_NOT_A_DIRECTORY, pIrp);
    403674
    404675    /*
    405676     * Don't create a session for kernel clients, they'll close the handle
    406677     * immediately and work with the file object via
    407      * VBoxDrvNtInternalDeviceControl.  The first request will there be one
    408      * to create a session.
     678     * VBoxDrvNtInternalDeviceControl.  The first request will be one to
     679     * create a session.
    409680     */
    410681    NTSTATUS rcNt;
    411682    if (pIrp->RequestorMode == KernelMode)
    412         rcNt = STATUS_SUCCESS;
     683    {
     684        if (pDevObj == g_pDevObjSys)
     685            return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     686
     687        rcNt = STATUS_ACCESS_DENIED;
     688    }
    413689    else
    414690    {
     691#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
    415692        /*
    416          * Call common code for the rest.
     693         * Make sure no debuggers are attached to non-user processes.
    417694         */
    418         pFileObj->FsContext = NULL;
    419         PSUPDRVSESSION pSession;
    420         int rc = supdrvCreateSession(pDevExt, true /*fUser*/, fUnrestricted, &pSession);
    421         if (!rc)
    422             pFileObj->FsContext = pSession;
    423         rcNt = pIrp->IoStatus.Status = VBoxDrvNtErr2NtStatus(rc);
    424     }
    425 
    426     pIrp->IoStatus.Information  = 0;
    427     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    428 
    429     return rcNt;
     695        if (   pDevObj != g_pDevObjUsr
     696            && supdrvNtIsDebuggerAttached())
     697        {
     698            LogRel(("vboxdrv: Process %p is being debugged, access to vboxdrv / vboxdrvu declined.\n",
     699                    PsGetProcessId(PsGetCurrentProcess())));
     700            rcNt = STATUS_TRUST_FAILURE;
     701        }
     702        else
     703#endif
     704        {
     705            int rc = VINF_SUCCESS;
     706
     707#ifdef VBOX_WITH_HARDENING
     708            /*
     709             * Access to the stub device is only granted to processes which
     710             * passes verification.
     711             *
     712             * Note! The stub device has no need for a SUPDRVSESSION structure,
     713             *       so the it uses the SUPDRVNTPROTECT directly instead.
     714             */
     715            if (pDevObj == g_pDevObjStub)
     716            {
     717                PSUPDRVNTPROTECT pNtProtect = NULL;
     718                rc = supdrvNtProtectCreate(&pNtProtect, PsGetProcessId(PsGetCurrentProcess()),
     719                                           kSupDrvNtProtectKind_StubUnverified, true /*fLink*/);
     720                if (RT_SUCCESS(rc))
     721                {
     722                    rc = supdrvNtProtectFindAssociatedCsrss(pNtProtect);
     723                    if (RT_SUCCESS(rc))
     724                        rc = supdrvNtProtectVerifyProcess(pNtProtect);
     725                    if (RT_SUCCESS(rc))
     726                    {
     727                        pFileObj->FsContext = pNtProtect; /* Keeps reference. */
     728                        return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     729                    }
     730
     731                    supdrvNtProtectRelease(pNtProtect);
     732                }
     733                LogRel(("vboxdrv: Declined %p access to VBoxDrvStub: rc=%d\n", PsGetProcessId(PsGetCurrentProcess()), rc));
     734            }
     735            /*
     736             * Unrestricted access is only granted to a process in the
     737             * VmProcessUnconfirmed state that checks out correctly and is
     738             * allowed to transition to VmProcessConfirmed.  Again, only one
     739             * session per process.
     740             */
     741            else if (pDevObj != g_pDevObjUsr)
     742            {
     743                PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(PsGetProcessId(PsGetCurrentProcess()));
     744                if (pNtProtect)
     745                {
     746                    if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
     747                    {
     748                        rc = supdrvNtProtectVerifyProcess(pNtProtect);
     749                        if (RT_SUCCESS(rc))
     750                        {
     751                            /* Create a session. */
     752                            PSUPDRVSESSION pSession;
     753                            rc = supdrvCreateSession(pDevExt, true /*fUser*/, pDevObj == g_pDevObjSys /*fUnrestricted*/,
     754                                                     &pSession);
     755                            if (RT_SUCCESS(rc))
     756                            {
     757                                rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     758                                supdrvSessionRelease(pSession);
     759                                if (RT_SUCCESS(rc))
     760                                {
     761                                    pSession->pNtProtect = pNtProtect; /* Keeps reference. */
     762                                    return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     763                                }
     764                            }
     765
     766                            /* No second attempt. */
     767                            RTSpinlockAcquire(g_hNtProtectLock);
     768                            if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessConfirmed)
     769                                pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
     770                            RTSpinlockRelease(g_hNtProtectLock);
     771
     772                            LogRel(("vboxdrv: supdrvCreateSession failed for process %p: rc=%d.\n",
     773                                    PsGetProcessId(PsGetCurrentProcess()), rc));
     774                        }
     775                        else
     776                            LogRel(("vboxdrv: Process %p failed process verification: rc=%d.\n",
     777                                    PsGetProcessId(PsGetCurrentProcess()), rc));
     778                    }
     779                    else
     780                    {
     781                        LogRel(("vboxdrv: %p is not a budding VM process (enmProcessKind=%d).\n",
     782                                PsGetProcessId(PsGetCurrentProcess()), pNtProtect->enmProcessKind));
     783                        rc = VERR_ACCESS_DENIED;
     784                    }
     785                    supdrvNtProtectRelease(pNtProtect);
     786                }
     787                else
     788                {
     789                    LogRel(("vboxdrv: %p is not a budding VM process.\n", PsGetProcessId(PsGetCurrentProcess())));
     790                    rc = VERR_ACCESS_DENIED;
     791                }
     792            }
     793            /*
     794             * Call common code to create an unprivileged session.
     795             */
     796            else
     797            {
     798                PSUPDRVSESSION pSession;
     799                rc = supdrvCreateSession(pDevExt, true /*fUser*/, false /*fUnrestricted*/, &pSession);
     800                if (RT_SUCCESS(rc))
     801                {
     802                    rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     803                    supdrvSessionRelease(pSession);
     804                    if (RT_SUCCESS(rc))
     805                    {
     806                        pFileObj->FsContext  = pSession; /* Keeps reference. No race. */
     807                        pSession->pNtProtect = NULL;
     808                        return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     809                    }
     810                }
     811            }
     812
     813#else  /* !VBOX_WITH_HARDENING */
     814            /*
     815             * Call common code to create a session.
     816             */
     817            pFileObj->FsContext = NULL;
     818            PSUPDRVSESSION pSession;
     819            rc = supdrvCreateSession(pDevExt, true /*fUser*/, pDevObj == g_pDevObjSys /*fUnrestricted*/, &pSession);
     820            if (RT_SUCCESS(rc))
     821            {
     822                rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
     823                supdrvSessionRelease(pSession);
     824                if (RT_SUCCESS(rc))
     825                    return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
     826
     827            }
     828#endif /* !VBOX_WITH_HARDENING */
     829
     830            /* bail out */
     831            rcNt = VBoxDrvNtErr2NtStatus(rc);
     832        }
     833    }
     834
     835    Assert(!NT_SUCCESS(rcNt));
     836    pFileObj->FsContext = NULL;
     837    return supdrvNtCompleteRequest(rcNt, pIrp); /* Note. the IoStatus is completely ignored on error. */
    430838}
    431839
     
    442850    PIO_STACK_LOCATION  pStack   = IoGetCurrentIrpStackLocation(pIrp);
    443851    PFILE_OBJECT        pFileObj = pStack->FileObject;
    444     PSUPDRVSESSION      pSession = (PSUPDRVSESSION)pFileObj->FsContext;
    445 
    446     Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
    447     if (pSession)
    448     {
    449         supdrvSessionRelease(pSession);
    450         pFileObj->FsContext = NULL;
    451     }
    452 
    453     pIrp->IoStatus.Information = 0;
    454     pIrp->IoStatus.Status = STATUS_SUCCESS;
    455     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    456 
    457     return STATUS_SUCCESS;
     852
     853#ifdef VBOX_WITH_HARDENING
     854    if (pDevObj == g_pDevObjStub)
     855    {
     856        PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)pFileObj->FsContext;
     857        Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pNtProtect=%p\n", pDevExt, pFileObj, pNtProtect));
     858        if (pNtProtect)
     859        {
     860            supdrvNtProtectRelease(pNtProtect);
     861            pFileObj->FsContext = NULL;
     862        }
     863    }
     864    else
     865#endif
     866    {
     867        PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
     868                                                             (PSUPDRVSESSION *)&pFileObj->FsContext);
     869        Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
     870        if (pSession)
     871        {
     872            supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
     873            supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
     874        }
     875    }
     876
     877    return supdrvNtCompleteRequest(STATUS_SUCCESS, pIrp);
    458878}
    459879
     
    470890    PIO_STACK_LOCATION  pStack   = IoGetCurrentIrpStackLocation(pIrp);
    471891    PFILE_OBJECT        pFileObj = pStack->FileObject;
    472     PSUPDRVSESSION      pSession = (PSUPDRVSESSION)pFileObj->FsContext;
    473 
    474     Log(("VBoxDrvNtClose: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
    475     if (pSession)
    476     {
    477         supdrvSessionRelease(pSession);
    478         pFileObj->FsContext = NULL;
    479     }
    480 
    481     pIrp->IoStatus.Information = 0;
    482     pIrp->IoStatus.Status = STATUS_SUCCESS;
    483     IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    484 
    485     return STATUS_SUCCESS;
     892
     893#ifdef VBOX_WITH_HARDENING
     894    if (pDevObj == g_pDevObjStub)
     895    {
     896        PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)pFileObj->FsContext;
     897        Log(("VBoxDrvNtClose: pDevExt=%p pFileObj=%p pNtProtect=%p\n", pDevExt, pFileObj, pNtProtect));
     898        if (pNtProtect)
     899        {
     900            supdrvNtProtectRelease(pNtProtect);
     901            pFileObj->FsContext = NULL;
     902        }
     903    }
     904    else
     905#endif
     906    {
     907        PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
     908                                                             (PSUPDRVSESSION *)&pFileObj->FsContext);
     909        Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
     910        if (pSession)
     911        {
     912            supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
     913            supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
     914        }
     915    }
     916
     917    return supdrvNtCompleteRequest(STATUS_SUCCESS, pIrp);
    486918}
    487919
     
    510942{
    511943    PSUPDRVDEVEXT   pDevExt  = SUPDRVNT_GET_DEVEXT(pDevObj);
    512     PSUPDRVSESSION  pSession = (PSUPDRVSESSION)pFileObj->FsContext;
    513944
    514945    /*
    515      * Check the input a little bit.
     946     * Check the input a little bit and get a the session references.
    516947     */
     948    PSUPDRVSESSION  pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
     949                                                          (PSUPDRVSESSION *)&pFileObj->FsContext);
    517950    if (!pSession)
    518951    {
    519         pIoStatus->Status      = STATUS_INVALID_PARAMETER;
     952        pIoStatus->Status      = STATUS_TRUST_FAILURE;
    520953        pIoStatus->Information = 0;
    521954        return TRUE;
    522955    }
    523956
    524     /*
    525      * Deal with the 2-3 high-speed IOCtl that takes their arguments from
    526      * the session and iCmd, and does not return anything.
    527      */
    528     if (   (   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
     957    if (pSession->fUnrestricted)
     958    {
     959#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
     960        if (supdrvNtIsDebuggerAttached())
     961        {
     962            pIoStatus->Status      = STATUS_TRUST_FAILURE;
     963            pIoStatus->Information = 0;
     964            supdrvSessionRelease(pSession);
     965            return TRUE;
     966        }
     967#endif
     968
     969        /*
     970         * Deal with the 2-3 high-speed IOCtl that takes their arguments from
     971         * the session and iCmd, and does not return anything.
     972         */
     973        if (   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
    529974            || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
    530975            || uCmd == SUP_IOCTL_FAST_DO_NOP)
    531         && pSession->fUnrestricted == true)
    532     {
    533         int rc = supdrvIOCtlFast(uCmd, (unsigned)(uintptr_t)pvOutput /* VMCPU id */, pDevExt, pSession);
    534         pIoStatus->Status      = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
    535         pIoStatus->Information = 0; /* Could be used to pass rc if we liked. */
    536         return TRUE;
     976        {
     977            int rc = supdrvIOCtlFast(uCmd, (unsigned)(uintptr_t)pvOutput/* VMCPU id */, pDevExt, pSession);
     978            pIoStatus->Status      = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
     979            pIoStatus->Information = 0; /* Could be used to pass rc if we liked. */
     980            supdrvSessionRelease(pSession);
     981            return TRUE;
     982        }
    537983    }
    538984
     
    546992          pDevExt, uCmd, pvInput, cbInput, pvOutput, cbOutput, pSession));
    547993
    548 #ifdef RT_ARCH_AMD64
     994# ifdef RT_ARCH_AMD64
    549995    /* Don't allow 32-bit processes to do any I/O controls. */
    550996    if (!IoIs32bitProcess(NULL))
    551 #endif
     997# endif
    552998    {
    553999        /*
     
    6551101        }
    6561102    }
     1103# ifdef RT_ARCH_AMD64
     1104    else
     1105    {
     1106        Log(("VBoxDrvNtFastIoDeviceControl: WOW64 req - not supported\n"));
     1107        rcNt = STATUS_NOT_SUPPORTED;
     1108    }
     1109# endif
     1110
     1111    /* complete the request. */
     1112    pIoStatus->Status = rcNt;
     1113    pIoStatus->Information = cbOut;
     1114    supdrvSessionRelease(pSession);
     1115    return TRUE; /* handled. */
     1116}
     1117#endif /* VBOXDRV_WITH_FAST_IO */
     1118
     1119
     1120#ifdef VBOXDRV_WITH_FAST_IO
     1121/**
     1122 * Fast I/O device control callback.
     1123 *
     1124 * This performs no buffering, neither on the way in or out.
     1125 *
     1126 * @returns TRUE if handled, FALSE if the normal I/O control routine should be
     1127 *          called.
     1128 * @param   pFileObj            The file object.
     1129 * @param   fWait               Whether it's a blocking call
     1130 * @param   pvInput             The input buffer as specified by the user.
     1131 * @param   cbInput             The size of the input buffer.
     1132 * @param   pvOutput            The output buffer as specfied by the user.
     1133 * @param   cbOutput            The size of the output buffer.
     1134 * @param   uFunction           The function.
     1135 * @param   pIoStatus           Where to return the status of the operation.
     1136 * @param   pDevObj             The device object..
     1137 */
     1138static BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput,
     1139                                                     PVOID pvOutput, ULONG cbOutput, ULONG uCmd,
     1140                                                     PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj)
     1141{
     1142    PSUPDRVDEVEXT   pDevExt  = SUPDRVNT_GET_DEVEXT(pDevObj);
     1143    PSUPDRVSESSION  pSession = (PSUPDRVSESSION)pFileObj->FsContext;
     1144
     1145    /*
     1146     * Check the input a little bit.
     1147     */
     1148    if (!pSession)
     1149    {
     1150        pIoStatus->Status      = STATUS_INVALID_PARAMETER;
     1151        pIoStatus->Information = 0;
     1152        return TRUE;
     1153    }
     1154
     1155    /*
     1156     * Deal with the 2-3 high-speed IOCtl that takes their arguments from
     1157     * the session and iCmd, and does not return anything.
     1158     */
     1159    if (   (   uCmd == SUP_IOCTL_FAST_DO_RAW_RUN
     1160            || uCmd == SUP_IOCTL_FAST_DO_HM_RUN
     1161            || uCmd == SUP_IOCTL_FAST_DO_NOP)
     1162        && pSession->fUnrestricted == true)
     1163    {
     1164        int rc = supdrvIOCtlFast(uCmd, (unsigned)(uintptr_t)pvOutput /* VMCPU id */, pDevExt, pSession);
     1165        pIoStatus->Status      = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
     1166        pIoStatus->Information = 0; /* Could be used to pass rc if we liked. */
     1167        return TRUE;
     1168    }
     1169
     1170    /*
     1171     * The normal path.
     1172     */
     1173    NTSTATUS    rcNt;
     1174    unsigned    cbOut = 0;
     1175    int         rc = 0;
     1176    Log2(("VBoxDrvNtFastIoDeviceControl(%p): ioctl=%#x pvIn=%p cbIn=%#x pvOut=%p cbOut=%#x pSession=%p\n",
     1177          pDevExt, uCmd, pvInput, cbInput, pvOutput, cbOutput, pSession));
     1178
     1179#ifdef RT_ARCH_AMD64
     1180    /* Don't allow 32-bit processes to do any I/O controls. */
     1181    if (!IoIs32bitProcess(NULL))
     1182#endif
     1183    {
     1184        /*
     1185         * In this fast I/O device control path we have to do our own buffering.
     1186         */
     1187        /* Verify that the I/O control function matches our pattern. */
     1188        if ((uCmd & 0x3) == METHOD_BUFFERED)
     1189        {
     1190            /* Get the header so we can validate it a little bit against the
     1191               parameters before allocating any memory kernel for the reqest. */
     1192            SUPREQHDR Hdr;
     1193            if (cbInput >= sizeof(Hdr) && cbOutput >= sizeof(Hdr))
     1194            {
     1195                __try
     1196                {
     1197                    RtlCopyMemory(&Hdr, pvInput, sizeof(Hdr));
     1198                    rcNt = STATUS_SUCCESS;
     1199                }
     1200                __except(EXCEPTION_EXECUTE_HANDLER)
     1201                {
     1202                    rcNt = GetExceptionCode();
     1203                }
     1204            }
     1205            else
     1206                rcNt = STATUS_INVALID_PARAMETER;
     1207            if (NT_SUCCESS(rcNt))
     1208            {
     1209                /* Verify that the sizes in the request header are correct. */
     1210                ULONG cbBuf = RT_MAX(cbInput, cbOutput);
     1211                if (   cbInput  == Hdr.cbIn
     1212                    && cbOutput == Hdr.cbOut
     1213                    && cbBuf < _1M*16)
     1214                {
     1215                    /* Allocate a buffer and copy all the input into it. */
     1216                    PSUPREQHDR pHdr = (PSUPREQHDR)ExAllocatePoolWithTag(NonPagedPool, cbBuf, 'VBox');
     1217                    if (pHdr)
     1218                    {
     1219                        __try
     1220                        {
     1221                            RtlCopyMemory(pHdr, pvInput, cbInput);
     1222                            if (cbInput < cbBuf)
     1223                                RtlZeroMemory((uint8_t *)pHdr + cbInput, cbBuf - cbInput);
     1224                            rcNt = STATUS_SUCCESS;
     1225                        }
     1226                        __except(EXCEPTION_EXECUTE_HANDLER)
     1227                        {
     1228                            rcNt = GetExceptionCode();
     1229                        }
     1230                    }
     1231                    else
     1232                        rcNt = STATUS_NO_MEMORY;
     1233                    if (NT_SUCCESS(rcNt))
     1234                    {
     1235                        /*
     1236                         * Now call the common code to do the real work.
     1237                         */
     1238                        rc = supdrvIOCtl(uCmd, pDevExt, pSession, pHdr);
     1239                        if (RT_SUCCESS(rc))
     1240                        {
     1241                            /*
     1242                             * Copy back the result.
     1243                             */
     1244                            cbOut = pHdr->cbOut;
     1245                            if (cbOut > cbOutput)
     1246                            {
     1247                                cbOut = cbOutput;
     1248                                OSDBGPRINT(("VBoxDrvNtFastIoDeviceControl: too much output! %#x > %#x; uCmd=%#x!\n",
     1249                                            pHdr->cbOut, cbOut, uCmd));
     1250                            }
     1251                            if (cbOut)
     1252                            {
     1253                                __try
     1254                                {
     1255                                    RtlCopyMemory(pvOutput, pHdr, cbOut);
     1256                                    rcNt = STATUS_SUCCESS;
     1257                                }
     1258                                __except(EXCEPTION_EXECUTE_HANDLER)
     1259                                {
     1260                                    rcNt = GetExceptionCode();
     1261                                }
     1262                            }
     1263                            else
     1264                                rcNt = STATUS_SUCCESS;
     1265                        }
     1266                        else if (rc == VERR_INVALID_PARAMETER)
     1267                            rcNt = STATUS_INVALID_PARAMETER;
     1268                        else
     1269                            rcNt = STATUS_NOT_SUPPORTED;
     1270                        Log2(("VBoxDrvNtFastIoDeviceControl: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
     1271                    }
     1272                    ExFreePoolWithTag(pHdr, 'VBox');
     1273                }
     1274                else
     1275                {
     1276                    Log(("VBoxDrvNtFastIoDeviceControl: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n",
     1277                         uCmd, Hdr.cbIn, Hdr.cbOut, cbInput, cbOutput));
     1278                    rcNt = STATUS_INVALID_PARAMETER;
     1279                }
     1280            }
     1281        }
     1282        else
     1283        {
     1284            Log(("VBoxDrvNtFastIoDeviceControl: not buffered request (%#x) - not supported\n", uCmd));
     1285            rcNt = STATUS_NOT_SUPPORTED;
     1286        }
     1287    }
    6571288#ifdef RT_ARCH_AMD64
    6581289    else
     
    6791310NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    6801311{
     1312    VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(pDevObj, pIrp);
     1313
    6811314    PSUPDRVDEVEXT       pDevExt  = SUPDRVNT_GET_DEVEXT(pDevObj);
    6821315    PIO_STACK_LOCATION  pStack   = IoGetCurrentIrpStackLocation(pIrp);
    683     PSUPDRVSESSION      pSession = (PSUPDRVSESSION)pStack->FileObject->FsContext;
     1316    PSUPDRVSESSION      pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
     1317                                                              (PSUPDRVSESSION *)&pStack->FileObject->FsContext);
     1318
     1319    if (!RT_VALID_PTR(pSession))
     1320        return supdrvNtCompleteRequest(STATUS_TRUST_FAILURE, pIrp);
    6841321
    6851322    /*
     
    6871324     * the session and iCmd, and does not return anything.
    6881325     */
    689     ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
    690     if (   (   ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
     1326    if (pSession->fUnrestricted)
     1327    {
     1328#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
     1329        if (supdrvNtIsDebuggerAttached())
     1330        {
     1331            supdrvSessionRelease(pSession);
     1332            return supdrvNtCompleteRequest(STATUS_TRUST_FAILURE, pIrp);
     1333        }
     1334#endif
     1335
     1336        ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
     1337        if (   ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
    6911338            || ulCmd == SUP_IOCTL_FAST_DO_HM_RUN
    6921339            || ulCmd == SUP_IOCTL_FAST_DO_NOP)
    693         && pSession->fUnrestricted == true)
    694     {
    695         int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession);
    696 
    697         /* Complete the I/O request. */
    698         NTSTATUS rcNt = pIrp->IoStatus.Status = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
    699         IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    700         return rcNt;
     1340        {
     1341            int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession);
     1342
     1343            /* Complete the I/O request. */
     1344            supdrvSessionRelease(pSession);
     1345            return supdrvNtCompleteRequest(RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER, pIrp);
     1346        }
    7011347    }
    7021348
     
    7871433    pIrp->IoStatus.Status = rcNt;
    7881434    pIrp->IoStatus.Information = cbOut;
     1435    supdrvSessionRelease(pSession);
    7891436    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    7901437    return rcNt;
     
    8001447NTSTATUS _stdcall VBoxDrvNtInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    8011448{
     1449    VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(pDevObj, pIrp);
     1450
    8021451    PSUPDRVDEVEXT       pDevExt  = SUPDRVNT_GET_DEVEXT(pDevObj);
    8031452    PIO_STACK_LOCATION  pStack   = IoGetCurrentIrpStackLocation(pIrp);
     
    9251574        RTPowerSignalEvent(((unsigned)pArgument2 == 0) ? RTPOWEREVENT_SUSPEND : RTPOWEREVENT_RESUME);
    9261575    }
     1576}
     1577
     1578
     1579/**
     1580 * Called to clean up the session structure before it's freed.
     1581 *
     1582 * @param   pDevExt             The device globals.
     1583 * @param   pSession            The session that's being cleaned up.
     1584 */
     1585void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
     1586{
     1587#ifdef VBOX_WITH_HARDENING
     1588    if (pSession->pNtProtect)
     1589    {
     1590        supdrvNtProtectRelease(pSession->pNtProtect);
     1591        pSession->pNtProtect = NULL;
     1592    }
     1593#endif
     1594}
     1595
     1596
     1597void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     1598{
     1599    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
     1600}
     1601
     1602
     1603void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
     1604{
     1605    NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
    9271606}
    9281607
     
    10821761                    rc = VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND;
    10831762                    break;
    1084                 case    0xC0000428 /* STATUS_INVALID_IMAGE_HASH */ :
     1763                case /* 0xC0000428 */ STATUS_INVALID_IMAGE_HASH:
    10851764                    rc = VERR_LDR_IMAGE_HASH;
    10861765                    break;
    1087                 case    0xC000010E /* STATUS_IMAGE_ALREADY_LOADED */ :
     1766                case /* 0xC000010E */ STATUS_IMAGE_ALREADY_LOADED:
    10881767                    Log(("WARNING: see @bugref{4853} for cause of this failure on Windows 7 x64\n"));
    10891768                    rc = VERR_ALREADY_LOADED;
     
    15092188    }
    15102189
     2190    if (rc < 0)
     2191    {
     2192        if (((uint32_t)rc & UINT32_C(0xffff0000)) == UINT32_C(0xffff0000))
     2193            return (NTSTATUS)( ((uint32_t)rc & UINT32_C(0xffff))
     2194                              | UINT32_C(0xe9860000) ); /* STATUS_SEVERITY_ERROR + C-bit + facility 0x986 */
     2195    }
    15112196    return STATUS_UNSUCCESSFUL;
    15122197}
     
    15472232}
    15482233#endif
     2234
     2235
     2236#ifdef VBOX_WITH_HARDENING
     2237
     2238/** @name Identifying Special Processes: CSRSS.EXE
     2239 * @{ */
     2240
     2241
     2242/**
     2243 * Checks if the process is a system32 process by the given name.
     2244 *
     2245 * @returns true / false.
     2246 * @param   pProcess            The process to check.
     2247 * @param   pszName             The lower case process name (no path!).
     2248 */
     2249static bool supdrvNtProtectIsSystem32ProcessMatch(PEPROCESS pProcess, const char *pszName)
     2250{
     2251    Assert(strlen(pszName) < 16); /* see buffer below */
     2252
     2253    /*
     2254     * This test works on XP+.
     2255     */
     2256    const char *pszImageFile = (const char *)PsGetProcessImageFileName(pProcess);
     2257    if (!pszImageFile)
     2258        return false;
     2259
     2260    if (RTStrICmp(pszImageFile, pszName) != 0)
     2261        return false;
     2262
     2263    /*
     2264     * This test requires a Vista+ API.
     2265     */
     2266    if (g_pfnPsReferenceProcessFilePointer)
     2267    {
     2268        PFILE_OBJECT pFile = NULL;
     2269        NTSTATUS rcNt = g_pfnPsReferenceProcessFilePointer(pProcess, &pFile);
     2270        if (!NT_SUCCESS(rcNt))
     2271            return false;
     2272
     2273        union
     2274        {
     2275            OBJECT_NAME_INFORMATION Info;
     2276            uint8_t        abBuffer[sizeof(g_System32NtPath) + 16 * sizeof(WCHAR)];
     2277        } Buf;
     2278        ULONG cbIgn;
     2279        rcNt = ObQueryNameString(pFile, &Buf.Info, sizeof(Buf) - sizeof(WCHAR), &cbIgn);
     2280        ObDereferenceObject(pFile);
     2281        if (!NT_SUCCESS(rcNt))
     2282            return false;
     2283
     2284        /* Terminate the name. */
     2285        PRTUTF16 pwszName = Buf.Info.Name.Buffer;
     2286        pwszName[Buf.Info.Name.Length / sizeof(RTUTF16)] = '\0';
     2287
     2288        /* Match the name against the system32 directory path. */
     2289        uint32_t cbSystem32 = g_System32NtPath.UniStr.Length;
     2290        if (Buf.Info.Name.Length < cbSystem32)
     2291            return false;
     2292        if (memcmp(pwszName, g_System32NtPath.UniStr.Buffer, cbSystem32))
     2293            return false;
     2294        pwszName += cbSystem32 / sizeof(RTUTF16);
     2295        if (*pwszName++ != '\\')
     2296            return false;
     2297
     2298        /* Compare the name. */
     2299        const char *pszRight = pszName;
     2300        for (;;)
     2301        {
     2302            WCHAR wchLeft = *pwszName++;
     2303            char  chRight = *pszRight++;
     2304            Assert(chRight == RT_C_TO_LOWER(chRight));
     2305
     2306            if (   wchLeft != chRight
     2307                && RT_C_TO_LOWER(wchLeft) != chRight)
     2308                return false;
     2309            if (!chRight)
     2310                break;
     2311        }
     2312    }
     2313
     2314    return true;
     2315}
     2316
     2317
     2318/**
     2319 * Checks if the current process is likely to be CSRSS.
     2320 *
     2321 * @returns true/false.
     2322 * @param   pProcess        The process.
     2323 */
     2324static bool supdrvNtProtectIsCsrssByProcess(PEPROCESS pProcess)
     2325{
     2326    /*
     2327     * On Windows 8.1 CSRSS.EXE is a protected process.
     2328     */
     2329    if (g_pfnPsIsProtectedProcessLight)
     2330    {
     2331        if (!g_pfnPsIsProtectedProcessLight(pProcess))
     2332            return false;
     2333    }
     2334
     2335    /*
     2336     * The name tests.
     2337     */
     2338    if (!supdrvNtProtectIsSystem32ProcessMatch(pProcess, "csrss.exe"))
     2339        return false;
     2340
     2341    /** @todo Could extend the CSRSS.EXE check with that the TokenUser of the
     2342     *        current process must be "NT AUTHORITY\SYSTEM" (S-1-5-18). */
     2343
     2344    return true;
     2345}
     2346
     2347
     2348/**
     2349 * Called in the context of VBoxDrvNtCreate to determin the CSRSS for the
     2350 * current process.
     2351 *
     2352 * The Client/Server Runtime Subsystem (CSRSS) process needs to be allowed some
     2353 * additional access right so we need to make 101% sure we correctly identify
     2354 * the CSRSS process a process is associated with.
     2355 *
     2356 * @returns IPRT status code.
     2357 * @param   pNtProtect          The NT protected process structure. The
     2358 *                              hCsrssPid member will be updated on success.
     2359 */
     2360static int supdrvNtProtectFindAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect)
     2361{
     2362    Assert(pNtProtect->AvlCore.Key == PsGetCurrentProcessId());
     2363    Assert(pNtProtect->pCsrssProcess == NULL);
     2364    Assert(pNtProtect->hCsrssPid == NULL);
     2365
     2366    /*
     2367     * We'll try use the ApiPort LPC object for the session we're in to track
     2368     * down the CSRSS process. So, we start by constructing a path to it.
     2369     */
     2370    int rc;
     2371    uint32_t    uSessionId = PsGetProcessSessionId(PsGetCurrentProcess());
     2372    WCHAR       wszApiPort[48];
     2373    if (uSessionId == 0)
     2374        rc = RTUtf16CopyAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Windows\\ApiPort");
     2375    else
     2376    {
     2377        char szTmp[64];
     2378        ssize_t cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), uSessionId, 10, 0, 0, 0);
     2379        AssertReturn(cchTmp > 0, (int)cchTmp);
     2380        rc = RTUtf16CopyAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Sessions\\");
     2381        if (RT_SUCCESS(rc))
     2382            rc = RTUtf16CatAscii(wszApiPort, RT_ELEMENTS(wszApiPort), szTmp);
     2383        if (RT_SUCCESS(rc))
     2384            rc = RTUtf16CatAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Windows\\ApiPort");
     2385    }
     2386    AssertRCReturn(rc, rc);
     2387
     2388    UNICODE_STRING ApiPortStr;
     2389    ApiPortStr.Buffer = wszApiPort;
     2390    ApiPortStr.Length = (USHORT)(RTUtf16Len(wszApiPort) * sizeof(RTUTF16));
     2391    ApiPortStr.MaximumLength = ApiPortStr.Length + sizeof(RTUTF16);
     2392
     2393    /*
     2394     * The object cannot be opened, but we can reference it by name.
     2395     */
     2396    void *pvApiPortObj = NULL;
     2397    NTSTATUS rcNt = ObReferenceObjectByName(&ApiPortStr,
     2398                                            0,
     2399                                            NULL /*pAccessState*/,
     2400                                            STANDARD_RIGHTS_READ,
     2401                                            *LpcPortObjectType,
     2402                                            KernelMode,
     2403                                            NULL /*pvParseContext*/,
     2404                                            &pvApiPortObj);
     2405    if (!NT_SUCCESS(rcNt))
     2406    {
     2407        SUPR0Printf("vboxdrv: Error opening '%ls': %#x\n", wszApiPort, rcNt);
     2408        return VERR_SUPDRV_APIPORT_OPEN_ERROR;
     2409    }
     2410
     2411    /*
     2412     * Query the processes in the system so we can locate CSRSS.EXE candidates.
     2413     * Note! Attempts at using SystemSessionProcessInformation failed with
     2414     *       STATUS_ACCESS_VIOLATION.
     2415     */
     2416    ULONG       cbNeeded = _64K;
     2417    uint32_t    cbBuf;
     2418    uint8_t    *pbBuf = NULL;
     2419    do
     2420    {
     2421        cbBuf = RT_ALIGN(cbNeeded + _4K, _64K);
     2422        pbBuf = (uint8_t *)RTMemAlloc(cbBuf);
     2423        if (!pbBuf)
     2424            break;
     2425
     2426        cbNeeded = 0;
     2427#if 0 /* doesn't work. */
     2428        SYSTEM_SESSION_PROCESS_INFORMATION Req;
     2429        Req.SessionId    = uSessionId;
     2430        Req.BufferLength = cbBuf;
     2431        Req.Buffer       = pbBuf;
     2432        rcNt = NtQuerySystemInformation(SystemSessionProcessInformation, &Req, sizeof(Req), &cbNeeded);
     2433#else
     2434        rcNt = NtQuerySystemInformation(SystemProcessInformation, pbBuf, cbBuf, &cbNeeded);
     2435#endif
     2436        if (NT_SUCCESS(rcNt))
     2437            break;
     2438
     2439        RTMemFree(pbBuf);
     2440        pbBuf = NULL;
     2441    } while (   rcNt == STATUS_INFO_LENGTH_MISMATCH
     2442             && cbNeeded > cbBuf
     2443             && cbNeeded < 32U*_1M);
     2444
     2445    if (   pbBuf
     2446        && NT_SUCCESS(rcNt)
     2447        && cbNeeded >= sizeof(SYSTEM_PROCESS_INFORMATION))
     2448    {
     2449        /*
     2450         * Walk the returned data and look for the process associated with the
     2451         * ApiPort object.  The ApiPort object keeps the EPROCESS address of
     2452         * the owner process (i.e. CSRSS) relatively early in the structure. On
     2453         * 64-bit windows 8.1 it's at offset 0x18.  So, obtain the EPROCESS
     2454         * pointer to likely CSRSS processes and check for a match in the first
     2455         * 0x40 bytes of the ApiPort object.
     2456         */
     2457        rc = VERR_SUPDRV_CSRSS_NOT_FOUND;
     2458        for (uint32_t offBuf = 0; offBuf <= cbNeeded - sizeof(SYSTEM_PROCESS_INFORMATION);)
     2459        {
     2460            PRTNT_SYSTEM_PROCESS_INFORMATION pProcInfo = (PRTNT_SYSTEM_PROCESS_INFORMATION)&pbBuf[offBuf];
     2461            if (   pProcInfo->ProcessName.Length == 9 * sizeof(WCHAR)
     2462                && pProcInfo->NumberOfThreads > 2   /* Very low guess. */
     2463                && pProcInfo->HandleCount     > 32  /* Very low guess, I hope. */
     2464                && (uintptr_t)pProcInfo->ProcessName.Buffer - (uintptr_t)pbBuf < cbNeeded
     2465                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[0]) == 'c'
     2466                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[1]) == 's'
     2467                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[2]) == 'r'
     2468                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[3]) == 's'
     2469                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[4]) == 's'
     2470                &&               pProcInfo->ProcessName.Buffer[5]  == '.'
     2471                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[6]) == 'e'
     2472                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[7]) == 'x'
     2473                && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[8]) == 'e' )
     2474            {
     2475
     2476                /* Get the process structure and perform some more thorough
     2477                   process checks. */
     2478                PEPROCESS pProcess;
     2479                rcNt = PsLookupProcessByProcessId(pProcInfo->UniqueProcessId, &pProcess);
     2480                if (NT_SUCCESS(rcNt))
     2481                {
     2482                    if (supdrvNtProtectIsCsrssByProcess(pProcess))
     2483                    {
     2484                        if (PsGetProcessSessionId(pProcess) == uSessionId)
     2485                        {
     2486                            /* Final test, check the ApiPort.
     2487                               Note! The old LPC (pre Vista) objects has the PID
     2488                                     much earlier in the structure.  Might be
     2489                                     worth looking for it instead. */
     2490                            bool fThatsIt = false;
     2491                            __try
     2492                            {
     2493                                PEPROCESS *ppPortProc = (PEPROCESS *)pvApiPortObj;
     2494                                uint32_t   cTests = g_uNtVerCombined >= SUP_NT_VER_VISTA ? 16 : 38; /* ALPC since Vista. */
     2495                                do
     2496                                {
     2497                                    fThatsIt = *ppPortProc == pProcess;
     2498                                    ppPortProc++;
     2499                                } while (!fThatsIt && --cTests > 0);
     2500                            }
     2501                            __except(EXCEPTION_EXECUTE_HANDLER)
     2502                            {
     2503                                fThatsIt = false;
     2504                            }
     2505                            if (fThatsIt)
     2506                            {
     2507                                /* Ok, we found it!  Keep the process structure
     2508                                   reference as well as the PID so we can
     2509                                   safely identify it later on.  */
     2510                                pNtProtect->hCsrssPid     = pProcInfo->UniqueProcessId;
     2511                                pNtProtect->pCsrssProcess = pProcess;
     2512                                rc = VINF_SUCCESS;
     2513                                break;
     2514                            }
     2515                        }
     2516                    }
     2517
     2518                    ObDereferenceObject(pProcess);
     2519                }
     2520            }
     2521
     2522            /* Advance. */
     2523            if (!pProcInfo->NextEntryOffset)
     2524                break;
     2525            offBuf += pProcInfo->NextEntryOffset;
     2526        }
     2527    }
     2528    else
     2529        rc = VERR_SUPDRV_SESSION_PROCESS_ENUM_ERROR;
     2530    RTMemFree(pbBuf);
     2531    ObDereferenceObject(pvApiPortObj);
     2532    return rc;
     2533}
     2534
     2535
     2536/**
     2537 * Checks that the given process is the CSRSS process associated with protected
     2538 * process.
     2539 *
     2540 * @returns true / false.
     2541 * @param   pNtProtect          The NT protection structure.
     2542 * @param   pCsrss              The process structure of the alleged CSRSS.EXE
     2543 *                              process.
     2544 */
     2545static bool supdrvNtProtectIsAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect, PEPROCESS pCsrss)
     2546{
     2547    if (pNtProtect->pCsrssProcess == pCsrss)
     2548    {
     2549        if (pNtProtect->hCsrssPid == PsGetProcessId(pCsrss))
     2550        {
     2551            return true;
     2552        }
     2553    }
     2554    return false;
     2555}
     2556
     2557
     2558/**
     2559 * Checks if the given process is the stupid themes service.
     2560 *
     2561 * The caller does some screening of access masks and what not. We do the rest.
     2562 *
     2563 * @returns true / false.
     2564 * @param   pNtProtect          The NT protection structure.
     2565 * @param   pAnnoyingProcess    The process structure of an process that might
     2566 *                              happen to be the annoying themes process.
     2567 */
     2568static bool supdrvNtProtectIsFrigginThemesService(PSUPDRVNTPROTECT pNtProtect, PEPROCESS pAnnoyingProcess)
     2569{
     2570    /*
     2571     * Check the process name.
     2572     */
     2573    if (!supdrvNtProtectIsSystem32ProcessMatch(pAnnoyingProcess, "svchost.exe"))
     2574        return false;
     2575
     2576    /** @todo Come up with more checks. */
     2577
     2578    return true;
     2579}
     2580
     2581
     2582/** @} */
     2583
     2584
     2585/** @name Process Creation Callbacks.
     2586 * @{ */
     2587
     2588/**
     2589 * Common worker used by the process creation hooks as well as the process
     2590 * handle creation hooks to check if a VM process is being created.
     2591 *
     2592 * @returns true if likely to be a VM process, false if not.
     2593 * @param   pNtStub             The NT protection structure for the possible
     2594 *                              stub process.
     2595 * @param   hParentPid          The parent pid.
     2596 * @param   hChildPid           The child pid.
     2597 */
     2598static bool supdrvNtProtectIsSpawningStubProcess(PSUPDRVNTPROTECT pNtStub, HANDLE hParentPid, HANDLE hChildPid)
     2599{
     2600    bool fRc = false;
     2601    if (pNtStub->AvlCore.Key == hParentPid) /* paranoia */
     2602    {
     2603        if (pNtStub->enmProcessKind == kSupDrvNtProtectKind_StubSpawning)
     2604        {
     2605            /* Compare short names. */
     2606            PEPROCESS pStubProcess;
     2607            NTSTATUS rcNt = PsLookupProcessByProcessId(hParentPid, &pStubProcess);
     2608            if (NT_SUCCESS(rcNt))
     2609            {
     2610                PEPROCESS pChildProcess;
     2611                rcNt = PsLookupProcessByProcessId(hChildPid, &pChildProcess);
     2612                if (NT_SUCCESS(rcNt))
     2613                {
     2614                    const char *pszStub  = (const char *)PsGetProcessImageFileName(pStubProcess);
     2615                    const char *pszChild = (const char *)PsGetProcessImageFileName(pChildProcess);
     2616                    fRc = pszStub != NULL
     2617                       && pszChild != NULL
     2618                       && strcmp(pszStub, pszChild) == 0;
     2619
     2620                    /** @todo check that the full image names matches. */
     2621
     2622                    ObDereferenceObject(pChildProcess);
     2623                }
     2624                ObDereferenceObject(pStubProcess);
     2625            }
     2626        }
     2627    }
     2628    return fRc;
     2629}
     2630
     2631
     2632/**
     2633 * Common code used by the notifies to protect a child process.
     2634 *
     2635 * @returns VBox status code.
     2636 * @param   pNtStub             The NT protect structure for the parent.
     2637 * @param   hChildPid           The child pid.
     2638 */
     2639static int supdrvNtProtectProtectNewStubChild(PSUPDRVNTPROTECT pNtParent, HANDLE hChildPid)
     2640{
     2641    /*
     2642     * Create a child protection struction.
     2643     */
     2644    PSUPDRVNTPROTECT pNtChild;
     2645    int rc = supdrvNtProtectCreate(&pNtChild, hChildPid, kSupDrvNtProtectKind_VmProcessUnconfirmed, false /*fLink*/);
     2646    if (RT_SUCCESS(rc))
     2647    {
     2648        pNtChild->fFirstProcessCreateHandle = true;
     2649        pNtChild->fFirstThreadCreateHandle = true;
     2650        pNtChild->fCsrssFirstProcessCreateHandle = true;
     2651        pNtChild->fCsrssFirstProcessDuplicateHandle = true;
     2652        pNtChild->fThemesFirstProcessCreateHandle = true;
     2653        pNtChild->hParentPid = pNtParent->AvlCore.Key;
     2654        pNtChild->hCsrssPid = pNtParent->hCsrssPid;
     2655        pNtChild->pCsrssProcess = pNtParent->pCsrssProcess;
     2656        if (pNtChild->pCsrssProcess)
     2657            ObReferenceObject(pNtChild->pCsrssProcess);
     2658
     2659        /*
     2660         * Take the spinlock, recheck parent conditions and link things.
     2661         */
     2662        RTSpinlockAcquire(g_hNtProtectLock);
     2663        if (pNtParent->enmProcessKind == kSupDrvNtProtectKind_StubSpawning)
     2664        {
     2665            bool fSuccess = RTAvlPVInsert(&g_NtProtectTree, &pNtChild->AvlCore);
     2666            if (fSuccess)
     2667            {
     2668                pNtParent->u.pChild       = pNtChild; /* Parent keeps the initial reference. */
     2669                pNtParent->enmProcessKind = kSupDrvNtProtectKind_StubParent;
     2670                pNtChild->u.pParent       = pNtParent;
     2671
     2672                RTSpinlockRelease(g_hNtProtectLock);
     2673                return VINF_SUCCESS;
     2674            }
     2675
     2676            rc = VERR_INTERNAL_ERROR_2;
     2677        }
     2678        else
     2679            rc = VERR_WRONG_ORDER;
     2680        RTSpinlockRelease(g_hNtProtectLock);
     2681
     2682        supdrvNtProtectRelease(pNtChild);
     2683    }
     2684    return rc;
     2685}
     2686
     2687
     2688/**
     2689 * Common process termination code.
     2690 *
     2691 * Transitions protected process to the dead states, protecting against handle
     2692 * PID reuse (esp. with unconfirmed VM processes) and handle cleanup issues.
     2693 *
     2694 * @param   hDeadPid            The PID of the dead process.
     2695 */
     2696static void supdrvNtProtectUnprotectDeadProcess(HANDLE hDeadPid)
     2697{
     2698    PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(hDeadPid);
     2699    if (pNtProtect)
     2700    {
     2701        PSUPDRVNTPROTECT pNtChild = NULL;
     2702
     2703        RTSpinlockAcquire(g_hNtProtectLock);
     2704
     2705        /*
     2706         * If this is an unconfirmed VM process, we must release the reference
     2707         * the parent structure holds.
     2708         */
     2709        if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
     2710        {
     2711            PSUPDRVNTPROTECT pNtParent = pNtProtect->u.pParent;
     2712            AssertRelease(pNtParent); AssertRelease(pNtParent->u.pChild == pNtProtect);
     2713            pNtParent->u.pChild   = NULL;
     2714            pNtProtect->u.pParent = NULL;
     2715            pNtChild = pNtProtect;
     2716        }
     2717        /*
     2718         * If this is a stub exitting before the VM process gets confirmed,
     2719         * release the protection of the potential VM process as this is not
     2720         * the prescribed behavior.
     2721         */
     2722        else if (   pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent
     2723                 && pNtProtect->u.pChild)
     2724        {
     2725            pNtChild = pNtProtect->u.pChild;
     2726            pNtProtect->u.pChild = NULL;
     2727            pNtChild->u.pParent  = NULL;
     2728            pNtChild->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
     2729        }
     2730
     2731        /*
     2732         * Transition it to the dead state to prevent it from opening the
     2733         * support driver again or be posthumously abused as a vm process parent.
     2734         */
     2735        if (   pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
     2736            || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessConfirmed)
     2737            pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
     2738        else if (   pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent
     2739                 || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubSpawning
     2740                 || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubUnverified)
     2741            pNtProtect->enmProcessKind = kSupDrvNtProtectKind_StubDead;
     2742
     2743        RTSpinlockRelease(g_hNtProtectLock);
     2744
     2745        supdrvNtProtectRelease(pNtProtect);
     2746        supdrvNtProtectRelease(pNtChild);
     2747
     2748        /*
     2749         * Do session cleanups.
     2750         */
     2751        AssertReturnVoid((HANDLE)(uintptr_t)RTProcSelf() == hDeadPid);
     2752        if (g_pDevObjSys)
     2753        {
     2754            PSUPDRVDEVEXT  pDevExt  = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
     2755            PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, (RTPROCESS)(uintptr_t)hDeadPid,
     2756                                                                 RTR0ProcHandleSelf(), NULL);
     2757            if (pSession)
     2758            {
     2759                supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
     2760                supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
     2761            }
     2762        }
     2763    }
     2764}
     2765
     2766
     2767/**
     2768 * Common worker for the process creation callback that verifies a new child
     2769 * being created by the handle creation callback code.
     2770 *
     2771 * @param   pNtStub         The parent.
     2772 * @param   pNtVm           The child.
     2773 * @param   fCallerChecks   The result of any additional tests the caller made.
     2774 *                          This is in order to avoid duplicating the failure
     2775 *                          path code.
     2776 */
     2777static void supdrvNtProtectVerifyNewChildProtection(PSUPDRVNTPROTECT pNtStub, PSUPDRVNTPROTECT pNtVm, bool fCallerChecks)
     2778{
     2779    if (   fCallerChecks
     2780        && pNtStub->enmProcessKind == kSupDrvNtProtectKind_StubParent
     2781        && pNtVm->enmProcessKind   == kSupDrvNtProtectKind_VmProcessUnconfirmed
     2782        && pNtVm->u.pParent        == pNtStub
     2783        && pNtStub->u.pChild       == pNtVm)
     2784    {
     2785        /* Fine, nothing to do. */
     2786        return;
     2787    }
     2788
     2789    LogRel(("vboxdrv: Misdetected vm stub; hParentPid=%p hChildPid=%p\n", pNtStub->AvlCore.Key, pNtVm->AvlCore.Key));
     2790    if (pNtStub->enmProcessKind != kSupDrvNtProtectKind_VmProcessConfirmed)
     2791        supdrvNtProtectUnprotectDeadProcess(pNtVm->AvlCore.Key);
     2792}
     2793
     2794
     2795/**
     2796 * Old style callback (since forever).
     2797 *
     2798 * @param   hParentPid          The parent PID.
     2799 * @param   hNewPid             The PID of the new child.
     2800 * @param   fCreated            TRUE if it's a creation notification,
     2801 *                              FALSE if termination.
     2802 * @remarks ASSUMES this arrives before the handle creation callback.
     2803 */
     2804static VOID __stdcall
     2805supdrvNtProtectCallback_ProcessCreateNotify(HANDLE hParentPid, HANDLE hNewPid, BOOLEAN fCreated)
     2806{
     2807    /*
     2808     * Is it a new process that needs protection?
     2809     */
     2810    if (fCreated)
     2811    {
     2812        PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(hParentPid);
     2813        if (pNtStub)
     2814        {
     2815            PSUPDRVNTPROTECT pNtVm = supdrvNtProtectLookup(hNewPid);
     2816            if (!pNtVm)
     2817            {
     2818                if (supdrvNtProtectIsSpawningStubProcess(pNtStub, hParentPid, hNewPid))
     2819                    supdrvNtProtectProtectNewStubChild(pNtStub, hNewPid);
     2820            }
     2821            else
     2822            {
     2823                supdrvNtProtectVerifyNewChildProtection(pNtStub, pNtVm, true);
     2824                supdrvNtProtectRelease(pNtVm);
     2825            }
     2826            supdrvNtProtectRelease(pNtStub);
     2827        }
     2828    }
     2829    /*
     2830     * Process termination, do clean ups.
     2831     */
     2832    else
     2833        supdrvNtProtectUnprotectDeadProcess(hNewPid);
     2834}
     2835
     2836
     2837/**
     2838 * New style callback (Vista SP1+ / w2k8).
     2839 *
     2840 * @param   pNewProcess         The new process.
     2841 * @param   hNewPid             The PID of the new process.
     2842 * @param   pInfo               Process creation details. NULL if process
     2843 *                              termination notification.
     2844 * @remarks ASSUMES this arrives before the handle creation callback.
     2845 */
     2846static VOID __stdcall
     2847supdrvNtProtectCallback_ProcessCreateNotifyEx(PEPROCESS pNewProcess, HANDLE hNewPid, PPS_CREATE_NOTIFY_INFO pInfo)
     2848{
     2849    /*
     2850     * Is it a new process that needs protection?
     2851     */
     2852    if (pInfo)
     2853    {
     2854        PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(pInfo->CreatingThreadId.UniqueProcess);
     2855
     2856        Log(("vboxdrv/NewProcessEx: ctx=%04zx/%p pid=%04zx ppid=%04zx ctor=%04zx/%04zx rcNt=%#x %.*ls\n",
     2857             PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     2858             hNewPid, pInfo->ParentProcessId,
     2859             pInfo->CreatingThreadId.UniqueProcess, pInfo->CreatingThreadId.UniqueThread, pInfo->CreationStatus,
     2860             pInfo->FileOpenNameAvailable && pInfo->ImageFileName ? (size_t)pInfo->ImageFileName->Length / 2 : 0,
     2861             pInfo->FileOpenNameAvailable && pInfo->ImageFileName ? pInfo->ImageFileName->Buffer : NULL));
     2862
     2863        if (pNtStub)
     2864        {
     2865            PSUPDRVNTPROTECT pNtVm = supdrvNtProtectLookup(hNewPid);
     2866            if (!pNtVm)
     2867            {
     2868                /* Parent must be creator. */
     2869                if (pInfo->CreatingThreadId.UniqueProcess == pInfo->ParentProcessId)
     2870                {
     2871                    if (supdrvNtProtectIsSpawningStubProcess(pNtStub, pInfo->ParentProcessId, hNewPid))
     2872                        supdrvNtProtectProtectNewStubChild(pNtStub, hNewPid);
     2873                }
     2874            }
     2875            else
     2876            {
     2877                /* Parent must be creator (as above). */
     2878                supdrvNtProtectVerifyNewChildProtection(pNtStub, pNtVm,
     2879                                                        pInfo->CreatingThreadId.UniqueProcess == pInfo->ParentProcessId);
     2880                supdrvNtProtectRelease(pNtVm);
     2881            }
     2882            supdrvNtProtectRelease(pNtStub);
     2883        }
     2884    }
     2885    /*
     2886     * Process termination, do clean ups.
     2887     */
     2888    else
     2889        supdrvNtProtectUnprotectDeadProcess(hNewPid);
     2890}
     2891
     2892/** @} */
     2893
     2894
     2895/** @name Process Handle Callbacks.
     2896 * @{ */
     2897
     2898/** Process rights that we allow for handles to stub and VM processes. */
     2899# define SUPDRV_NT_ALLOW_PROCESS_RIGHTS  \
     2900    (  PROCESS_TERMINATE \
     2901     | PROCESS_VM_READ \
     2902     | PROCESS_QUERY_INFORMATION \
     2903     | PROCESS_QUERY_LIMITED_INFORMATION \
     2904     | PROCESS_SUSPEND_RESUME \
     2905     | DELETE \
     2906     | READ_CONTROL \
     2907     | SYNCHRONIZE)
     2908
     2909/** Evil process rights. */
     2910# define SUPDRV_NT_EVIL_PROCESS_RIGHTS  \
     2911    (  PROCESS_CREATE_THREAD \
     2912     | PROCESS_SET_SESSIONID /*?*/ \
     2913     | PROCESS_VM_OPERATION \
     2914     | PROCESS_VM_WRITE \
     2915     | PROCESS_DUP_HANDLE \
     2916     | PROCESS_CREATE_PROCESS /*?*/ \
     2917     | PROCESS_SET_QUOTA /*?*/ \
     2918     | PROCESS_SET_INFORMATION \
     2919     | PROCESS_SET_LIMITED_INFORMATION /*?*/ \
     2920     | 0)
     2921AssertCompile((SUPDRV_NT_ALLOW_PROCESS_RIGHTS & SUPDRV_NT_EVIL_PROCESS_RIGHTS) == 0);
     2922
     2923
     2924static OB_PREOP_CALLBACK_STATUS __stdcall
     2925supdrvNtProtectCallback_ProcessHandlePre(PVOID pvUser, POB_PRE_OPERATION_INFORMATION pOpInfo)
     2926{
     2927    Assert(pvUser == NULL);
     2928    Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
     2929    Assert(pOpInfo->ObjectType == *PsProcessType);
     2930
     2931    /*
     2932     * Protected?  Kludge required for NtOpenProcess calls comming in before
     2933     * the create process hook triggers on Windows 8.1 (possibly others too).
     2934     */
     2935    HANDLE           hObjPid    = PsGetProcessId((PEPROCESS)pOpInfo->Object);
     2936    PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(hObjPid);
     2937    if (!pNtProtect)
     2938    {
     2939        HANDLE           hParentPid = PsGetProcessInheritedFromUniqueProcessId((PEPROCESS)pOpInfo->Object);
     2940        PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(hParentPid);
     2941        if (pNtStub)
     2942        {
     2943            if (supdrvNtProtectIsSpawningStubProcess(pNtStub, hParentPid, hObjPid))
     2944            {
     2945                supdrvNtProtectProtectNewStubChild(pNtStub, hObjPid);
     2946                pNtProtect = supdrvNtProtectLookup(hObjPid);
     2947            }
     2948            supdrvNtProtectRelease(pNtStub);
     2949        }
     2950    }
     2951    pOpInfo->CallContext = pNtProtect; /* Just for reference. */
     2952    if (pNtProtect)
     2953    {
     2954        /*
     2955         * Ok, it's a protected process.  Strip rights as required or possible.
     2956         */
     2957        static ACCESS_MASK const s_fCsrssStupidDesires = 0x1fffff;
     2958        ACCESS_MASK fAllowedRights = SUPDRV_NT_ALLOW_PROCESS_RIGHTS;
     2959
     2960        if (pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE)
     2961        {
     2962            /* Don't restrict the process accessing itself. */
     2963            if ((PEPROCESS)pOpInfo->Object == PsGetCurrentProcess())
     2964            {
     2965                pOpInfo->CallContext = NULL; /* don't assert */
     2966                pNtProtect->fFirstProcessCreateHandle = false;
     2967
     2968                Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] %s\n",
     2969                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     2970                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
     2971                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
     2972                     PsGetProcessImageFileName(PsGetCurrentProcess()) ));
     2973            }
     2974            else
     2975            {
     2976                /* Special case 1 on Vista, 7 & 8:
     2977                   The CreateProcess code passes the handle over to CSRSS.EXE
     2978                   and the code inBaseSrvCreateProcess will duplicate the
     2979                   handle with 0x1fffff as access mask.  NtDuplicateObject will
     2980                   fail this call before it ever gets down here.
     2981
     2982                   Special case 2 on 8.1:
     2983                   The CreateProcess code requires additional rights for
     2984                   something, we'll drop these in the stub code. */
     2985                if (   pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
     2986                    && pNtProtect->fFirstProcessCreateHandle
     2987                    && pNtProtect->hParentPid == PsGetProcessId(PsGetCurrentProcess()))
     2988                {
     2989                    if (   !pOpInfo->KernelHandle
     2990                        && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
     2991                    {
     2992                        if (g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3))
     2993                            fAllowedRights |= s_fCsrssStupidDesires;
     2994                        else
     2995                            fAllowedRights = fAllowedRights
     2996                                           | PROCESS_VM_OPERATION
     2997                                           | PROCESS_VM_WRITE
     2998                                           | PROCESS_SET_INFORMATION
     2999                                           | PROCESS_SET_LIMITED_INFORMATION
     3000                                           | 0;
     3001                        pOpInfo->CallContext = NULL; /* don't assert this. */
     3002                    }
     3003                    pNtProtect->fFirstProcessCreateHandle = false;
     3004                }
     3005
     3006                /* Special case 3 on 8.1:
     3007                   The interaction between the CreateProcess code and CSRSS.EXE
     3008                   has changed to the better with Windows 8.1.  CSRSS.EXE no
     3009                   longer duplicates the process (thread too) handle, but opens
     3010                   it, thus allowing us to do our job. */
     3011                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)
     3012                    && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
     3013                    && pNtProtect->fCsrssFirstProcessCreateHandle
     3014                    && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess())
     3015                   )
     3016                {
     3017                    pNtProtect->fCsrssFirstProcessCreateHandle = false;
     3018                    if (pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
     3019                    {
     3020                        /* Not needed: PROCESS_CREATE_THREAD, PROCESS_SET_SESSIONID,
     3021                           PROCESS_CREATE_PROCESS */
     3022                        fAllowedRights = fAllowedRights
     3023                                       | PROCESS_VM_OPERATION
     3024                                       | PROCESS_VM_WRITE
     3025                                       | PROCESS_DUP_HANDLE /* Needed for CreateProcess/VBoxTestOGL. */
     3026                                       | 0;
     3027                        pOpInfo->CallContext = NULL; /* don't assert this. */
     3028                    }
     3029                }
     3030
     3031                /* Special case 4, Windows 7, Vista, possibly 8, but not 8.1:
     3032                   The Themes service requires PROCESS_DUP_HANDLE access to our
     3033                   process or we won't get any menus and dialogs will be half
     3034                   unreadable.  This is _very_ unfortunate and more work will
     3035                   go into making this more secure.  */
     3036                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)
     3037                    && g_uNtVerCombined  < SUP_MAKE_NT_VER_SIMPLE(6, 2)
     3038                    && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == 0x1478 /* 6.1.7600.16385 (win7_rtm.090713-1255) */
     3039                    && pNtProtect->fThemesFirstProcessCreateHandle
     3040                    && supdrvNtProtectIsFrigginThemesService(pNtProtect, PsGetCurrentProcess()))
     3041                {
     3042                    pNtProtect->fThemesFirstProcessCreateHandle = true; /* Only once! */
     3043                    fAllowedRights |= PROCESS_DUP_HANDLE;
     3044                    pOpInfo->CallContext = NULL; /* don't assert this. */
     3045                }
     3046
     3047                Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p wants %#x to %p/pid=%04zx [%d], allow %#x => %#x; %s\n",
     3048                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3049                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
     3050                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
     3051                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess & fAllowedRights,
     3052                     PsGetProcessImageFileName(PsGetCurrentProcess())));
     3053
     3054                pOpInfo->Parameters->CreateHandleInformation.DesiredAccess &= fAllowedRights;
     3055            }
     3056        }
     3057        else
     3058        {
     3059            /* Don't restrict the process accessing itself. */
     3060            if (   (PEPROCESS)pOpInfo->Object == PsGetCurrentProcess()
     3061                && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == pOpInfo->Object)
     3062            {
     3063                Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
     3064                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3065                     pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
     3066                     PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
     3067                     pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
     3068                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
     3069                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
     3070                     PsGetProcessImageFileName(PsGetCurrentProcess()) ));
     3071
     3072                pOpInfo->CallContext = NULL; /* don't assert */
     3073            }
     3074            else
     3075            {
     3076                /* Special case 5 on Vista, 7 & 8:
     3077                   This is the CSRSS.EXE end of special case #1. */
     3078                if (   g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3)
     3079                    && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
     3080                    && pNtProtect->fCsrssFirstProcessDuplicateHandle
     3081                    &&    pNtProtect->hParentPid
     3082                       == PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess)
     3083                    && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == PsGetCurrentProcess()
     3084                    && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess())
     3085                   )
     3086                {
     3087                    pNtProtect->fCsrssFirstProcessDuplicateHandle = false;
     3088                    if (pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
     3089                    {
     3090                        /* Not needed: PROCESS_CREATE_THREAD, PROCESS_SET_SESSIONID,
     3091                           PROCESS_CREATE_PROCESS, PROCESS_DUP_HANDLE */
     3092                        fAllowedRights = fAllowedRights
     3093                                       | PROCESS_VM_OPERATION
     3094                                       | PROCESS_VM_WRITE
     3095                                       | PROCESS_DUP_HANDLE /* Needed for launching VBoxTestOGL. */
     3096                                       | 0;
     3097                        pOpInfo->CallContext = NULL; /* don't assert this. */
     3098                    }
     3099                }
     3100
     3101                Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
     3102                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3103                     pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
     3104                     PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
     3105                     pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
     3106                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
     3107                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
     3108                     PsGetProcessImageFileName(PsGetCurrentProcess()) ));
     3109
     3110                pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess &= fAllowedRights;
     3111            }
     3112        }
     3113        supdrvNtProtectRelease(pNtProtect);
     3114    }
     3115
     3116    return OB_PREOP_SUCCESS;
     3117}
     3118
     3119
     3120static VOID __stdcall
     3121supdrvNtProtectCallback_ProcessHandlePost(PVOID pvUser, POB_POST_OPERATION_INFORMATION pOpInfo)
     3122{
     3123    Assert(pvUser == NULL);
     3124    Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
     3125    Assert(pOpInfo->ObjectType == *PsProcessType);
     3126
     3127    if (   pOpInfo->CallContext
     3128        && NT_SUCCESS(pOpInfo->ReturnStatus))
     3129    {
     3130        ACCESS_MASK const fGrantedAccess = pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE
     3131                                         ? pOpInfo->Parameters->CreateHandleInformation.GrantedAccess
     3132                                         : pOpInfo->Parameters->DuplicateHandleInformation.GrantedAccess;
     3133        AssertReleaseMsg(   !(fGrantedAccess & ~(  SUPDRV_NT_ALLOW_PROCESS_RIGHTS
     3134                                                 | WRITE_OWNER | WRITE_DAC /* these two might be forced upon us */
     3135                                                 | PROCESS_UNKNOWN_4000 /* Seen set on win 8.1 */
     3136                                                 /*| PROCESS_UNKNOWN_8000 */ ) )
     3137                         || pOpInfo->KernelHandle,
     3138                         ("GrantedAccess=%#x - we allow %#x - we did not allow %#x\n",
     3139                          fGrantedAccess, SUPDRV_NT_ALLOW_PROCESS_RIGHTS, fGrantedAccess & ~SUPDRV_NT_ALLOW_PROCESS_RIGHTS));
     3140    }
     3141}
     3142
     3143# undef SUPDRV_NT_ALLOW_PROCESS_RIGHTS
     3144
     3145/** @} */
     3146
     3147
     3148/** @name Thread Handle Callbacks
     3149 * @{ */
     3150
     3151/* From ntifs.h */
     3152extern "C" NTKERNELAPI PEPROCESS __stdcall IoThreadToProcess(PETHREAD);
     3153
     3154/** Thread rights that we allow for handles to stub and VM processes. */
     3155# define SUPDRV_NT_ALLOWED_THREAD_RIGHTS  \
     3156    (  THREAD_TERMINATE \
     3157     | THREAD_GET_CONTEXT \
     3158     | THREAD_QUERY_INFORMATION \
     3159     | THREAD_QUERY_LIMITED_INFORMATION \
     3160     | DELETE \
     3161     | READ_CONTROL \
     3162     | SYNCHRONIZE)
     3163/** @todo consider THREAD_SET_LIMITED_INFORMATION & THREAD_RESUME */
     3164
     3165/** Evil thread rights.
     3166 * @remarks THREAD_RESUME is not included as it seems to be forced upon us by
     3167 *          Windows 8.1, at least for some processes.  We dont' actively
     3168 *          allow it though, just tollerate it when forced to. */
     3169# define SUPDRV_NT_EVIL_THREAD_RIGHTS  \
     3170    (  THREAD_SUSPEND_RESUME \
     3171     | THREAD_SET_CONTEXT \
     3172     | THREAD_SET_INFORMATION \
     3173     | THREAD_SET_LIMITED_INFORMATION /*?*/ \
     3174     | THREAD_SET_THREAD_TOKEN /*?*/ \
     3175     | THREAD_IMPERSONATE /*?*/ \
     3176     | THREAD_DIRECT_IMPERSONATION /*?*/ \
     3177     /*| THREAD_RESUME - see remarks. */ \
     3178     | 0)
     3179AssertCompile((SUPDRV_NT_EVIL_THREAD_RIGHTS & SUPDRV_NT_ALLOWED_THREAD_RIGHTS) == 0);
     3180
     3181
     3182static OB_PREOP_CALLBACK_STATUS __stdcall
     3183supdrvNtProtectCallback_ThreadHandlePre(PVOID pvUser, POB_PRE_OPERATION_INFORMATION pOpInfo)
     3184{
     3185    Assert(pvUser == NULL);
     3186    Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
     3187    Assert(pOpInfo->ObjectType == *PsThreadType);
     3188
     3189    PEPROCESS pProcess = IoThreadToProcess((PETHREAD)pOpInfo->Object);
     3190    PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(PsGetProcessId(pProcess));
     3191    pOpInfo->CallContext = pNtProtect; /* Just for reference. */
     3192    if (pNtProtect)
     3193    {
     3194        static ACCESS_MASK const s_fCsrssStupidDesires = 0x1fffff;
     3195        ACCESS_MASK fAllowedRights = SUPDRV_NT_ALLOWED_THREAD_RIGHTS;
     3196
     3197        if (pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE)
     3198        {
     3199            /* Don't restrict the process accessing its own threads. */
     3200            if (pProcess == PsGetCurrentProcess())
     3201            {
     3202                Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] self\n",
     3203                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3204                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
     3205                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind));
     3206                pOpInfo->CallContext = NULL; /* don't assert */
     3207                pNtProtect->fFirstThreadCreateHandle = false;
     3208            }
     3209            else
     3210            {
     3211                /* Special case 1 on Vista, 7, 8:
     3212                   The CreateProcess code passes the handle over to CSRSS.EXE
     3213                   and the code inBaseSrvCreateProcess will duplicate the
     3214                   handle with 0x1fffff as access mask.  NtDuplicateObject will
     3215                   fail this call before it ever gets down here.  */
     3216                if (   g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3)
     3217                    && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
     3218                    && pNtProtect->fFirstThreadCreateHandle
     3219                    && pNtProtect->hParentPid == PsGetProcessId(PsGetCurrentProcess()))
     3220                {
     3221                    if (   !pOpInfo->KernelHandle
     3222                        && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
     3223                    {
     3224                        fAllowedRights |= s_fCsrssStupidDesires;
     3225                        pOpInfo->CallContext = NULL; /* don't assert this. */
     3226                    }
     3227                    pNtProtect->fFirstThreadCreateHandle = false;
     3228                }
     3229
     3230                /* Special case 2 on 8.1, possibly also Vista, 7, 8:
     3231                   When creating a process like VBoxTestOGL from the VM process,
     3232                   CSRSS.EXE will try talk to the calling thread and, it
     3233                   appears, impersonate it.  We unfortunately need to allow
     3234                   this or there will be no 3D support.  Typical DbgPrint:
     3235                        "SXS: BasepCreateActCtx() Calling csrss server failed. Status = 0xc00000a5" */
     3236                SUPDRVNTPROTECTKIND enmProcessKind;
     3237                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 0, 0, 0)
     3238                    && (   (enmProcessKind = pNtProtect->enmProcessKind) == kSupDrvNtProtectKind_VmProcessConfirmed
     3239                        || enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
     3240                    && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
     3241                {
     3242                    fAllowedRights |= THREAD_IMPERSONATE;
     3243                    fAllowedRights |= THREAD_DIRECT_IMPERSONATION;
     3244                    //fAllowedRights |= THREAD_SET_LIMITED_INFORMATION; - try without this one
     3245                    pOpInfo->CallContext = NULL; /* don't assert this. */
     3246                }
     3247
     3248                Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p wants %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s\n",
     3249                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3250                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
     3251                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
     3252                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess & fAllowedRights,
     3253                     PsGetProcessImageFileName(PsGetCurrentProcess())));
     3254
     3255                pOpInfo->Parameters->CreateHandleInformation.DesiredAccess &= fAllowedRights;
     3256            }
     3257        }
     3258        else
     3259        {
     3260            /* Don't restrict the process accessing its own threads. */
     3261            if (   pProcess == PsGetCurrentProcess()
     3262                && (PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == pProcess)
     3263            {
     3264                Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] self\n",
     3265                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3266                     pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
     3267                     PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
     3268                     pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
     3269                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
     3270                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
     3271                     PsGetProcessImageFileName(PsGetCurrentProcess()) ));
     3272                pOpInfo->CallContext = NULL; /* don't assert */
     3273            }
     3274            else
     3275            {
     3276                /* Special case 3 on Vista, 7, 8:
     3277                   This is the follow up to special case 1. */
     3278                SUPDRVNTPROTECTKIND enmProcessKind;
     3279                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 0, 0, 0)
     3280                    && (   (enmProcessKind = pNtProtect->enmProcessKind) == kSupDrvNtProtectKind_VmProcessConfirmed
     3281                        || enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
     3282                    && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == PsGetCurrentProcess()
     3283                    && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
     3284                {
     3285                    fAllowedRights |= THREAD_IMPERSONATE;
     3286                    fAllowedRights |= THREAD_DIRECT_IMPERSONATION;
     3287                    //fAllowedRights |= THREAD_SET_LIMITED_INFORMATION; - try without this one
     3288                    pOpInfo->CallContext = NULL; /* don't assert this. */
     3289                }
     3290
     3291                Log(("vboxdrv/ThreadHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s\n",
     3292                     PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
     3293                     pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
     3294                     PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
     3295                     pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
     3296                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
     3297                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
     3298                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess & fAllowedRights,
     3299                     PsGetProcessImageFileName(PsGetCurrentProcess()) ));
     3300
     3301                pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess &= fAllowedRights;
     3302            }
     3303        }
     3304
     3305        supdrvNtProtectRelease(pNtProtect);
     3306    }
     3307
     3308    return OB_PREOP_SUCCESS;
     3309}
     3310
     3311
     3312static VOID __stdcall
     3313supdrvNtProtectCallback_ThreadHandlePost(PVOID pvUser, POB_POST_OPERATION_INFORMATION pOpInfo)
     3314{
     3315    Assert(pvUser == NULL);
     3316    Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
     3317    Assert(pOpInfo->ObjectType == *PsThreadType);
     3318
     3319    if (   pOpInfo->CallContext
     3320        && NT_SUCCESS(pOpInfo->ReturnStatus))
     3321    {
     3322        ACCESS_MASK const fGrantedAccess = pOpInfo->Parameters->CreateHandleInformation.GrantedAccess;
     3323        AssertReleaseMsg(   !(fGrantedAccess & ~(  SUPDRV_NT_ALLOWED_THREAD_RIGHTS
     3324                                                 | WRITE_OWNER | WRITE_DAC /* these two might be forced upon us */
     3325                                                 | THREAD_RESUME /* This seems to be force upon us too with 8.1. */
     3326                                                 ) )
     3327                         || pOpInfo->KernelHandle,
     3328                         ("GrantedAccess=%#x - we allow %#x - we did not allow %#x\n",
     3329                          fGrantedAccess, SUPDRV_NT_ALLOWED_THREAD_RIGHTS, fGrantedAccess & ~SUPDRV_NT_ALLOWED_THREAD_RIGHTS));
     3330    }
     3331}
     3332
     3333# undef SUPDRV_NT_ALLOWED_THREAD_RIGHTS
     3334
     3335/** @} */
     3336
     3337
     3338/**
     3339 * Creates a new process protection structure.
     3340 *
     3341 * @returns VBox status code.
     3342 * @param   ppNtProtect         Where to return the pointer to the structure
     3343 *                              on success.
     3344 * @param   hPid                The process ID of the process to protect.
     3345 * @param   enmProcessKind      The kind of process we're protecting.
     3346 * @param   fLink               Whether to link the structure into the tree.
     3347 */
     3348static int supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid, SUPDRVNTPROTECTKIND enmProcessKind, bool fLink)
     3349{
     3350    AssertReturn(g_hNtProtectLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
     3351
     3352    PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)RTMemAllocZ(sizeof(*pNtProtect));
     3353    if (!pNtProtect)
     3354        return VERR_NO_MEMORY;
     3355
     3356    pNtProtect->AvlCore.Key                  = hPid;
     3357    pNtProtect->u32Magic                     = SUPDRVNTPROTECT_MAGIC;
     3358    pNtProtect->cRefs                        = 1;
     3359    pNtProtect->enmProcessKind               = enmProcessKind;
     3360    pNtProtect->hParentPid                   = NULL;
     3361    pNtProtect->hCsrssPid                    = NULL;
     3362    pNtProtect->pCsrssProcess                = NULL;
     3363
     3364    if (fLink)
     3365    {
     3366        RTSpinlockAcquire(g_hNtProtectLock);
     3367        bool fSuccess = RTAvlPVInsert(&g_NtProtectTree, &pNtProtect->AvlCore);
     3368        RTSpinlockRelease(g_hNtProtectLock);
     3369
     3370        if (!fSuccess)
     3371        {
     3372            /* Duplicate entry, fail. */
     3373            pNtProtect->u32Magic = SUPDRVNTPROTECT_MAGIC_DEAD;
     3374            RTMemFree(pNtProtect);
     3375            return VERR_ACCESS_DENIED;
     3376        }
     3377    }
     3378
     3379    *ppNtProtect = pNtProtect;
     3380    return VINF_SUCCESS;
     3381}
     3382
     3383
     3384/**
     3385 * Releases a reference to a NT protection structure.
     3386 *
     3387 * @param   pNtProtect          The NT protection structure.
     3388 */
     3389static void supdrvNtProtectRelease(PSUPDRVNTPROTECT pNtProtect)
     3390{
     3391    if (!pNtProtect)
     3392        return;
     3393    AssertReturnVoid(pNtProtect->u32Magic == SUPDRVNTPROTECT_MAGIC);
     3394
     3395    RTSpinlockAcquire(g_hNtProtectLock);
     3396    uint32_t cRefs = ASMAtomicDecU32(&pNtProtect->cRefs);
     3397    if (cRefs != 0)
     3398        RTSpinlockRelease(g_hNtProtectLock);
     3399    else
     3400    {
     3401        /*
     3402         * That was the last reference.  Remove it from the tree, invalidate it
     3403         * and free the resources associated with it.  Also, release any
     3404         * child/parent references related to this protection structure.
     3405         */
     3406        ASMAtomicWriteU32(&pNtProtect->u32Magic, SUPDRVNTPROTECT_MAGIC_DEAD);
     3407        PSUPDRVNTPROTECT pRemoved = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pNtProtect->AvlCore.Key);
     3408
     3409        PSUPDRVNTPROTECT pRemovedChild = NULL;
     3410        PSUPDRVNTPROTECT pChild = NULL;
     3411        if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent)
     3412        {
     3413            pChild = pNtProtect->u.pChild;
     3414            if (pChild)
     3415            {
     3416                pNtProtect->u.pChild   = NULL;
     3417                pChild->u.pParent      = NULL;
     3418                pChild->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
     3419                uint32_t cChildRefs = ASMAtomicIncU32(&pChild->cRefs);
     3420                if (!cChildRefs)
     3421                    pRemovedChild = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pChild->AvlCore.Key);
     3422                else
     3423                    pChild = NULL;
     3424            }
     3425        }
     3426        else
     3427            AssertRelease(pNtProtect->enmProcessKind != kSupDrvNtProtectKind_VmProcessUnconfirmed);
     3428
     3429        RTSpinlockRelease(g_hNtProtectLock);
     3430        Assert(pRemoved == pNtProtect);
     3431        Assert(pRemovedChild == pChild);
     3432
     3433        if (pNtProtect->pCsrssProcess)
     3434        {
     3435            ObDereferenceObject(pNtProtect->pCsrssProcess);
     3436            pNtProtect->pCsrssProcess = NULL;
     3437        }
     3438
     3439        RTMemFree(pNtProtect);
     3440        if (pChild)
     3441            RTMemFree(pChild);
     3442    }
     3443}
     3444
     3445
     3446/**
     3447 * Looks up a PID in the NT protect tree.
     3448 *
     3449 * @returns Pointer to a NT protection structure (with a referenced) on success,
     3450 *          NULL if not found.
     3451 * @param   hPid                The process ID.
     3452 */
     3453static PSUPDRVNTPROTECT supdrvNtProtectLookup(HANDLE hPid)
     3454{
     3455    RTSpinlockAcquire(g_hNtProtectLock);
     3456    PSUPDRVNTPROTECT pFound = (PSUPDRVNTPROTECT)RTAvlPVGet(&g_NtProtectTree, hPid);
     3457    if (pFound)
     3458        ASMAtomicIncU32(&pFound->cRefs);
     3459    RTSpinlockRelease(g_hNtProtectLock);
     3460    return pFound;
     3461}
     3462
     3463
     3464/**
     3465 * Worker for supdrvNtProtectVerifyProcess that verifies the handles to a VM
     3466 * process and its thread.
     3467 *
     3468 * @returns VBox status code.
     3469 * @param   pNtProtect          The NT protect structure for getting information
     3470 *                              about special processes.
     3471 */
     3472static int supdrvNtProtectRestrictHandlesToProcessAndThread(PSUPDRVNTPROTECT pNtProtect)
     3473{
     3474    /*
     3475     * What to protect.
     3476     */
     3477    PEPROCESS   pProtectedProcess = PsGetCurrentProcess();
     3478    HANDLE      hProtectedPid     = PsGetProcessId(pProtectedProcess);
     3479    PETHREAD    pProtectedThread  = PsGetCurrentThread();
     3480    AssertReturn(pNtProtect->AvlCore.Key == hProtectedPid, VERR_INTERNAL_ERROR_5);
     3481
     3482    /*
     3483     * Take a snapshot of all the handles in the system.
     3484     */
     3485    uint32_t    cbBuf    = _256K;
     3486    uint8_t    *pbBuf    = (uint8_t *)RTMemAlloc(cbBuf);
     3487    ULONG       cbNeeded = cbBuf;
     3488    NTSTATUS rcNt = NtQuerySystemInformation(SystemExtendedHandleInformation, pbBuf, cbBuf, &cbNeeded);
     3489    if (!NT_SUCCESS(rcNt))
     3490    {
     3491        while (   rcNt == STATUS_INFO_LENGTH_MISMATCH
     3492               && cbNeeded > cbBuf
     3493               && cbBuf <= 32U*_1M)
     3494        {
     3495            cbBuf = RT_ALIGN_32(cbNeeded + _4K, _64K);
     3496            RTMemFree(pbBuf);
     3497            pbBuf = (uint8_t *)RTMemAlloc(cbBuf);
     3498            if (!pbBuf)
     3499                return VERR_NO_MEMORY;
     3500            rcNt = NtQuerySystemInformation(SystemExtendedHandleInformation, pbBuf, cbBuf, &cbNeeded);
     3501        }
     3502        if (!NT_SUCCESS(rcNt))
     3503        {
     3504            RTMemFree(pbBuf);
     3505            return RTErrConvertFromNtStatus(rcNt);
     3506        }
     3507    }
     3508
     3509    /*
     3510     * Walk the information and look for handles to the two objects we're protecting.
     3511     */
     3512    int rc = VINF_SUCCESS;
     3513
     3514    uint32_t cCsrssProcessHandles  = 0;
     3515    uint32_t cSystemProcessHandles = 0;
     3516    uint32_t cEvilProcessHandles   = 0;
     3517    uint32_t cBenignProcessHandles = 0;
     3518
     3519    uint32_t cCsrssThreadHandles   = 0;
     3520    uint32_t cEvilThreadHandles    = 0;
     3521    uint32_t cBenignThreadHandles  = 0;
     3522
     3523    SYSTEM_HANDLE_INFORMATION_EX const *pInfo = (SYSTEM_HANDLE_INFORMATION_EX const *)pbBuf;
     3524    ULONG_PTR i = pInfo->NumberOfHandles;
     3525    AssertRelease(RT_OFFSETOF(SYSTEM_HANDLE_INFORMATION_EX, Handles[i]) == cbNeeded);
     3526    while (i-- > 0)
     3527    {
     3528        const char *pszType;
     3529        SYSTEM_HANDLE_ENTRY_INFO_EX const *pHandleInfo = &pInfo->Handles[i];
     3530        if (pHandleInfo->Object == pProtectedProcess)
     3531        {
     3532            /* Handles within the protected process is fine. */
     3533            if (   !(pHandleInfo->GrantedAccess & SUPDRV_NT_EVIL_PROCESS_RIGHTS)
     3534                || pHandleInfo->UniqueProcessId == hProtectedPid)
     3535            {
     3536                cBenignProcessHandles++;
     3537                continue;
     3538            }
     3539
     3540            /* CSRSS is allowed to have one evil process handle.
     3541               See the special cases in the hook code. */
     3542            if (   cCsrssProcessHandles < 1
     3543                && pHandleInfo->UniqueProcessId == pNtProtect->hCsrssPid)
     3544            {
     3545                cCsrssProcessHandles++;
     3546                continue;
     3547            }
     3548
     3549            /* The system process is allowed having one open process handle in
     3550               Windows 8.1 and later. */
     3551            if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)
     3552                && cSystemProcessHandles < 1
     3553                && pHandleInfo->UniqueProcessId == PsGetProcessId(PsInitialSystemProcess))
     3554            {
     3555                cSystemProcessHandles++;
     3556                continue;
     3557            }
     3558
     3559            cEvilProcessHandles++;
     3560            pszType = "process";
     3561        }
     3562        else if (pHandleInfo->Object == pProtectedThread)
     3563        {
     3564            /* Handles within the protected process is fine. */
     3565            if (   !(pHandleInfo->GrantedAccess & SUPDRV_NT_EVIL_THREAD_RIGHTS)
     3566                || pHandleInfo->UniqueProcessId == hProtectedPid)
     3567            {
     3568                cBenignThreadHandles++;
     3569                continue;
     3570            }
     3571
     3572            /* CSRSS is allowed to have one evil handle to the primary thread
     3573               for LPC purposes.  See the hook for special case. */
     3574            if (   cCsrssThreadHandles < 1
     3575                && pHandleInfo->UniqueProcessId == pNtProtect->hCsrssPid)
     3576            {
     3577                cCsrssThreadHandles++;
     3578                continue;
     3579            }
     3580
     3581            cEvilThreadHandles++;
     3582            pszType = "thread";
     3583        }
     3584        else
     3585            continue;
     3586
     3587        /* Found evil handle. Currently ignoring on pre-Vista. */
     3588# ifndef VBOX_WITH_VISTA_NO_SP
     3589        if (   g_uNtVerCombined >= SUP_NT_VER_VISTA
     3590# else
     3591        if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 6001, 0, 0)
     3592# endif
     3593            || g_pfnObRegisterCallbacks)
     3594        {
     3595            LogRel(("vboxdrv: Found evil handle to budding VM process: pid=%p h=%p acc=%#x attr=%#x type=%s\n",
     3596                    pHandleInfo->UniqueProcessId, pHandleInfo->HandleValue,
     3597                    pHandleInfo->GrantedAccess, pHandleInfo->HandleAttributes, pszType));
     3598            rc = VERR_SUPDRV_HARDENING_EVIL_HANDLE;
     3599        }
     3600    }
     3601
     3602    return rc;
     3603}
     3604
     3605
     3606/**
     3607 * Checks if the current process checks out as a VM process stub.
     3608 *
     3609 * @returns VBox status code.
     3610 * @param   pNtProtect          The NT protect structure.  This is upgraded to a
     3611 *                              final protection kind (state) on success.
     3612 */
     3613static int supdrvNtProtectVerifyProcess(PSUPDRVNTPROTECT pNtProtect)
     3614{
     3615    AssertReturn(PsGetProcessId(PsGetCurrentProcess()) == pNtProtect->AvlCore.Key, VERR_INTERNAL_ERROR_3);
     3616
     3617    /*
     3618     * Do the verification.  The handle restriction checks are only preformed
     3619     * on VM processes.
     3620     */
     3621    int rc = VINF_SUCCESS;
     3622    if (pNtProtect->enmProcessKind >= kSupDrvNtProtectKind_VmProcessUnconfirmed)
     3623        rc = supdrvNtProtectRestrictHandlesToProcessAndThread(pNtProtect);
     3624    if (RT_SUCCESS(rc))
     3625    {
     3626        char szErr[256];
     3627        RT_ZERO(szErr);
     3628        RTERRINFO ErrInfo;
     3629        RTErrInfoInit(&ErrInfo, szErr, sizeof(szErr));
     3630
     3631        rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), &ErrInfo);
     3632        if (RT_FAILURE(rc))
     3633            RTLogWriteDebugger(szErr, strlen(szErr));
     3634    }
     3635
     3636    /*
     3637     * Upgrade and return.
     3638     */
     3639    RTSpinlockAcquire(g_hNtProtectLock);
     3640
     3641    /* Stub process verficiation is pretty much straight forward. */
     3642    if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubUnverified)
     3643        pNtProtect->enmProcessKind = RT_SUCCESS(rc) ? kSupDrvNtProtectKind_StubSpawning : kSupDrvNtProtectKind_StubDead;
     3644
     3645    /* The VM process verification is a little bit more complicated
     3646       because we need to drop the parent process reference as well. */
     3647    else if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
     3648    {
     3649        AssertRelease(pNtProtect->cRefs >= 2); /* Parent + Caller */
     3650        PSUPDRVNTPROTECT pParent = pNtProtect->u.pParent;
     3651        AssertRelease(pParent);
     3652        AssertRelease(pParent->u.pParent == pNtProtect);
     3653        AssertRelease(pParent->enmProcessKind == kSupDrvNtProtectKind_StubParent);
     3654        pParent->u.pParent = NULL;
     3655
     3656        pNtProtect->u.pParent = NULL;
     3657        ASMAtomicDecU32(&pNtProtect->cRefs);
     3658
     3659        if (RT_SUCCESS(rc))
     3660            pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessConfirmed;
     3661        else
     3662            pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
     3663    }
     3664
     3665    /* Since the stub and VM processes are only supposed to have one thread,
     3666       we're not supposed to be subject to any races from within the processes.
     3667
     3668       There is a race between VM process verification and the stub process
     3669       exiting, though.  We require the stub process to be alive until the new
     3670       VM process has made it thru the validation.  So, when the stub
     3671       terminates the notification handler will change the state of both stub
     3672       and VM process to dead.
     3673
     3674       Also, I'm not entirely certain where the process
     3675       termination notification is triggered from, so that can theorically
     3676       create a race in both cases.  */
     3677    else
     3678    {
     3679        AssertReleaseMsg(   pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubDead
     3680                         || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessDead,
     3681                         ("enmProcessKind=%d rc=%Rrc\n", pNtProtect->enmProcessKind, rc));
     3682        if (RT_SUCCESS(rc))
     3683            rc = VERR_INVALID_STATE; /* There should be no races here. */
     3684    }
     3685
     3686    RTSpinlockRelease(g_hNtProtectLock);
     3687    return rc;
     3688}
     3689
     3690
     3691# ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
     3692
     3693/**
     3694 * Checks if the current process is being debugged.
     3695 * @return @c true if debugged, @c false if not.
     3696 */
     3697static bool supdrvNtIsDebuggerAttached(void)
     3698{
     3699    return PsIsProcessBeingDebugged(PsGetCurrentProcess()) != FALSE;
     3700}
     3701
     3702# endif /* !VBOX_WITHOUT_DEBUGGER_CHECKS */
     3703
     3704
     3705/**
     3706 * Terminates the hardening bits.
     3707 */
     3708static void supdrvNtProtectTerm(void)
     3709{
     3710    /*
     3711     * Stop intercepting process and thread handle creation calls.
     3712     */
     3713    if (g_pvObCallbacksCookie)
     3714    {
     3715        g_pfnObUnRegisterCallbacks(g_pvObCallbacksCookie);
     3716        g_pvObCallbacksCookie = NULL;
     3717    }
     3718
     3719    /*
     3720     * Stop intercepting process creation and termination notifications.
     3721     */
     3722    NTSTATUS rcNt;
     3723    if (g_pfnPsSetCreateProcessNotifyRoutineEx)
     3724        rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
     3725    else
     3726        rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, TRUE /*fRemove*/);
     3727    AssertMsg(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
     3728
     3729    Assert(g_NtProtectTree == NULL);
     3730
     3731    /*
     3732     * Clean up globals.
     3733     */
     3734    RTSpinlockDestroy(g_hNtProtectLock);
     3735    g_NtProtectTree = NIL_RTSPINLOCK;
     3736
     3737    supHardenedWinTermImageVerifier();
     3738}
     3739
     3740# ifdef RT_ARCH_X86
     3741DECLASM(void) supdrvNtQueryVirtualMemory_0xAF(void);
     3742DECLASM(void) supdrvNtQueryVirtualMemory_0xB0(void);
     3743DECLASM(void) supdrvNtQueryVirtualMemory_0xB1(void);
     3744DECLASM(void) supdrvNtQueryVirtualMemory_0xB2(void);
     3745DECLASM(void) supdrvNtQueryVirtualMemory_0xB3(void);
     3746DECLASM(void) supdrvNtQueryVirtualMemory_0xB4(void);
     3747DECLASM(void) supdrvNtQueryVirtualMemory_0xB5(void);
     3748DECLASM(void) supdrvNtQueryVirtualMemory_0xB6(void);
     3749DECLASM(void) supdrvNtQueryVirtualMemory_0xB7(void);
     3750DECLASM(void) supdrvNtQueryVirtualMemory_0xB8(void);
     3751DECLASM(void) supdrvNtQueryVirtualMemory_0xB9(void);
     3752DECLASM(void) supdrvNtQueryVirtualMemory_0xBA(void);
     3753DECLASM(void) supdrvNtQueryVirtualMemory_0xBB(void);
     3754DECLASM(void) supdrvNtQueryVirtualMemory_0xBC(void);
     3755DECLASM(void) supdrvNtQueryVirtualMemory_0xBD(void);
     3756DECLASM(void) supdrvNtQueryVirtualMemory_0xBE(void);
     3757# elif defined(RT_ARCH_AMD64)
     3758DECLASM(void) supdrvNtQueryVirtualMemory_0x1F(void);
     3759DECLASM(void) supdrvNtQueryVirtualMemory_0x20(void);
     3760DECLASM(void) supdrvNtQueryVirtualMemory_0x21(void);
     3761DECLASM(void) supdrvNtQueryVirtualMemory_0x22(void);
     3762DECLASM(void) supdrvNtQueryVirtualMemory_0x23(void);
     3763extern "C" NTSYSAPI NTSTATUS NTAPI ZwRequestWaitReplyPort(HANDLE, PVOID, PVOID);
     3764# endif
     3765
     3766/**
     3767 * Initalizes the hardening bits.
     3768 *
     3769 * @returns NT status code.
     3770 */
     3771static NTSTATUS supdrvNtProtectInit(void)
     3772{
     3773    /*
     3774     * Initialize the globals.
     3775     */
     3776
     3777    /* The NT version. */
     3778    ULONG uMajor, uMinor, uBuild;
     3779    PsGetVersion(&uMajor, &uMinor, &uBuild, NULL);
     3780    g_uNtVerCombined = SUP_MAKE_NT_VER_COMBINED(uMajor, uMinor, uBuild, 0, 0);
     3781
     3782    /* Resolve methods we want but isn't available everywhere. */
     3783    UNICODE_STRING RoutineName;
     3784
     3785    RtlInitUnicodeString(&RoutineName, L"ObRegisterCallbacks");
     3786    g_pfnObRegisterCallbacks   = (PFNOBREGISTERCALLBACKS)MmGetSystemRoutineAddress(&RoutineName);
     3787
     3788    RtlInitUnicodeString(&RoutineName, L"ObUnRegisterCallbacks");
     3789    g_pfnObUnRegisterCallbacks = (PFNOBUNREGISTERCALLBACKS)MmGetSystemRoutineAddress(&RoutineName);
     3790
     3791    RtlInitUnicodeString(&RoutineName, L"PsSetCreateProcessNotifyRoutineEx");
     3792    g_pfnPsSetCreateProcessNotifyRoutineEx = (PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)MmGetSystemRoutineAddress(&RoutineName);
     3793
     3794    RtlInitUnicodeString(&RoutineName, L"PsReferenceProcessFilePointer");
     3795    g_pfnPsReferenceProcessFilePointer = (PFNPSREFERENCEPROCESSFILEPOINTER)MmGetSystemRoutineAddress(&RoutineName);
     3796
     3797    RtlInitUnicodeString(&RoutineName, L"PsIsProtectedProcessLight");
     3798    g_pfnPsIsProtectedProcessLight = (PFNPSISPROTECTEDPROCESSLIGHT)MmGetSystemRoutineAddress(&RoutineName);
     3799
     3800    RtlInitUnicodeString(&RoutineName, L"ZwQueryVirtualMemory"); /* Yes, using Zw version here. */
     3801    g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)MmGetSystemRoutineAddress(&RoutineName);
     3802    if (!g_pfnNtQueryVirtualMemory && g_uNtVerCombined < SUP_NT_VER_VISTA)
     3803    {
     3804        /* XP & W2K3 doesn't have this function exported, so we've cooked up a
     3805           few alternative in the assembly helper file that uses the code in
     3806           ZwQueryVolumeInformationFile with a different eax value. */
     3807# ifdef RT_ARCH_X86
     3808        uint8_t const *pbCode = (uint8_t const *)(uintptr_t)ZwQueryVolumeInformationFile;
     3809        if (*pbCode == 0xb8) /* mov eax, dword */
     3810            switch (*(uint32_t const *)&pbCode[1])
     3811            {
     3812                case 0xb0: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xAF; break; /* just in case */
     3813                case 0xb1: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB0; break; /* just in case */
     3814                case 0xb2: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB1; break; /* just in case */
     3815                case 0xb3: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* XP SP3 */
     3816                case 0xb4: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* just in case */
     3817                case 0xb5: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB3; break; /* just in case */
     3818                case 0xb6: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB4; break; /* just in case */
     3819                case 0xb7: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB5; break; /* just in case */
     3820                case 0xb8: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB6; break; /* just in case */
     3821                case 0xb9: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB7; break; /* just in case */
     3822                case 0xba: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB8; break; /* just in case */
     3823                case 0xbb: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBA; break; /* W2K3 R2 SP2 */
     3824                case 0xbc: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBB; break; /* just in case */
     3825                case 0xbd: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBC; break; /* just in case */
     3826                case 0xbe: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBD; break; /* just in case */
     3827                case 0xbf: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBE; break; /* just in case */
     3828            }
     3829# elif defined(RT_ARCH_AMD64)
     3830        uint8_t const *pbCode = (uint8_t const *)(uintptr_t)ZwRequestWaitReplyPort;
     3831        if (   pbCode[ 0] == 0x48   /* mov rax, rsp */
     3832            && pbCode[ 1] == 0x8b
     3833            && pbCode[ 2] == 0xc4
     3834            && pbCode[ 3] == 0xfa   /* cli */
     3835            && pbCode[ 4] == 0x48   /* sub rsp, 10h */
     3836            && pbCode[ 5] == 0x83
     3837            && pbCode[ 6] == 0xec
     3838            && pbCode[ 7] == 0x10
     3839            && pbCode[ 8] == 0x50   /* push rax */
     3840            && pbCode[ 9] == 0x9c   /* pushfq */
     3841            && pbCode[10] == 0x6a   /* push 10 */
     3842            && pbCode[11] == 0x10
     3843            && pbCode[12] == 0x48   /* lea rax, [nt!KiServiceLinkage] */
     3844            && pbCode[13] == 0x8d
     3845            && pbCode[14] == 0x05
     3846            && pbCode[19] == 0x50   /* push rax */
     3847            && pbCode[20] == 0xb8   /* mov eax,1fh <- the syscall no. */
     3848            /*&& pbCode[21] == 0x1f*/
     3849            && pbCode[22] == 0x00
     3850            && pbCode[23] == 0x00
     3851            && pbCode[24] == 0x00
     3852            && pbCode[25] == 0xe9   /* jmp KiServiceInternal */
     3853           )
     3854        {
     3855            uint8_t const *pbKiServiceInternal = &pbCode[30] + *(int32_t const *)&pbCode[26];
     3856            uint8_t const *pbKiServiceLinkage  = &pbCode[19] + *(int32_t const *)&pbCode[15];
     3857            if (*pbKiServiceLinkage == 0xc3)
     3858            {
     3859                g_pfnKiServiceInternal = (PFNRT)pbKiServiceInternal;
     3860                g_pfnKiServiceLinkage  = (PFNRT)pbKiServiceLinkage;
     3861                switch (pbCode[21])
     3862                {
     3863                    case 0x1e: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x1F; break;
     3864                    case 0x1f: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x20; break;
     3865                    case 0x20: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x21; break;
     3866                    case 0x21: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x22; break;
     3867                    case 0x22: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x23; break;
     3868                }
     3869            }
     3870        }
     3871# endif
     3872    }
     3873    if (!g_pfnNtQueryVirtualMemory)
     3874    {
     3875        LogRel(("vboxdrv: Cannot locate ZwQueryVirtualMemory in ntoskrnl, nor were we able to cook up a replacement.\n"));
     3876        return STATUS_PROCEDURE_NOT_FOUND;
     3877    }
     3878
     3879
     3880    /* The spinlock protecting our structures. */
     3881    int rc = RTSpinlockCreate(&g_hNtProtectLock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "NtProtectLock");
     3882    if (RT_FAILURE(rc))
     3883        return VBoxDrvNtErr2NtStatus(rc);
     3884    g_NtProtectTree = NULL;
     3885
     3886    /* Image stuff + certificates. */
     3887    NTSTATUS rcNt;
     3888    rc = supHardenedWinInitImageVerifier(NULL);
     3889    if (RT_SUCCESS(rc))
     3890    {
     3891        /*
     3892         * Intercept process creation and termination.
     3893         */
     3894        if (g_pfnPsSetCreateProcessNotifyRoutineEx)
     3895            rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, FALSE /*fRemove*/);
     3896        else
     3897            rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, FALSE /*fRemove*/);
     3898        if (NT_SUCCESS(rcNt))
     3899        {
     3900            /*
     3901             * Intercept process and thread handle creation calls.
     3902             * The preferred method is only available on Vista SP1+.
     3903             */
     3904            if (g_pfnObRegisterCallbacks && g_pfnObUnRegisterCallbacks)
     3905            {
     3906                static OB_OPERATION_REGISTRATION s_aObOperations[] =
     3907                {
     3908                    {
     3909                        PsProcessType,
     3910                        OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
     3911                        supdrvNtProtectCallback_ProcessHandlePre,
     3912                        supdrvNtProtectCallback_ProcessHandlePost,
     3913                    },
     3914                    {
     3915                        PsThreadType,
     3916                        OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
     3917                        supdrvNtProtectCallback_ThreadHandlePre,
     3918                        supdrvNtProtectCallback_ThreadHandlePost,
     3919                    },
     3920                };
     3921                static OB_CALLBACK_REGISTRATION s_ObCallbackReg =
     3922                {
     3923                    /* .Version                     = */ OB_FLT_REGISTRATION_VERSION,
     3924                    /* .OperationRegistrationCount  = */ RT_ELEMENTS(s_aObOperations),
     3925                    /* .Altitude.Length             = */ 0,
     3926                    /* .Altitude.MaximumLength      = */ 0,
     3927                    /* .Altitude.Buffer             = */ NULL,
     3928                    /* .RegistrationContext         = */ NULL,
     3929                    /* .OperationRegistration       = */ &s_aObOperations[0]
     3930                };
     3931                static WCHAR const *s_apwszAltitudes[] = /** @todo get a valid number */
     3932                {
     3933                     L"48596.98940",  L"46935.19485",  L"49739.39704",  L"40334.74976",
     3934                     L"66667.98940",  L"69888.19485",  L"69889.39704",  L"60364.74976",
     3935                     L"85780.98940",  L"88978.19485",  L"89939.39704",  L"80320.74976",
     3936                     L"329879.98940", L"326787.19485", L"328915.39704", L"320314.74976",
     3937                };
     3938
     3939                rcNt = STATUS_FLT_INSTANCE_ALTITUDE_COLLISION;
     3940                for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszAltitudes) && rcNt == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION; i++)
     3941                {
     3942                    s_ObCallbackReg.Altitude.Buffer = (WCHAR *)s_apwszAltitudes[i];
     3943                    s_ObCallbackReg.Altitude.Length = (uint16_t)RTUtf16Len(s_apwszAltitudes[i]) * sizeof(WCHAR);
     3944                    s_ObCallbackReg.Altitude.MaximumLength = s_ObCallbackReg.Altitude.Length + sizeof(WCHAR);
     3945
     3946                    rcNt = g_pfnObRegisterCallbacks(&s_ObCallbackReg, &g_pvObCallbacksCookie);
     3947                    if (NT_SUCCESS(rcNt))
     3948                    {
     3949                        /*
     3950                         * Happy ending.
     3951                         */
     3952                        return STATUS_SUCCESS;
     3953                    }
     3954                }
     3955                LogRel(("vboxdrv: ObRegisterCallbacks failed with rcNt=%#x\n", rcNt));
     3956                g_pvObCallbacksCookie = NULL;
     3957            }
     3958            else
     3959            {
     3960                /*
     3961                 * For the time being, we do not implement extra process
     3962                 * protection on pre-Vista-SP1 systems as they are lacking
     3963                 * necessary KPIs.  XP is end of life, we do not wish to
     3964                 * spend more time on it, so we don't put up a fuss there.
     3965                 * Vista users without SP1 can install SP1 (or later), darn it,
     3966                 * so refuse to load.
     3967                 */
     3968                /** @todo Hack up an XP solution - will require hooking kernel APIs or doing bad
     3969                 *        stuff to a couple of object types. */
     3970# ifndef VBOX_WITH_VISTA_NO_SP
     3971                if (g_uNtVerCombined >= SUP_NT_VER_VISTA)
     3972# else
     3973                if (g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 6001, 0, 0))
     3974# endif
     3975                {
     3976                    DbgPrint("vboxdrv: ObRegisterCallbacks was not found. Please make sure you got the latest updates and service packs installed\n");
     3977                    rcNt = STATUS_SXS_VERSION_CONFLICT;
     3978                }
     3979                else
     3980                {
     3981                    Log(("vboxdrv: ObRegisterCallbacks was not found; ignored pre-Vista\n"));
     3982                    return rcNt = STATUS_SUCCESS;
     3983                }
     3984                g_pvObCallbacksCookie = NULL;
     3985            }
     3986
     3987            /*
     3988             * Drop process create/term notifications.
     3989             */
     3990            if (g_pfnPsSetCreateProcessNotifyRoutineEx)
     3991                g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
     3992            else
     3993                PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, TRUE /*fRemove*/);
     3994        }
     3995        else
     3996            LogRel(("vboxdrv: PsSetCreateProcessNotifyRoutine%s failed with rcNt=%#x\n",
     3997                    g_pfnPsSetCreateProcessNotifyRoutineEx ? "Ex" : "", rcNt));
     3998        supHardenedWinTermImageVerifier();
     3999    }
     4000    else
     4001        rcNt = VBoxDrvNtErr2NtStatus(rc);
     4002
     4003    RTSpinlockDestroy(g_hNtProtectLock);
     4004    g_NtProtectTree = NIL_RTSPINLOCK;
     4005    return rcNt;
     4006}
     4007
     4008#endif /* VBOX_WITH_HARDENING */
     4009
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm

    r44528 r51770  
    55
    66;
    7 ; Copyright (C) 2006-2010 Oracle Corporation
     7; Copyright (C) 2006-2014 Oracle Corporation
    88;
    99; This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545%endif
    4646
     47
     48%ifdef RT_ARCH_X86
     49;
     50; Faking up ZwQueryVirtualMemory on XP and W2K3 where it's not exported.
     51; Using ZwQueryVolumeInformationFile as a helper.
     52;
     53extern  IMPNAME(ZwQueryVolumeInformationFile@20)
     54
     55BEGINPROC supdrvNtQueryVirtualMemory_Xxx
     56 %macro NtQueryVirtualMemorySyscall 1
     57 GLOBALNAME supdrvNtQueryVirtualMemory_ %+ %1
     58        mov     eax, %1
     59        jmp     supdrvNtQueryVirtualMemory_Jump
     60 %endm
     61    NtQueryVirtualMemorySyscall 0xAF
     62    NtQueryVirtualMemorySyscall 0xB0
     63    NtQueryVirtualMemorySyscall 0xB1
     64    NtQueryVirtualMemorySyscall 0xB2
     65    NtQueryVirtualMemorySyscall 0xB3
     66    NtQueryVirtualMemorySyscall 0xB4
     67    NtQueryVirtualMemorySyscall 0xB5
     68    NtQueryVirtualMemorySyscall 0xB6
     69    NtQueryVirtualMemorySyscall 0xB7
     70    NtQueryVirtualMemorySyscall 0xB8
     71    NtQueryVirtualMemorySyscall 0xB9
     72    NtQueryVirtualMemorySyscall 0xBA
     73    NtQueryVirtualMemorySyscall 0xBB
     74    NtQueryVirtualMemorySyscall 0xBC
     75    NtQueryVirtualMemorySyscall 0xBD
     76    NtQueryVirtualMemorySyscall 0xBE
     77
     78supdrvNtQueryVirtualMemory_Jump:
     79        mov     edx, IMP2(ZwQueryVolumeInformationFile@20)
     80        lea     edx, [edx + 5]
     81        jmp     edx
     82ENDPROC   supdrvNtQueryVirtualMemory_Xxx
     83
     84%endif
     85
     86%ifdef RT_ARCH_AMD64
     87;
     88; Faking up ZwQueryVirtualMemory on XP64 and W2K3-64 where it's not exported.
     89; The C code locates and verifies the essentials in ZwRequestWaitReplyPort.
     90;
     91extern NAME(g_pfnKiServiceLinkage)
     92extern NAME(g_pfnKiServiceInternal)
     93BEGINPROC supdrvNtQueryVirtualMemory_Xxx
     94 %macro NtQueryVirtualMemorySyscall 1
     95 GLOBALNAME supdrvNtQueryVirtualMemory_ %+ %1
     96        mov     eax, %1
     97        jmp     supdrvNtQueryVirtualMemory_Jump
     98 %endm
     99
     100    NtQueryVirtualMemorySyscall 0x1F
     101    NtQueryVirtualMemorySyscall 0x20
     102    NtQueryVirtualMemorySyscall 0x21
     103    NtQueryVirtualMemorySyscall 0x22
     104    NtQueryVirtualMemorySyscall 0x23
     105
     106supdrvNtQueryVirtualMemory_Jump:
     107        cli
     108        mov     r10, rsp                ; save call frame pointer.
     109        mov     r11, [NAME(g_pfnKiServiceLinkage) wrt rip]
     110        push    0
     111        push    0
     112        push    r10                     ; call frame pointer (incoming rsp).
     113        pushfq
     114        push    10h
     115        push    r11                     ; r11 = KiServiceLinkage (ret w/ unwind info)
     116        jmp     qword [NAME(g_pfnKiServiceInternal) wrt rip]
     117ENDPROC   supdrvNtQueryVirtualMemory_Xxx
     118%endif
     119
  • trunk/src/VBox/HostDrivers/Support/win/SUPLib-win.cpp

    r49213 r51770  
    3131#ifdef IN_SUP_HARDENED_R3
    3232# undef DEBUG /* Warning: disables RT_STRICT */
     33# undef LOG_DISABLED
    3334# define LOG_DISABLED
    3435  /** @todo RTLOGREL_DISABLED */
     
    3940
    4041#define USE_NT_DEVICE_IO_CONTROL_FILE
    41 #ifdef USE_NT_DEVICE_IO_CONTROL_FILE
    42 # include <iprt/nt/nt-and-windows.h>
    43 #else
    44 # include <Windows.h>
    45 #endif
     42#include <iprt/nt/nt-and-windows.h>
    4643
    4744#include <VBox/sup.h>
     
    5552#include "../SUPLibInternal.h"
    5653#include "../SUPDrvIOC.h"
     54#ifdef VBOX_WITH_HARDENING
     55# include "win/SUPHardenedVerify-win.h"
     56#endif
    5757
    5858
     
    7575*   Internal Functions                                                         *
    7676*******************************************************************************/
     77#ifndef IN_SUP_HARDENED_R3
    7778static int suplibOsCreateService(void);
    7879//unused: static int suplibOsUpdateService(void);
     
    8081static int suplibOsStartService(void);
    8182static int suplibOsStopService(void);
     83#endif
    8284#ifdef USE_NT_DEVICE_IO_CONTROL_FILE
    8385static int suplibConvertNtStatus(NTSTATUS rcNt);
     
    8789
    8890
    89 
    90 
    9191int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted)
    9292{
    9393    /*
    94      * Nothing to do if pre-inited.
     94     * Almost nothing to do if pre-inited.
    9595     */
    9696    if (fPreInited)
     97    {
     98#if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_HARDENED_R3)
     99# ifdef IN_SUP_R3_STATIC
     100        return VERR_NOT_SUPPORTED;
     101# else
     102        supR3HardenedWinInitVersion();
     103        return supHardenedWinInitImageVerifier(NULL);
     104# endif
     105#else
    97106        return VINF_SUCCESS;
     107#endif
     108    }
    98109
    99110    /*
    100111     * Try open the device.
    101112     */
    102     HANDLE hDevice = CreateFile(fUnrestricted ? DEVICE_NAME_SYS : DEVICE_NAME_USR,
    103                                 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
    104                                 NULL,
    105                                 OPEN_EXISTING,
    106                                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
    107                                 NULL);
    108     if (hDevice == INVALID_HANDLE_VALUE)
    109     {
    110113#ifndef IN_SUP_HARDENED_R3
    111         /*
    112          * Try start the service and retry opening it.
    113          */
    114         suplibOsStartService();
    115 
    116         hDevice = CreateFile(fUnrestricted ? DEVICE_NAME_SYS : DEVICE_NAME_USR,
    117                              GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
    118                              NULL,
    119                              OPEN_EXISTING,
    120                              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
    121                              NULL);
    122         if (hDevice == INVALID_HANDLE_VALUE)
    123 #endif /* !IN_SUP_HARDENED_R3 */
    124         {
    125             int rc = GetLastError();
    126             switch (rc)
     114    uint32_t cTry = 0;
     115#endif
     116    HANDLE hDevice;
     117    for (;;)
     118    {
     119        IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     120
     121        static const WCHAR  s_wszName[] = L"\\Device\\VBoxDrvU";
     122        UNICODE_STRING      NtName;
     123        NtName.Buffer        = (PWSTR)s_wszName;
     124        NtName.Length        = sizeof(s_wszName) - sizeof(WCHAR) * (fUnrestricted ? 2 : 1);
     125        NtName.MaximumLength = NtName.Length;
     126
     127        OBJECT_ATTRIBUTES   ObjAttr;
     128        InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
     129
     130        hDevice = RTNT_INVALID_HANDLE_VALUE;
     131
     132        NTSTATUS rcNt = NtCreateFile(&hDevice,
     133                                     GENERIC_READ | GENERIC_WRITE,
     134                                     &ObjAttr,
     135                                     &Ios,
     136                                     NULL /* Allocation Size*/,
     137                                     FILE_ATTRIBUTE_NORMAL,
     138                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
     139                                     FILE_OPEN,
     140                                     FILE_NON_DIRECTORY_FILE,
     141                                     NULL /*EaBuffer*/,
     142                                     0 /*EaLength*/);
     143        if (NT_SUCCESS(rcNt))
     144            rcNt = Ios.Status;
     145        if (!NT_SUCCESS(rcNt))
     146        {
     147#ifndef IN_SUP_HARDENED_R3
     148            /*
     149             * Failed to open, try starting the service and reopen the device
     150             * exactly once.
     151             */
     152            if (cTry == 0 && !NT_SUCCESS(rcNt))
     153            {
     154                cTry++;
     155                suplibOsStartService();
     156                continue;
     157            }
     158#endif
     159            switch (rcNt)
    127160            {
    128161                /** @todo someone must test what is actually returned. */
    129                 case ERROR_DEV_NOT_EXIST:
    130                 case ERROR_DEVICE_NOT_CONNECTED:
    131                 case ERROR_BAD_DEVICE:
    132                 case ERROR_DEVICE_REMOVED:
    133                 case ERROR_DEVICE_NOT_AVAILABLE:
     162                case STATUS_DEVICE_DOES_NOT_EXIST:
     163                case STATUS_DEVICE_NOT_CONNECTED:
     164                //case ERROR_BAD_DEVICE:
     165                case STATUS_DEVICE_REMOVED:
     166                //case ERROR_DEVICE_NOT_AVAILABLE:
    134167                    return VERR_VM_DRIVER_LOAD_ERROR;
    135                 case ERROR_PATH_NOT_FOUND:
    136                 case ERROR_FILE_NOT_FOUND:
     168                case STATUS_OBJECT_PATH_NOT_FOUND:
     169                case STATUS_NO_SUCH_DEVICE:
     170                case STATUS_NO_SUCH_FILE:
     171                case STATUS_OBJECT_NAME_NOT_FOUND:
    137172                    return VERR_VM_DRIVER_NOT_INSTALLED;
    138                 case ERROR_ACCESS_DENIED:
    139                 case ERROR_SHARING_VIOLATION:
     173                case STATUS_ACCESS_DENIED:
     174                case STATUS_SHARING_VIOLATION:
    140175                    return VERR_VM_DRIVER_NOT_ACCESSIBLE;
     176                case STATUS_UNSUCCESSFUL:
     177                    return VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0;
     178                case STATUS_TRUST_FAILURE:
     179                    return VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1;
     180                case STATUS_TOO_LATE:
     181                    return VERR_SUPDRV_HARDENING_EVIL_HANDLE;
    141182                default:
     183
     184                    return rcNt;
    142185                    return VERR_VM_DRIVER_OPEN_ERROR;
    143186            }
    144 
    145             return -1 /** @todo define proper error codes for suplibOsInit failure. */;
    146         }
     187        }
     188        break;
    147189    }
    148190
     
    154196    return VINF_SUCCESS;
    155197}
    156 
    157198
    158199#ifndef IN_SUP_HARDENED_R3
     
    440481            fRc = StartService(hService, 0, NULL);
    441482            DWORD LastError = GetLastError(); NOREF(LastError);
     483#ifndef DEBUG_bird
    442484            AssertMsg(fRc, ("StartService failed with LastError=%Rwa\n", LastError));
     485#endif
    443486        }
    444487
     
    652695    }
    653696
     697    /* See VBoxDrvNtErr2NtStatus. */
     698    if (((uint32_t)rcNt & 0xffff0000) == UINT32_C(0xe9860000)) /** @todo defines for these? */
     699        return (int)((uint32_t)rcNt | UINT32_C(0xffff0000));
     700
    654701    /* Fall back on IPRT for the rest. */
    655702    return RTErrConvertFromNtStatus(rcNt);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette