SUPR3HardenedVerify.cpp revision 3c36c06229c460f138561516170abc867297f256
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/* $Id$ */
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/** @file
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * VirtualBox Support Library - Verification of Hardened Installation.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync */
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copyright (C) 2006-2013 Oracle Corporation
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync *
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * available from http://www.virtualbox.org. This file is free software;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * General Public License (GPL) as published by the Free Software
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync *
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * The contents of this file may alternatively be used under the terms
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * of the Common Development and Distribution License Version 1.0
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * CDDL are applicable instead of those of the GPL.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync *
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * You may elect to license modified versions of this file under the
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * terms and conditions of either the GPL or the CDDL or both.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync */
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/*******************************************************************************
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync* Header Files *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync*******************************************************************************/
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync#if defined(RT_OS_OS2)
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# define INCL_BASE
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# define INCL_ERRORS
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <os2.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <stdio.h>
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync# include <stdlib.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <unistd.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <sys/fcntl.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <sys/errno.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <sys/syslimits.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync#elif defined(RT_OS_WINDOWS)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <Windows.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# ifndef IN_SUP_HARDENED_R3
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <stdio.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# endif
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else /* UNIXes */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <sys/types.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <stdio.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <stdlib.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <dirent.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <dlfcn.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <fcntl.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <limits.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <errno.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <unistd.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# include <sys/stat.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync# include <sys/time.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <sys/fcntl.h>
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# include <pwd.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# ifdef RT_OS_DARWIN
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include <mach-o/dyld.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync# endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#include <VBox/sup.h>
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#include <VBox/err.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#include <iprt/asm.h>
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#include <iprt/ctype.h>
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#include <iprt/param.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#include <iprt/path.h>
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#include <iprt/string.h>
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#include "SUPLibInternal.h"
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# define SUPHNTVI_NO_NT_STUFF
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# include "win/SUPHardenedVerify-win.h"
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#endif
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync/*******************************************************************************
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync* Defined Constants And Macros *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync*******************************************************************************/
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/** The max path length acceptable for a trusted path. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#define SUPR3HARDENED_MAX_PATH 260U
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#ifdef RT_OS_SOLARIS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# define dirfd(d) ((d)->d_fd)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Compare table file names with externally supplied names. */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# define SUP_COMP_FILENAME suplibHardenedStrICmp
0c94a8282c9042b02f022302a3d987746140eab9vboxsync#else
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# define SUP_COMP_FILENAME suplibHardenedStrCmp
0c94a8282c9042b02f022302a3d987746140eab9vboxsync#endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync/*******************************************************************************
0c94a8282c9042b02f022302a3d987746140eab9vboxsync* Global Variables *
0c94a8282c9042b02f022302a3d987746140eab9vboxsync*******************************************************************************/
0c94a8282c9042b02f022302a3d987746140eab9vboxsync/**
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * The files that gets verified.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync *
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * @todo This needs reviewing against the linux packages.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @todo The excessive use of kSupID_SharedLib needs to be reviewed at some point. For
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * the time being we're building the linux packages with SharedLib pointing to
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * AppPrivArch (lazy bird).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c94a8282c9042b02f022302a3d987746140eab9vboxsyncstatic SUPINSTFILE const g_aSupInstallFiles[] =
0c94a8282c9042b02f022302a3d987746140eab9vboxsync{
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* type, dir, fOpt, "pszFile" */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* ---------------------------------------------------------------------- */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VMMR0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VBoxDDR0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VBoxDD2R0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#ifdef VBOX_WITH_RAW_MODE
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VMMGC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VBoxDDGC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VBoxDD2GC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxRT" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxVMM" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxREM" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#if HC_ARCH_BITS == 32
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxREM32" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxREM64" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDD" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDD2" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDDU" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_DEBUGGER_GUI
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxDbg" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxDbg3" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_SHARED_CLIPBOARD
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedClipboard" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#endif
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync//#ifdef VBOX_WITH_SHARED_FOLDERS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedFolders" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_DRAG_AND_DROP
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxDragAndDropSvc" SUPLIB_DLL_SUFF },
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync//#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_GUEST_PROPS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxGuestPropSvc" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_GUEST_CONTROL
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxGuestControlSvc" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxHostChannel" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedCrOpenGL" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLhostcrutil" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLhosterrorspu" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLrenderspu" SUPLIB_DLL_SUFF },
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxManage" SUPLIB_EXE_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#ifdef VBOX_WITH_MAIN
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Exe, kSupID_AppBin, false, "VBoxSVC" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync #ifdef RT_OS_WINDOWS
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync #else
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppPrivArch, false, "VBoxXPCOMIPCD" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxXPCOM" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxXPCOMIPCC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxSVCM" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Data, kSupID_AppPrivArchComp, false, "VBoxXPCOMBase.xpt" },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync #endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync#endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VRDPAuth" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxAuth" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxVRDP" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_HEADLESS
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxHeadless" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxHeadless" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxVideoRecFB" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_QTGUI
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VirtualBox" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VirtualBox" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# if !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxKeyboard" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#endif
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_VBOXSDL
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxSDL" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSDL" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#ifdef VBOX_WITH_WEBSERVICES
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "vboxwebsrv" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#ifdef RT_OS_LINUX
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxTunctl" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#ifdef VBOX_WITH_NETFLT
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxNetDHCP" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxNetDHCP" SUPLIB_DLL_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync//#endif
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync//#ifdef VBOX_WITH_LWIP_NAT
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxNetNAT" SUPLIB_EXE_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxNetNAT" SUPLIB_DLL_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync//#endif
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#if defined(VBOX_WITH_HARDENING) && defined(RT_OS_WINDOWS)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# define HARDENED_TESTCASE_BIN_ENTRY(a_szName) \
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_TestExe, kSupID_AppBin, true, a_szName SUPLIB_EXE_SUFF }, \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestDll, kSupID_AppBin, true, a_szName SUPLIB_DLL_SUFF }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstMicro"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstPDMAsyncCompletion"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstPDMAsyncCompletionStress"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstVMM"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstVMREQ"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync# define HARDENED_TESTCASE_ENTRY(a_szName) \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestExe, kSupID_Testcase, true, a_szName SUPLIB_EXE_SUFF }, \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestDll, kSupID_Testcase, true, a_szName SUPLIB_DLL_SUFF }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstCFGM"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstIntNet-1"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstMMHyperHeap"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstR0ThreadPreemptionDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstRTR0MemUserKernelDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstRTR0SemMutexDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstRTR0TimerDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstSSM"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync};
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync/** Array parallel to g_aSupInstallFiles containing per-file status info. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic SUPVERIFIEDFILE g_aSupVerifiedFiles[RT_ELEMENTS(g_aSupInstallFiles)];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync/** Array index by install directory specifier containing info about verified directories. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic SUPVERIFIEDDIR g_aSupVerifiedDirs[kSupID_End];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync/**
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Assembles the path to a directory.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync *
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @returns VINF_SUCCESS on success, some error code on failure (fFatal
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * decides whether it returns or not).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync *
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param enmDir The directory.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param pszDst Where to assemble the path.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param cchDst The size of the buffer.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param fFatal Whether failures should be treated as fatal (true) or not (false).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedMakePath(SUPINSTDIR enmDir, char *pszDst, size_t cchDst, bool fFatal)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync switch (enmDir)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_AppBin: /** @todo fix this AppBin crap (uncertain wtf some binaries actually are installed). */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_Bin:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathExecDir(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync break;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_SharedLib:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathSharedLibs(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync break;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_AppPrivArch:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathAppPrivateArch(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync break;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_AppPrivArchComp:
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathAppPrivateArch(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync size_t off = suplibHardenedStrLen(pszDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (cchDst - off >= sizeof("/components"))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync suplibHardenedMemCopy(&pszDst[off], "/components", sizeof("/components"));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = VERR_BUFFER_OVERFLOW;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync break;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync case kSupID_AppPrivNoArch:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedPathAppPrivateNoArch(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync break;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_Testcase:
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supR3HardenedPathExecDir(pszDst, cchDst);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_SUCCESS(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync size_t off = suplibHardenedStrLen(pszDst);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (cchDst - off >= sizeof("/testcase"))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync suplibHardenedMemCopy(&pszDst[off], "/testcase", sizeof("/testcase"));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = VERR_BUFFER_OVERFLOW;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync break;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync default:
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedMakePath: enmDir=%d\n", enmDir);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_FAILURE(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync supR3HardenedError(rc, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedMakePath: enmDir=%d rc=%d\n", enmDir, rc);
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync return rc;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Assembles the path to a file table entry, with or without the actual filename.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VINF_SUCCESS on success, some error code on failure (fFatal
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * decides whether it returns or not).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pFile The file table entry.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszDst Where to assemble the path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param cchDst The size of the buffer.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fWithFilename If set, the filename is included, otherwise it is omitted (no trailing slash).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fFatal Whether failures should be treated as fatal (true) or not (false).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedMakeFilePath(PCSUPINSTFILE pFile, char *pszDst, size_t cchDst, bool fWithFilename, bool fFatal)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Combine supR3HardenedMakePath and the filename.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = supR3HardenedMakePath(pFile->enmDir, pszDst, cchDst, fFatal);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_SUCCESS(rc) && fWithFilename)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t cchFile = suplibHardenedStrLen(pFile->pszFile);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t off = suplibHardenedStrLen(pszDst);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (cchDst - off >= cchFile + 2)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszDst[off++] = '/';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync suplibHardenedMemCopy(&pszDst[off], pFile->pszFile, cchFile + 1);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supR3HardenedError(VERR_BUFFER_OVERFLOW, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedMakeFilePath: pszFile=%s off=%lu\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync pFile->pszFile, (long)off);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return rc;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync}
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync/**
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Verifies a directory.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync *
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fFatal is clear and if it's set the function wont return.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param enmDir The directory specifier.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFixedDir(SUPINSTDIR enmDir, bool fFatal)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync{
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Validate the index just to be on the safe side...
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (enmDir <= kSupID_Invalid || enmDir >= kSupID_End)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyDir: enmDir=%d\n", enmDir);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /*
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Already validated?
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (g_aSupVerifiedDirs[enmDir].fValidated)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return VINF_SUCCESS; /** @todo revalidate? */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* initialize the entry. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (g_aSupVerifiedDirs[enmDir].hDir != 0)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyDir: hDir=%p enmDir=%d\n",
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync (void *)g_aSupVerifiedDirs[enmDir].hDir, enmDir);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync g_aSupVerifiedDirs[enmDir].hDir = -1;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync g_aSupVerifiedDirs[enmDir].fValidated = false;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Make the path and open the directory.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync char szPath[RTPATH_MAX];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = supR3HardenedMakePath(enmDir, szPath, sizeof(szPath), fFatal);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_SUCCESS(rc))
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync#if defined(RT_OS_WINDOWS)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync PRTUTF16 pwszPath;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync rc = RTStrToUtf16(szPath, &pwszPath);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if (RT_SUCCESS(rc))
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync HANDLE hDir = CreateFileW(pwszPath,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync GENERIC_READ,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync NULL,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync OPEN_EXISTING,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync NULL);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if (hDir != INVALID_HANDLE_VALUE)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /** @todo check the type */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* That's all on windows, for now at least... */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync g_aSupVerifiedDirs[enmDir].hDir = (intptr_t)hDir;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync g_aSupVerifiedDirs[enmDir].fValidated = true;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else if (enmDir == kSupID_Testcase)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync g_aSupVerifiedDirs[enmDir].fValidated = true;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = VINF_SUCCESS; /* Optional directory, ignore if missing. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int err = GetLastError();
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyDir: Failed to open \"%s\": err=%d\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, err);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync RTUtf16Free(pwszPath);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supR3HardenedError(rc, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyDir: Failed to convert \"%s\" to UTF-16: err=%d\n", szPath, rc);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync#else /* UNIXY */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int fd = open(szPath, O_RDONLY, 0);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (fd >= 0)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On unixy systems we'll make sure the directory is owned by root
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * and not writable by the group and user.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync struct stat st;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (!fstat(fd, &st))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync if ( st.st_uid == 0
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync && !(st.st_mode & (S_IWGRP | S_IWOTH))
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync && S_ISDIR(st.st_mode))
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync g_aSupVerifiedDirs[enmDir].hDir = fd;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync g_aSupVerifiedDirs[enmDir].fValidated = true;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync {
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (!S_ISDIR(st.st_mode))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_NOT_A_DIRECTORY, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: \"%s\" is not a directory\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync szPath, (long)st.st_uid);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else if (st.st_uid)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Cannot trust the directory \"%s\": not owned by root (st_uid=%ld)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync szPath, (long)st.st_uid);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Cannot trust the directory \"%s\": group and/or other writable (st_mode=0%lo)\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync szPath, (long)st.st_mode);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync close(fd);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync int err = errno;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Failed to fstat \"%s\": %s (%d)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync szPath, strerror(err), err);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync close(fd);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else if (enmDir == kSupID_Testcase)
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync {
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync g_aSupVerifiedDirs[enmDir].fValidated = true;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = VINF_SUCCESS; /* Optional directory, ignore if missing. */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int err = errno;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyDir: Failed to open \"%s\": %s (%d)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync szPath, strerror(err), err);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync#endif /* UNIXY */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return rc;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync}
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync#ifdef RT_OS_WINDOWS
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync/**
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Opens the file for verification.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync *
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * fFatal is clear and if it's set the function wont return.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param pFile The file entry.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param fFatal Whether validation failures should be treated as
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * kl fatal (true) or not (false).
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param phFile The file handle, set to -1 if we failed to open
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * the file. The function may return VINF_SUCCESS
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * and a -1 handle if the file is optional.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedVerifyFileOpen(PCSUPINSTFILE pFile, bool fFatal, intptr_t *phFile)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync{
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync *phFile = -1;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync char szPath[RTPATH_MAX];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = supR3HardenedMakeFilePath(pFile, szPath, sizeof(szPath), true /*fWithFilename*/, fFatal);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync PRTUTF16 pwszPath;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = RTStrToUtf16(szPath, &pwszPath);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HANDLE hFile = CreateFileW(pwszPath,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync GENERIC_READ,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync FILE_SHARE_READ,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync NULL,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync OPEN_EXISTING,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync FILE_ATTRIBUTE_NORMAL,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync NULL);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (hFile)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync *phFile = (intptr_t)hFile;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = VINF_SUCCESS;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int err = GetLastError();
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if ( !pFile->fOptional
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync || ( err != ERROR_FILE_NOT_FOUND
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync && (err != ERROR_PATH_NOT_FOUND || pFile->enmDir != kSupID_Testcase) ) )
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync "supR3HardenedVerifyFileInternal: Failed to open '%s': err=%d\n", szPath, err);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync }
0c94a8282c9042b02f022302a3d987746140eab9vboxsync RTUtf16Free(pwszPath);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
0c94a8282c9042b02f022302a3d987746140eab9vboxsync rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: Failed to convert '%s' to UTF-16: %Rrc\n",
0c94a8282c9042b02f022302a3d987746140eab9vboxsync szPath, rc);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return rc;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync}
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync/**
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Worker for supR3HardenedVerifyFileInternal.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fFatal is clear and if it's set the function wont return.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pFile The file entry.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param pVerified The verification record.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fLeaveFileOpen Whether the file should be left open.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedVerifyFileSignature(PCSUPINSTFILE pFile, PSUPVERIFIEDFILE pVerified, bool fFatal, bool fLeaveFileOpen)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync{
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync# if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_R3_STATIC) /* Latter: Not in VBoxCpuReport and friends. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Open the file if we have to.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync intptr_t hFileOpened;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync intptr_t hFile = pVerified->hFile;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (hFile != -1)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync hFileOpened = -1;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedVerifyFileOpen(pFile, fFatal, &hFileOpened);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_FAILURE(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return rc;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync hFile = hFileOpened;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /*
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Verify the signature.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync char szErr[1024];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync RTERRINFO ErrInfo;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync RTErrInfoInit(&ErrInfo, szErr, sizeof(szErr));
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync uint32_t fFlags = SUPHNTVI_F_REQUIRE_BUILD_CERT;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (pFile->enmType == kSupIFT_Rc)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync fFlags |= SUPHNTVI_F_RC_IMAGE;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supHardenedWinVerifyImageByHandleNoName((HANDLE)hFile, fFlags, &ErrInfo);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->fCheckedSignature = true;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->fCheckedSignature = false;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: '%s': Image verify error rc=%Rrc: %s\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pFile->pszFile, rc, szErr);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /*
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Close the handle if we opened the file and we should close it.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (hFileOpened != -1)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (fLeaveFileOpen && RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->hFile = hFileOpened;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync else
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync CloseHandle((HANDLE)hFileOpened);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return rc;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync# else /* Not checking signatures. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return VINF_SUCCESS;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync# endif /* Not checking signatures. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync#endif
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync/**
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a file entry.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * fFatal is clear and if it's set the function wont return.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param iFile The file table index of the file to be verified.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * fatal (true) or not (false).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param fLeaveFileOpen Whether the file should be left open.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fVerifyAll Set if this is an verify all call and we will
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * postpone signature checking.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncstatic int supR3HardenedVerifyFileInternal(int iFile, bool fFatal, bool fLeaveFileOpen, bool fVerifyAll)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync{
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync PCSUPINSTFILE pFile = &g_aSupInstallFiles[iFile];
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync PSUPVERIFIEDFILE pVerified = &g_aSupVerifiedFiles[iFile];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /*
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Already done validation? Do signature validation if we haven't yet.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (pVerified->fValidated)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /** @todo revalidate? Check that the file hasn't been replace or similar. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#ifdef RT_OS_WINDOWS
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (!pVerified->fCheckedSignature && !fVerifyAll)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return supR3HardenedVerifyFileSignature(pFile, pVerified, fFatal, fLeaveFileOpen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return VINF_SUCCESS;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* initialize the entry. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (pVerified->hFile != 0)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync "supR3HardenedVerifyFileInternal: hFile=%p (%s)\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync (void *)pVerified->hFile, pFile->pszFile);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->hFile = -1;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->fValidated = false;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#ifdef RT_OS_WINDOWS
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->fCheckedSignature = false;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync#endif
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /*
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Verify the directory then proceed to open it.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * (This'll make sure the directory is opened and that we can (later)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * use openat if we wish.)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = supR3HardenedVerifyFixedDir(pFile->enmDir, fFatal);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (RT_SUCCESS(rc))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#if defined(RT_OS_WINDOWS)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedVerifyFileOpen(pFile, fFatal, &pVerified->hFile);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (RT_SUCCESS(rc))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!fVerifyAll)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedVerifyFileSignature(pFile, pVerified, fFatal, fLeaveFileOpen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (RT_SUCCESS(rc))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync pVerified->fValidated = true;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!fLeaveFileOpen)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync CloseHandle((HANDLE)pVerified->hFile);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync pVerified->hFile = -1;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#else /* !RT_OS_WINDOWS */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync char szPath[RTPATH_MAX];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedMakeFilePath(pFile, szPath, sizeof(szPath), true /*fWithFilename*/, fFatal);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (RT_SUCCESS(rc))
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int fd = open(szPath, O_RDONLY, 0);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if (fd >= 0)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync {
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync /*
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * On unixy systems we'll make sure the file is owned by root
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * and not writable by the group and user.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync struct stat st;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!fstat(fd, &st))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync if ( st.st_uid == 0
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync && !(st.st_mode & (S_IWGRP | S_IWOTH))
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync && S_ISREG(st.st_mode))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* it's valid. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (fLeaveFileOpen)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync pVerified->hFile = fd;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync close(fd);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync pVerified->fValidated = true;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!S_ISREG(st.st_mode))
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_IS_A_DIRECTORY, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: \"%s\" is not a regular file\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, (long)st.st_uid);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else if (st.st_uid)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Cannot trust the file \"%s\": not owned by root (st_uid=%ld)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, (long)st.st_uid);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Cannot trust the file \"%s\": group and/or other writable (st_mode=0%lo)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, (long)st.st_mode);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync close(fd);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync int err = errno;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Failed to fstat \"%s\": %s (%d)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, strerror(err), err);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync close(fd);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync else
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync {
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync int err = errno;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (!pFile->fOptional || err != ENOENT)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Failed to open \"%s\": %s (%d)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync szPath, strerror(err), err);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#endif /* !RT_OS_WINDOWS */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync return rc;
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync}
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync/**
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Verifies that the specified table entry matches the given filename.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync *
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @returns VINF_SUCCESS if matching. On mismatch fFatal indicates whether an
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * error is returned or we terminate the application.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync *
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @param iFile The file table index.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @param pszFilename The filename.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fFatal Whether validation failures should be treated as
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync * fatal (true) or not (false).
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncstatic int supR3HardenedVerifySameFile(int iFile, const char *pszFilename, bool fFatal)
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync{
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync PCSUPINSTFILE pFile = &g_aSupInstallFiles[iFile];
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync /*
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * Construct the full path for the file table entry
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * and compare it with the specified file.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync */
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync char szName[RTPATH_MAX];
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync int rc = supR3HardenedMakeFilePath(pFile, szName, sizeof(szName), true /*fWithFilename*/, fFatal);
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync if (RT_FAILURE(rc))
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync return rc;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if (SUP_COMP_FILENAME(szName, pszFilename))
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync {
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync /*
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Normalize the two paths and compare again.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = VERR_NOT_SAME_DEVICE;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#if defined(RT_OS_WINDOWS)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync LPSTR pszIgnored;
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync char szName2[RTPATH_MAX];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if ( GetFullPathName(szName, RT_ELEMENTS(szName2), &szName2[0], &pszIgnored)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync && GetFullPathName(pszFilename, RT_ELEMENTS(szName), &szName[0], &pszIgnored))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (!SUP_COMP_FILENAME(szName2, szName))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = VINF_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync AssertCompile(RTPATH_MAX >= PATH_MAX);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync char szName2[RTPATH_MAX];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( realpath(szName, szName2) != NULL
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync && realpath(pszFilename, szName) != NULL)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (!SUP_COMP_FILENAME(szName2, szName))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = VINF_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_FAILURE(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync supR3HardenedMakeFilePath(pFile, szName, sizeof(szName), true /*fWithFilename*/, fFatal);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedError(rc, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedVerifySameFile: \"%s\" isn't the same as \"%s\"\n",
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszFilename, szName);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check more stuff like the stat info if it's an already open file?
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return VINF_SUCCESS;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync/**
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a file.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * VERR_NOT_FOUND if the file isn't in the table, this isn't ever a fatal error.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On verification failure, an error code will be returned when fFatal is clear,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * otherwise the program will be terminated.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pszFilename The filename.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFixedFile(const char *pszFilename, bool fFatal)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync{
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Lookup the file and check if it's the same file.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync const char *pszName = supR3HardenedPathFilename(pszFilename);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (!SUP_COMP_FILENAME(pszName, g_aSupInstallFiles[iFile].pszFile))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = supR3HardenedVerifySameFile(iFile, pszFilename, fFatal);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (RT_SUCCESS(rc))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, false /* fLeaveFileOpen */, false /* fVerifyAll */);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return rc;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return VERR_NOT_FOUND;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync/**
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a program, worker for supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pszProgName See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fLeaveOpen The leave open setting used by
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncstatic int supR3HardenedVerifyProgram(const char *pszProgName, bool fFatal, bool fLeaveOpen)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync{
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Search the table looking for the executable and the DLL/DYLIB/SO.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = VINF_SUCCESS;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync bool fExe = false;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync bool fDll = false;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync size_t const cchProgName = suplibHardenedStrLen(pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (!suplibHardenedStrNCmp(pszProgName, g_aSupInstallFiles[iFile].pszFile, cchProgName))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if ( ( g_aSupInstallFiles[iFile].enmType == kSupIFT_Dll
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync || g_aSupInstallFiles[iFile].enmType == kSupIFT_TestDll)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync && !suplibHardenedStrCmp(&g_aSupInstallFiles[iFile].pszFile[cchProgName], SUPLIB_DLL_SUFF))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* This only has to be found (once). */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (fDll)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: duplicate DLL entry for \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, false /* fVerifyAll */);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync fDll = true;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else if ( ( g_aSupInstallFiles[iFile].enmType == kSupIFT_Exe
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync || g_aSupInstallFiles[iFile].enmType == kSupIFT_TestExe)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync && !suplibHardenedStrCmp(&g_aSupInstallFiles[iFile].pszFile[cchProgName], SUPLIB_EXE_SUFF))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Here we'll have to check that the specific program is the same as the entry. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (fExe)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: duplicate EXE entry for \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, false /* fVerifyAll */);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync fExe = true;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync char szFilename[RTPATH_MAX];
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc2 = supR3HardenedPathExecDir(szFilename, sizeof(szFilename) - cchProgName - sizeof(SUPLIB_EXE_SUFF));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (RT_SUCCESS(rc2))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync suplibHardenedStrCat(szFilename, "/");
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync suplibHardenedStrCat(szFilename, g_aSupInstallFiles[iFile].pszFile);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync supR3HardenedVerifySameFile(iFile, szFilename, fFatal);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = supR3HardenedError(rc2, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: failed to query program path: rc=%d\n", rc2);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync }
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Check the findings.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (RT_SUCCESS(rc))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync {
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (!fDll && !fExe)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_NOT_FOUND, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: Couldn't find the program \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else if (!fExe)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_NOT_FOUND, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: Couldn't find the EXE entry for \"%s\"\n", pszProgName);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync else if (!fDll)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_NOT_FOUND, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyProgram: Couldn't find the DLL entry for \"%s\"\n", pszProgName);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync }
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return rc;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync/**
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies all the known files (called from SUPR3HardenedMain).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On verification failure, an error code will be returned when fFatal is clear,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * otherwise the program will be terminated.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync *
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fFatal Whether validation failures should be treated as
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * fatal (true) or not (false).
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param pszProgName The program name. This is used to verify that
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync * both the executable and corresponding
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync * DLL/DYLIB/SO are valid.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncDECLHIDDEN(int) supR3HardenedVerifyAll(bool fFatal, const char *pszProgName)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync{
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /*
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On windows
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync#if defined(RT_OS_WINDOWS)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync bool fLeaveOpen = true;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync#else
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync bool fLeaveOpen = false;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync#endif
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync /*
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * The verify all the files.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc = VINF_SUCCESS;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync {
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc2 = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, true /* fVerifyAll */);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = rc2;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync }
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync /*
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Verify the program name, that is to say, check that it's in the table
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * (thus verified above) and verify the signature on platforms where we
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * sign things.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc2 = supR3HardenedVerifyProgram(pszProgName, fFatal, fLeaveOpen);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc2 = rc;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync return rc;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync}
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync/**
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Copies the N messages into the error buffer and returns @a rc.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param cMsgs The number of messages in the ellipsis.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param ... Message parts.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetErrorN(int rc, PRTERRINFO pErrInfo, unsigned cMsgs, ...)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (pErrInfo)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t cbErr = pErrInfo->cbMsg;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync char *pszErr = pErrInfo->pszMsg;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync va_list va;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync va_start(va, cMsgs);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync while (cMsgs-- > 0 && cbErr > 0)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync const char *pszMsg = va_arg(va, const char *);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t cchMsg = VALID_PTR(pszMsg) ? suplibHardenedStrLen(pszMsg) : 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (cchMsg >= cbErr)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync cchMsg = cbErr - 1;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync suplibHardenedMemCopy(pszErr, pszMsg, cchMsg);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszErr[cchMsg] = '\0';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszErr += cchMsg;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync cbErr -= cchMsg;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync va_end(va);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pErrInfo->rc = rc;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pErrInfo->fFlags |= RTERRINFO_FLAGS_SET;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return rc;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the three messages into the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg1 The first message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg2 The second message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg3 The third message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync const char *pszMsg2, const char *pszMsg3)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#ifdef SOME_UNUSED_FUNCTION
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the two messages into the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg1 The first message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg2 The second message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync const char *pszMsg2)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 2, pszMsg1, pszMsg2);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the error message to the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg The message.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError(int rc, PRTERRINFO pErrInfo, const char *pszMsg)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 1, pszMsg);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif /* SOME_UNUSED_FUNCTION */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Output from a successfull supR3HardenedVerifyPathSanity call.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef struct SUPR3HARDENEDPATHINFO
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /** The length of the path in szCopy. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uint16_t cch;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** The number of path components. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uint16_t cComponents;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** Set if the path ends with slash, indicating that it's a directory
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * reference and not a file reference. The slash has been removed from
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * the copy. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync bool fDirSlash;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** The offset where each path component starts, i.e. the char after the
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * slash. The array has cComponents + 1 entries, where the final one is
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * cch + 1 so that one can always terminate the current component by
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * szPath[aoffComponent[i] - 1] = '\0'. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uint16_t aoffComponents[32+1];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** A normalized copy of the path.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Reserve some extra space so we can be more relaxed about overflow
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * checks and terminator paddings, especially when recursing. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync char szPath[SUPR3HARDENED_MAX_PATH * 2];
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync} SUPR3HARDENEDPATHINFO;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync/** Pointer to a parsed path. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsynctypedef SUPR3HARDENEDPATHINFO *PSUPR3HARDENEDPATHINFO;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync/**
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Verifies that the path is absolutely sane, it also parses the path.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync *
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * A sane path starts at the root (w/ drive letter on DOS derived systems) and
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * does not have any relative bits (/../) or unnecessary slashes (/bin//ls).
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Sane paths are less or equal to SUPR3HARDENED_MAX_PATH bytes in length. UNC
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * paths are not supported.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync *
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @returns VBox status code.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pszPath The path to check.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pErrInfo The error info structure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pInfo Where to return a copy of the path along with
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * parsing information.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsyncstatic int supR3HardenedVerifyPathSanity(const char *pszPath, PRTERRINFO pErrInfo, PSUPR3HARDENEDPATHINFO pInfo)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync{
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync const char *pszSrc = pszPath;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync char *pszDst = pInfo->szPath;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check that it's an absolute path and copy the volume/root specifier.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( !RT_C_IS_ALPHA(pszSrc[0])
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || pszSrc[1] != ':'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || !RTPATH_IS_SLASH(pszSrc[2]))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *pszDst++ = RT_C_TO_UPPER(pszSrc[0]);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *pszDst++ = ':';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *pszDst++ = RTPATH_SLASH;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync pszSrc += 3;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (!RTPATH_IS_SLASH(pszSrc[0]))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *pszDst++ = RTPATH_SLASH;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszSrc += 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * No path specifying the root or something very shortly thereafter will
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * be approved of.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (pszSrc[0] == '\0')
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_IS_ROOT, pErrInfo, "The path is root: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( pszSrc[1] == '\0'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || pszSrc[2] == '\0')
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_SHORT, pErrInfo, "The path is too short: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /*
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Check each component. No parent references or double slashes.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync pInfo->cComponents = 0;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync pInfo->fDirSlash = false;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync while (pszSrc[0])
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync {
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /* Sanity checks. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RTPATH_IS_SLASH(pszSrc[0])) /* can be relaxed if we care. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_CLEAN, pErrInfo,
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync "The path is not clean of double slashes: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if ( pszSrc[0] == '.'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync && pszSrc[1] == '.'
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync && RTPATH_IS_SLASH(pszSrc[2]))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The path is not absolute: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Record the start of the component. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (pInfo->cComponents >= RT_ELEMENTS(pInfo->aoffComponents) - 1)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_MANY_COMPONENTS, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The path has too many components: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->aoffComponents[pInfo->cComponents++] = pszDst - &pInfo->szPath[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Traverse to the end of the component, copying it as we go along. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync while (pszSrc[0])
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RTPATH_IS_SLASH(pszSrc[0]))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszSrc++;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (*pszSrc)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *pszDst++ = RTPATH_SLASH;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->fDirSlash = true;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync break;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *pszDst++ = *pszSrc++;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ((uintptr_t)(pszDst - &pInfo->szPath[0]) >= SUPR3HARDENED_MAX_PATH)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The path is too long: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Terminate the string and enter its length. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszDst[0] = '\0';
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pszDst[1] = '\0'; /* for aoffComponents */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->cch = (uint16_t)(pszDst - &pInfo->szPath[0]);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->aoffComponents[pInfo->cComponents] = pInfo->cch + 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return VINF_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * The state information collected by supR3HardenedVerifyFsObject.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * This can be used to verify that a directory we've opened for enumeration is
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * the same as the one that supR3HardenedVerifyFsObject just verified. It can
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * equally be used to verify a native specfied by the user.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef struct SUPR3HARDENEDFSOBJSTATE
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#ifdef RT_OS_WINDOWS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /** Not implemented for windows yet. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync char chTodo;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#else
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** The stat output. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync struct stat Stat;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync} SUPR3HARDENEDFSOBJSTATE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Pointer to a file system object state. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef SUPR3HARDENEDFSOBJSTATE *PSUPR3HARDENEDFSOBJSTATE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Pointer to a const file system object state. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef SUPR3HARDENEDFSOBJSTATE const *PCSUPR3HARDENEDFSOBJSTATE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Query information about a file system object by path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VBox status code, error buffer filled on failure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszPath The path to the object.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pFsObjState Where to return the state information.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedQueryFsObjectByPath(char const *pszPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState, PRTERRINFO pErrInfo)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync#if defined(RT_OS_WINDOWS)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /** @todo Windows hardening. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync pFsObjState->chTodo = 0;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return VINF_SUCCESS;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync#else
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /*
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Stat the object, do not follow links.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (lstat(pszPath, &pFsObjState->Stat) != 0)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync {
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /* Ignore access errors */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (errno != EACCES)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_STAT_FAILED, pErrInfo,
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync 5, "stat failed with ", strerror(errno), " on: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync }
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /*
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Read ACLs.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /** @todo */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return VINF_SUCCESS;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync#endif
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync}
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync/**
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Query information about a file system object by native handle.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync *
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * @returns VBox status code, error buffer filled on failure.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * @param hNative The native handle to the object @a pszPath
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * specifies and this should be verified to be the
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * same file system object.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState Where to return the state information.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object. (For the error message
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * only.)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedQueryFsObjectByHandle(RTHCUINTPTR hNative, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync char const *pszPath, PRTERRINFO pErrInfo)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#if defined(RT_OS_WINDOWS)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync pFsObjState->chTodo = 0;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Stat the object, do not follow links.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (fstat((int)hNative, &pFsObjState->Stat) != 0)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_STAT_FAILED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 5, "fstat failed with ", strerror(errno), " on '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Read ACLs.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#endif
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync}
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/**
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies that the file system object indicated by the native handle is the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same as the one @a pFsObjState indicates.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState1 File system object information/state by path.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState2 File system object information/state by handle.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object @a pFsObjState
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * describes. (For the error message.)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pErrInfo The error info structure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsyncstatic int supR3HardenedIsSameFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState1, PCSUPR3HARDENEDFSOBJSTATE pFsObjState2,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync const char *pszPath, PRTERRINFO pErrInfo)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync{
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync#if defined(RT_OS_WINDOWS)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** @todo Windows hardening. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return VINF_SUCCESS;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync#elif defined(RT_OS_OS2)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return VINF_SUCCESS;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync#else
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Compare the ino+dev, then the uid+gid and finally the important mode
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * bits. Technically the first one should be enough, but we're paranoid.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( pFsObjState1->Stat.st_ino != pFsObjState2->Stat.st_ino
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync || pFsObjState1->Stat.st_dev != pFsObjState2->Stat.st_dev)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (ino/dev)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( pFsObjState1->Stat.st_uid != pFsObjState2->Stat.st_uid
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync || pFsObjState1->Stat.st_gid != pFsObjState2->Stat.st_gid)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (uid/gid)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( (pFsObjState1->Stat.st_mode & (S_IFMT | S_IWUSR | S_IWGRP | S_IWOTH))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync != (pFsObjState2->Stat.st_mode & (S_IFMT | S_IWUSR | S_IWGRP | S_IWOTH)))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (mode)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#endif
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync}
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/**
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies a file system object (file or directory).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState The file system object information/state to be
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * verified.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fDir Whether this is a directory or a file.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRelaxed Whether we can be more relaxed about this
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * directory (only used for grand parent
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * directories).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object. For error messages and
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * securing a couple of hacks.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync const char *pszPath, PRTERRINFO pErrInfo)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#if defined(RT_OS_WINDOWS)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(pFsObjState); NOREF(fDir); NOREF(fRelaxed); NOREF(pszPath); NOREF(pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#elif defined(RT_OS_OS2)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* No hardening here - it's a single user system. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(pFsObjState); NOREF(fDir); NOREF(fRelaxed); NOREF(pszPath); NOREF(pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The owner must be root.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * This can be extended to include predefined system users if necessary.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (pFsObjState->Stat.st_uid != 0)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_OWNER_NOT_ROOT, pErrInfo, "The owner is not root: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The object type must be directory or file, no symbolic links or other
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * risky stuff (sorry dude, but we're paranoid on purpose here).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( !S_ISDIR(pFsObjState->Stat.st_mode)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync && !S_ISREG(pFsObjState->Stat.st_mode))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (S_ISLNK(pFsObjState->Stat.st_mode))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Symlinks are not permitted: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Not regular file or directory: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (fDir != !!S_ISDIR(pFsObjState->Stat.st_mode))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (S_ISDIR(pFsObjState->Stat.st_mode))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Expected file but found directory: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Expected directory but found file: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The group does not matter if it does not have write access, if it has
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * write access it must be group 0 (root/wheel/whatever).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * This can be extended to include predefined system groups or groups that
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * only root is member of.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( (pFsObjState->Stat.st_mode & S_IWGRP)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync && pFsObjState->Stat.st_gid != 0)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#ifdef RT_OS_DARWIN
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* HACK ALERT: On Darwin /Applications is root:admin with admin having
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync full access. So, to work around we relax the hardening a bit and
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync permit grand parents and beyond to be group writable by admin. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo dynamically resolve the admin group? */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 80 /*admin*/ || suplibHardenedStrCmp(pszPath, "/Applications");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#elif defined(RT_OS_FREEBSD)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* HACK ALERT: PC-BSD 9 has group-writable /usr/pib directory which is
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync similar to /Applications on OS X (see above).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync On FreeBSD root is normally the only member of this group, on
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync PC-BSD the default user is a member. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo dynamically resolve the operator group? */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 5 /*operator*/ || suplibHardenedStrCmp(pszPath, "/usr/pbi");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(fRelaxed);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(fRelaxed);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = true;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#endif
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (fBad)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_WRITE_NON_SYS_GROUP, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The group is not a system group and it has write access to '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * World must not have write access. There is no relaxing this rule.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (pFsObjState->Stat.st_mode & S_IWOTH)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_WORLD_WRITABLE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "World writable: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Check the ACLs.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#endif
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync}
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/**
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies that the file system object indicated by the native handle is the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same as the one @a pFsObjState indicates.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param hNative The native handle to the object @a pszPath
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * specifies and this should be verified to be the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same file system object.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState The information/state returned by a previous
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * query call.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object @a pFsObjState
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * describes. (For the error message.)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifySameFsObject(RTHCUINTPTR hNative, PCSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync const char *pszPath, PRTERRINFO pErrInfo)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync SUPR3HARDENEDFSOBJSTATE FsObjState2;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync int rc = supR3HardenedQueryFsObjectByHandle(hNative, &FsObjState2, pszPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (RT_SUCCESS(rc))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedIsSameFsObject(pFsObjState, &FsObjState2, pszPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return rc;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync}
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/**
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Does the recursive directory enumeration.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszDirPath The path buffer containing the subdirectory to
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * enumerate followed by a slash (this is never
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * the root slash). The buffer is RTPATH_MAX in
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * size and anything starting at @a cchDirPath
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * - 1 and beyond is scratch space.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param cchDirPath The length of the directory path + slash.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState Pointer to the file system object state buffer.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * On input this will hold the stats for
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * the directory @a pszDirPath indicates and will
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * be used to verified that we're opening the same
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * thing.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRecursive Whether to recurse into subdirectories.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifyDirRecursive(char *pszDirPath, size_t cchDirPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fRecursive, PRTERRINFO pErrInfo)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#if defined(RT_OS_WINDOWS)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#elif defined(RT_OS_OS2)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* No hardening here - it's a single user system. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Open the directory. Now, we could probably eliminate opendir here
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * and go down on kernel API level (open + getdents for instance), however
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * that's not very portable and hopefully not necessary.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync DIR *pDir = opendir(pszDirPath);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (!pDir)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* Ignore access errors. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (errno == EACCES)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_DIR_ENUM_FAILED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 5, "opendir failed with ", strerror(errno), " on '", pszDirPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (dirfd(pDir) != -1)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync int rc = supR3HardenedVerifySameFsObject(dirfd(pDir), pFsObjState, pszDirPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (RT_FAILURE(rc))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync {
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync closedir(pDir);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return rc;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync }
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync }
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Enumerate the directory, check all the requested bits.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync int rc = VINF_SUCCESS;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync for (;;)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync {
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync pszDirPath[cchDirPath] = '\0'; /* for error messages. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync struct dirent Entry;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync struct dirent *pEntry;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync int iErr = readdir_r(pDir, &Entry, &pEntry);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if (iErr)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync {
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedSetErrorN(VERR_SUPLIB_DIR_ENUM_FAILED, pErrInfo,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync 5, "readdir_r failed with ", strerror(iErr), " in '", pszDirPath, "'");
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync break;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync }
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if (!pEntry)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync break;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Check the length and copy it into the path buffer so it can be
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * stat()'ed.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync size_t cchName = suplibHardenedStrLen(pEntry->d_name);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if (cchName + cchDirPath > SUPR3HARDENED_MAX_PATH)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedSetErrorN(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync 4, "Path grew too long during recursion: '", pszDirPath, pEntry->d_name, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync break;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync suplibHardenedMemCopy(&pszDirPath[cchName], pEntry->d_name, cchName + 1);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /*
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Query the information about the entry and verify it.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * (We don't bother skipping '.' and '..' at this point, a little bit
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * of extra checks doesn't hurt and neither requires relaxed handling.)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedQueryFsObjectByPath(pszDirPath, pFsObjState, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if (RT_SUCCESS(rc))
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync break;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync pszDirPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (RT_FAILURE(rc))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync break;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Recurse into subdirectories if requested.
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync */
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync if ( fRecursive
0c94a8282c9042b02f022302a3d987746140eab9vboxsync && S_ISDIR(pFsObjState->Stat.st_mode)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync && suplibHardenedStrCmp(pEntry->d_name, ".")
0c94a8282c9042b02f022302a3d987746140eab9vboxsync && suplibHardenedStrCmp(pEntry->d_name, ".."))
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync pszDirPath[cchDirPath + cchName] = RTPATH_SLASH;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync pszDirPath[cchDirPath + cchName + 1] = '\0';
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedVerifyDirRecursive(pszDirPath, cchDirPath + cchName + 1, pFsObjState,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync fRecursive, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (RT_FAILURE(rc))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync break;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync closedir(pDir);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return VINF_SUCCESS;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync#endif
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync}
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync/**
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Worker for SUPR3HardenedVerifyDir.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszDirPath See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRecursive See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fCheckFiles See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncDECLHIDDEN(int) supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Validate the input path and parse it.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync SUPR3HARDENEDPATHINFO Info;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync int rc = supR3HardenedVerifyPathSanity(pszDirPath, pErrInfo, &Info);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if (RT_FAILURE(rc))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return rc;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /*
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verify each component from the root up.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync SUPR3HARDENEDFSOBJSTATE FsObjState;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync uint32_t const cComponents = Info.cComponents;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync for (uint32_t iComponent = 0; iComponent < cComponents; iComponent++)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync bool fRelaxed = iComponent + 2 < cComponents;
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if (RT_SUCCESS(rc))
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync if (RT_FAILURE(rc))
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return rc;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = iComponent + 1 != cComponents ? RTPATH_SLASH : '\0';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /*
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Check files and subdirectories if requested.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync if (fCheckFiles || fRecursive)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Info.szPath[Info.cch] = RTPATH_SLASH;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync Info.szPath[Info.cch + 1] = '\0';
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return supR3HardenedVerifyDirRecursive(Info.szPath, Info.cch + 1, &FsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync fRecursive, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync }
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return VINF_SUCCESS;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync}
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync/**
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Verfies a file.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync *
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @returns VBox status code, error buffer filled on failure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pszFilename The file to verify.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param hNativeFile Handle to the file, verify that it's the same
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * as we ended up with when verifying the path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * RTHCUINTPTR_MAX means NIL here.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fMaybe3rdParty Set if the file is could be a supplied by a
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * third party. Different validation rules may
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * apply to 3rd party code on some platforms.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo Where to return extended error information.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Optional.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync bool fMaybe3rdParty, PRTERRINFO pErrInfo)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Validate the input path and parse it.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync SUPR3HARDENEDPATHINFO Info;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = supR3HardenedVerifyPathSanity(pszFilename, pErrInfo, &Info);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RT_FAILURE(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return rc;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (Info.fDirSlash)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The file path specifies a directory: '", pszFilename, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Verify each component from the root up.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync SUPR3HARDENEDFSOBJSTATE FsObjState;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync uint32_t const cComponents = Info.cComponents;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for (uint32_t iComponent = 0; iComponent < cComponents; iComponent++)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync {
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync bool fFinal = iComponent + 1 == cComponents;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync bool fRelaxed = iComponent + 2 < cComponents;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RT_SUCCESS(rc))
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RT_FAILURE(rc))
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return rc;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = !fFinal ? RTPATH_SLASH : '\0';
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync }
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /*
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Verify the file handle against the last component, if specified.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (hNativeFile != RTHCUINTPTR_MAX)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync {
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync rc = supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RT_FAILURE(rc))
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return rc;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync }
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync#ifdef RT_OS_WINDOWS
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /*
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * The files shall be signed on windows, verify that.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = VINF_SUCCESS;
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync HANDLE hVerify;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (hNativeFile == RTHCUINTPTR_MAX)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync {
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync PRTUTF16 pwszPath;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = RTStrToUtf16(pszFilename, &pwszPath);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_SUCCESS(rc))
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync {
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync hVerify = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync RTUtf16Free(pwszPath);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync }
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync else
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = RTErrInfoSetF(pErrInfo, rc, "Error converting '%s' to UTF-16: %Rrc", pszFilename, rc);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)hNativeFile, GetCurrentProcess(), &hVerify,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync GENERIC_READ, false /*bInheritHandle*/, 0 /*dwOptions*/))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync hVerify = INVALID_HANDLE_VALUE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (hVerify != INVALID_HANDLE_VALUE)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync {
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# ifdef VBOX_WITH_HARDENING
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uint32_t fFlags = SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (!fMaybe3rdParty)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fFlags = SUPHNTVI_F_REQUIRE_BUILD_CERT;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync const char *pszSuffix = RTPathSuffix(pszFilename);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( pszSuffix
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync && pszSuffix[0] == '.'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync && ( RT_C_TO_LOWER(pszSuffix[1]) == 'r'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || RT_C_TO_LOWER(pszSuffix[1]) == 'g')
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync && RT_C_TO_LOWER(pszSuffix[2]) == 'c'
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync && pszSuffix[3] == '\0' )
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync fFlags |= SUPHNTVI_F_RC_IMAGE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# ifndef IN_SUP_R3_STATIC /* Not in VBoxCpuReport and friends. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supHardenedWinVerifyImageByHandleNoName(hVerify, fFlags, pErrInfo);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync CloseHandle(hVerify);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync }
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else if (RT_SUCCESS(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(GetLastError()),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "Error %u trying to open (or duplicate handle for) '%s'", GetLastError(), pszFilename);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (RT_FAILURE(rc))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return rc;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return VINF_SUCCESS;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Gets the pre-init data for the hand-over to the other version
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * of this code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The reason why we pass this information on is that it contains
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * open directories and files. Later it may include even more info
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * (int the verified arrays mostly).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The receiver is supR3HardenedRecvPreInitData.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pPreInitData Where to store it.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(void) supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->cInstallFiles = RT_ELEMENTS(g_aSupInstallFiles);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paInstallFiles = &g_aSupInstallFiles[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paVerifiedFiles = &g_aSupVerifiedFiles[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->cVerifiedDirs = RT_ELEMENTS(g_aSupVerifiedDirs);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paVerifiedDirs = &g_aSupVerifiedDirs[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync}
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/**
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Receives the pre-init data from the static executable stub.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VBox status code. Will not bitch on failure since the
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * runtime isn't ready for it, so that is left to the exe stub.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pPreInitData The hand-over data.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(int) supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync{
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Compare the array lengths and the contents of g_aSupInstallFiles.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if ( pPreInitData->cInstallFiles != RT_ELEMENTS(g_aSupInstallFiles)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || pPreInitData->cVerifiedDirs != RT_ELEMENTS(g_aSupVerifiedDirs))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return VERR_VERSION_MISMATCH;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync SUPINSTFILE const *paInstallFiles = pPreInitData->paInstallFiles;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if ( g_aSupInstallFiles[iFile].enmDir != paInstallFiles[iFile].enmDir
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || g_aSupInstallFiles[iFile].enmType != paInstallFiles[iFile].enmType
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || g_aSupInstallFiles[iFile].fOptional != paInstallFiles[iFile].fOptional
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || suplibHardenedStrCmp(g_aSupInstallFiles[iFile].pszFile, paInstallFiles[iFile].pszFile))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync return VERR_VERSION_MISMATCH;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check that we're not called out of order.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * If dynamic linking it screwed up, we may end up here.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( ASMMemIsAll8(&g_aSupVerifiedFiles[0], sizeof(g_aSupVerifiedFiles), 0) != NULL
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || ASMMemIsAll8(&g_aSupVerifiedDirs[0], sizeof(g_aSupVerifiedDirs), 0) != NULL)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return VERR_WRONG_ORDER;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /*
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * Copy the verification data over.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync suplibHardenedMemCopy(&g_aSupVerifiedFiles[0], pPreInitData->paVerifiedFiles, sizeof(g_aSupVerifiedFiles));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync suplibHardenedMemCopy(&g_aSupVerifiedDirs[0], pPreInitData->paVerifiedDirs, sizeof(g_aSupVerifiedDirs));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return VINF_SUCCESS;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync}
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync