SUPR3HardenedVerify.cpp revision 3c36c06229c460f138561516170abc867297f256
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * VirtualBox Support Library - Verification of Hardened Installation.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * Copyright (C) 2006-2013 Oracle Corporation
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * available from http://www.virtualbox.org. This file is free software;
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * you can redistribute it and/or modify it under the terms of the GNU
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * General Public License (GPL) as published by the Free Software
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * The contents of this file may alternatively be used under the terms
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * of the Common Development and Distribution License Version 1.0
fa28a063d8ed660b9ae9aef07f417338b0efd8acvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * VirtualBox OSE distribution, in which case the provisions of the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * CDDL are applicable instead of those of the GPL.
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * You may elect to license modified versions of this file under the
16a8d09569a2ebd598cef72fa605be6fb4563607vboxsync * terms and conditions of either the GPL or the CDDL or both.
a7a0244227b5c1fb4410f6a1fa6cf7a462eaf4c1vboxsync/*******************************************************************************
a7a0244227b5c1fb4410f6a1fa6cf7a462eaf4c1vboxsync* Header Files *
a7a0244227b5c1fb4410f6a1fa6cf7a462eaf4c1vboxsync*******************************************************************************/
# include <stdio.h>
# include <stdlib.h>
# include <dirent.h>
# include <dlfcn.h>
# include <fcntl.h>
# include <limits.h>
# include <errno.h>
# include <unistd.h>
# include <pwd.h>
# ifdef RT_OS_DARWIN
#include "SUPLibInternal.h"
# define SUPHNTVI_NO_NT_STUFF
# include "win/SUPHardenedVerify-win.h"
#ifdef RT_OS_SOLARIS
#ifdef VBOX_WITH_RAW_MODE
#ifdef VBOX_WITH_MAIN
#ifdef RT_OS_WINDOWS
#ifdef RT_OS_LINUX
int rc;
switch (enmDir)
case kSupID_AppBin: /** @todo fix this AppBin crap (uncertain wtf some binaries actually are installed). */
case kSupID_Bin:
case kSupID_SharedLib:
case kSupID_AppPrivArch:
case kSupID_AppPrivArchComp:
case kSupID_AppPrivNoArch:
case kSupID_Testcase:
return rc;
* @param fWithFilename If set, the filename is included, otherwise it is omitted (no trailing slash).
static int supR3HardenedMakeFilePath(PCSUPINSTFILE pFile, char *pszDst, size_t cchDst, bool fWithFilename, bool fFatal)
return rc;
#if defined(RT_OS_WINDOWS)
NULL,
NULL);
if (fd >= 0)
"supR3HardenedVerifyDir: Cannot trust the directory \"%s\": group and/or other writable (st_mode=0%lo)\n",
return rc;
#ifdef RT_OS_WINDOWS
NULL,
NULL);
if (hFile)
rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: Failed to convert '%s' to UTF-16: %Rrc\n",
return rc;
static int supR3HardenedVerifyFileSignature(PCSUPINSTFILE pFile, PSUPVERIFIEDFILE pVerified, bool fFatal, bool fLeaveFileOpen)
# if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_R3_STATIC) /* Latter: Not in VBoxCpuReport and friends. */
int rc;
return rc;
rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: '%s': Image verify error rc=%Rrc: %s\n",
return rc;
return VINF_SUCCESS;
static int supR3HardenedVerifyFileInternal(int iFile, bool fFatal, bool fLeaveFileOpen, bool fVerifyAll)
#ifdef RT_OS_WINDOWS
return VINF_SUCCESS;
#ifdef RT_OS_WINDOWS
#if defined(RT_OS_WINDOWS)
if (!fVerifyAll)
if (!fLeaveFileOpen)
if (fd >= 0)
if (fLeaveFileOpen)
"supR3HardenedVerifyFileInternal: Cannot trust the file \"%s\": group and/or other writable (st_mode=0%lo)\n",
return rc;
return rc;
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
rc = supR3HardenedVerifyFileInternal(iFile, fFatal, false /* fLeaveFileOpen */, false /* fVerifyAll */);
return rc;
return VERR_NOT_FOUND;
bool fExe = false;
bool fDll = false;
if (fDll)
fDll = true;
if (fExe)
fExe = true;
int rc2 = supR3HardenedPathExecDir(szFilename, sizeof(szFilename) - cchProgName - sizeof(SUPLIB_EXE_SUFF));
else if (!fExe)
else if (!fDll)
return rc;
#if defined(RT_OS_WINDOWS)
bool fLeaveOpen = true;
bool fLeaveOpen = false;
return rc;
if (pErrInfo)
return rc;
#ifdef SOME_UNUSED_FUNCTION
const char *pszMsg2)
typedef struct SUPR3HARDENEDPATHINFO
bool fDirSlash;
static int supR3HardenedVerifyPathSanity(const char *pszPath, PRTERRINFO pErrInfo, PSUPR3HARDENEDPATHINFO pInfo)
return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
return supR3HardenedSetError3(VERR_SUPLIB_PATH_IS_ROOT, pErrInfo, "The path is root: '", pszPath, "'");
return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_SHORT, pErrInfo, "The path is too short: '", pszPath, "'");
while (pszSrc[0])
while (pszSrc[0])
pszSrc++;
if (*pszSrc)
return VINF_SUCCESS;
typedef struct SUPR3HARDENEDFSOBJSTATE
#ifdef RT_OS_WINDOWS
char chTodo;
static int supR3HardenedQueryFsObjectByPath(char const *pszPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState, PRTERRINFO pErrInfo)
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
return VINF_SUCCESS;
static int supR3HardenedQueryFsObjectByHandle(RTHCUINTPTR hNative, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
return VINF_SUCCESS;
* @param pFsObjState1 File system object information/state by path.
* @param pFsObjState2 File system object information/state by handle.
static int supR3HardenedIsSameFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState1, PCSUPR3HARDENEDFSOBJSTATE pFsObjState2,
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
* @param pFsObjState The file system object information/state to be
static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed,
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
return VINF_SUCCESS;
return supR3HardenedSetError3(VERR_SUPLIB_OWNER_NOT_ROOT, pErrInfo, "The owner is not root: '", pszPath, "'");
#ifdef RT_OS_DARWIN
bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 80 /*admin*/ || suplibHardenedStrCmp(pszPath, "/Applications");
bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 5 /*operator*/ || suplibHardenedStrCmp(pszPath, "/usr/pbi");
bool fBad = true;
if (fBad)
return VINF_SUCCESS;
* @param pFsObjState The information/state returned by a previous
static int supR3HardenedVerifySameFsObject(RTHCUINTPTR hNative, PCSUPR3HARDENEDFSOBJSTATE pFsObjState,
return rc;
static int supR3HardenedVerifyDirRecursive(char *pszDirPath, size_t cchDirPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
#if defined(RT_OS_WINDOWS)
return VINF_SUCCESS;
return VINF_SUCCESS;
if (!pDir)
return VINF_SUCCESS;
return rc;
if (iErr)
if (!pEntry)
rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/,
if ( fRecursive
return VINF_SUCCESS;
DECLHIDDEN(int) supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
return rc;
return rc;
Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = iComponent + 1 != cComponents ? RTPATH_SLASH : '\0';
return VINF_SUCCESS;
return rc;
return rc;
return rc;
#ifdef RT_OS_WINDOWS
hVerify = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
# ifdef VBOX_WITH_HARDENING
if (!fMaybe3rdParty)
if ( pszSuffix
return rc;
return VINF_SUCCESS;
return VERR_VERSION_MISMATCH;
return VERR_VERSION_MISMATCH;
return VERR_WRONG_ORDER;
suplibHardenedMemCopy(&g_aSupVerifiedFiles[0], pPreInitData->paVerifiedFiles, sizeof(g_aSupVerifiedFiles));
suplibHardenedMemCopy(&g_aSupVerifiedDirs[0], pPreInitData->paVerifiedDirs, sizeof(g_aSupVerifiedDirs));
return VINF_SUCCESS;