SUPR3HardenedMain.cpp revision bfc39c8324b2a90c8cb3fedf883495d1ed92e724
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * VirtualBox Support Library - Hardened main().
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Copyright (C) 2006-2014 Oracle Corporation
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * available from http://www.virtualbox.org. This file is free software;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * you can redistribute it and/or modify it under the terms of the GNU
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * General Public License (GPL) as published by the Free Software
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * The contents of this file may alternatively be used under the terms
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * of the Common Development and Distribution License Version 1.0
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * VirtualBox OSE distribution, in which case the provisions of the
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * CDDL are applicable instead of those of the GPL.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * You may elect to license modified versions of this file under the
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * terms and conditions of either the GPL or the CDDL or both.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Header Files *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else /* UNIXes */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <iprt/types.h> /* stdint fun on darwin. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# undef USE_LIB_PCAP /* don't depend on libcap as we had to depend on either
dbec828311ed2a5cf6fbc68fe4391d516ba4f92fvboxsync libcap1 or libcap2 */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <linux/types.h> /* sys/capabilities from uek-headers require this */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Defined Constants And Macros *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @def SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Whether we're employing set-user-ID-on-execute in the hardening.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) && !defined(RT_OS_L4)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @def SUP_HARDENED_SYM
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Decorate a symbol that's resolved dynamically.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Structures and Typedefs *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @see RTR3InitEx */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsynctypedef DECLCALLBACK(int) FNRTR3INITEX(uint32_t iVersion, uint32_t fFlags, int cArgs,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Global Variables *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program executable path. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program directory path. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program name. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic const char *g_pszSupLibHardenedProgName;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The real UID at startup. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The real GID at startup. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The startup log file. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The current SUPR3HardenedMain state / location. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncSUPR3HARDENEDMAINSTATE g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Internal Functions *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic PFNSUPTRUSTEDERROR supR3HardenedMainGetTrustedError(const char *pszProgName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Safely copy one or more strings into the given buffer.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszDst The destionation buffer.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param cbDst The size of the destination buffer.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param ... One or more zero terminated strings, ending with
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic int suplibHardenedStrCopyEx(char *pszDst, size_t cbDst, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Exit current process in the quickest possible fashion.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param rcExit The exit code.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLNORETURN(void) suplibHardenedExit(RTEXITCODE rcExit)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a substring to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pch The start of the substring.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param cch The length of the substring.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintStrN(const char *pch, size_t cch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HANDLE hStdOut = NtCurrentPeb()->ProcessParameters->StandardOutput;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# if 0 /* Windows 7 and earlier uses fake handles, with the last two bits set ((hStdOut & 3) == 3). */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NtWriteFile(hStdOut, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync &Ios, (PVOID)pch, (ULONG)cch, NULL /*ByteOffset*/, NULL /*Key*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync WriteFile(hStdOut, pch, (DWORD)cch, &cbWritten, NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a string to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param psz The string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(psz, suplibHardenedStrLen(psz));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a char to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param ch The character value to write.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a decimal number to stdard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uValue The value.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintDecimal(uint64_t uValue)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync } while (uValue > 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a hexadecimal or octal number to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uValue The value.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uBase The base (16 or 8).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param fFlags Format flags.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintHexOctal(uint64_t uValue, unsigned uBase, uint32_t fFlags)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static char const s_achDigitsLower[17] = "0123456789abcdef";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static char const s_achDigitsUpper[17] = "0123456789ABCDEF";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pchDigits = !(fFlags & RTSTR_F_CAPITAL) ? s_achDigitsLower : s_achDigitsUpper;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync } while (uValue > 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a wide character string to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pwsz The string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintWideStr(PCRTUTF16 pwsz)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** Buffer structure used by suplibHardenedOutput. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** Callback for RTStrFormatV, see FNRTSTROUTPUT. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic DECLCALLBACK(size_t) suplibHardenedOutput(void *pvArg, const char *pachChars, size_t cbChars)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync SUPLIBHARDENEDOUTPUTBUF *pBuf = (SUPLIBHARDENEDOUTPUTBUF *)pvArg;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cbSpace = sizeof(pBuf->szBuf) - pBuf->off - 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Flush the buffer? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Copy the string into the buffer. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbTodo);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbSpace);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* IPRT_NO_CRT */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Simple printf to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszFormat The format string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param va Arguments to format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) suplibHardenedPrintFV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Use buffered output here to avoid character mixing on the windows
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * console and to enable us to use OutputDebugString.
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync RTStrFormatV(suplibHardenedOutput, &Buf, NULL, NULL, pszFormat, va);
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync#else /* !IPRT_NO_CRT */
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync * Format loop.
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * Format argument.
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Flush unwritten bits. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast - 1);
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* flags. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else if (ch == '\'') fFlags |= RTSTR_F_THOUSAND_SEP;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else break;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Width and precision - ignored. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Size. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Do type specific formatting.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync fFlags |= RTSTR_F_ZEROPAD; /* Note not standard behaviour (but I like it this way!) */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == 'p' || chArgSize == 'z' || chArgSize == 't')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintHexOctal(uValue, uBase, fFlags);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* fall thru */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Custom format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* continue */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Flush the last bits of the string. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* !IPRT_NO_CRT */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Prints to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszFormat The format string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param ... Arguments to format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) suplibHardenedPrintF(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathStripFilename.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPathStripFilename(char *pszPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* handle separators. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* the end */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* will never get here */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathFilename
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(char *) supR3HardenedPathFilename(const char *pszPath)
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync /* handle separators. */
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync /* the end */
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync return (char *)(void *)pszLastComp;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* will never get here */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppPrivateNoArch
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppPrivateNoArch(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathPrivateNoArch = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppPrivateNoArch: Buffer overflow, %zu >= %zu\n", cchPathPrivateNoArch, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathPrivateNoArch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppPrivateArch
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppPrivateArch(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE_ARCH)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathPrivateArch = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppPrivateArch: Buffer overflow, %zu >= %zu\n", cchPathPrivateArch, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathPrivateArch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathSharedLibs
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathSharedLibs(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_SHARED_LIBS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathSharedLibs = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathSharedLibs: Buffer overflow, %zu >= %zu\n", cchPathSharedLibs, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathSharedLibs + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppDocs
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppDocs(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_DOCS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathAppDocs = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppDocs: Buffer overflow, %zu >= %zu\n", cchPathAppDocs, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathAppDocs + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Returns the full path to the executable.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns IPRT status code.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszPath Where to store it.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param cchPath How big that buffer is.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Get the program filename.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Most UNIXes have no API for obtaining the executable path, but provides a symbolic
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * link in the proc file system that tells who was exec'ed. The bad thing about this
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * is that we have to use readlink, one of the weirder UNIX APIs.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Darwin, OS/2 and Windows all have proper APIs for getting the program file name.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink("/proc/self/exe", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink(szFileBuf, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# else /* RT_OS_FREEBSD */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (sysctl(aiName, RT_ELEMENTS(aiName), g_szSupLibHardenedExePath, &cbPath, NULL, 0) < 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: sysctl failed\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_szSupLibHardenedExePath[sizeof(g_szSupLibHardenedExePath) - 1] = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = suplibHardenedStrLen(g_szSupLibHardenedExePath); /* paranoid? can't we use cbPath? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedExePath) - 1)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: couldn't read \"%s\", errno=%d cchLink=%d\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync _execname(g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszImageName = _dyld_get_image_name(0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: _dyld_get_image_name(0) failed\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchImageName = suplibHardenedStrLen(pszImageName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!cchImageName || cchImageName >= sizeof(g_szSupLibHardenedExePath))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: _dyld_get_image_name(0) failed, cchImageName=%d\n", cchImageName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(g_szSupLibHardenedExePath, pszImageName, cchImageName + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = RTUtf16ToUtf8Ex(g_wszSupLibHardenedExePath, RTSTR_MAX, &pszDst, sizeof(g_szSupLibHardenedExePath), NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: RTUtf16ToUtf8Ex failed, rc=%Rrc\n", rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Strip off the filename part (RTPathStripFilename()).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedStrCopy(g_szSupLibHardenedDirPath, g_szSupLibHardenedExePath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPathStripFilename(g_szSupLibHardenedDirPath);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * Checks if we can read /proc/self/exe.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * This is used on linux to see if we have to call init
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * with program path or not.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns true / false.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic bool supR3HardenedMainIsProcSelfExeAccssible(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink("/proc/self/exe", szPath, sizeof(szPath));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* RT_OS_LINUX */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathExecDir
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathExecDir(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Lazy init (probably not required).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Calc the length and check if there is space before copying.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cch = suplibHardenedStrLen(g_szSupLibHardenedDirPath) + 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, g_szSupLibHardenedDirPath, cch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathExecDir: Buffer too small (%u < %u)\n", cchPath, cch);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedOpenLog(int *pcArgs, char **papszArgs)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static const char s_szLogOption[] = "--sup-startup-log=";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Scan the argument vector.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (strncmp(papszArgs[iArg], s_szLogOption, sizeof(s_szLogOption) - 1) == 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszLogFile = &papszArgs[iArg][sizeof(s_szLogOption) - 1];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Drop the argument from the vector (has trailing NULL entry).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memmove(&papszArgs[iArg], &papszArgs[iArg + 1], (cArgs - iArg) * sizeof(papszArgs[0]));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Open the log file, unless we've already opened one.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * First argument takes precedence
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync SUP_DPRINTF(("Log file opened: " VBOX_VERSION_STRING "r%u g_hStartupLog=%p g_uNtVerCombined=%#x\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync //g_hStartupLog = open()
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedLogV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PCLIENT_ID pSelfId = &((PTEB)NtCurrentTeb())->ClientId;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPrefix = RTStrPrintf(szBuf, sizeof(szBuf), "%x.%x: ", pSelfId->UniqueProcess, pSelfId->UniqueThread);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cch = RTStrPrintfV(&szBuf[cchPrefix], sizeof(szBuf) - cchPrefix, pszFormat, va) + cchPrefix;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NtWriteFile(g_hStartupLog, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* later */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedLog(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Prints the message prefix.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr(g_pszSupLibHardenedProgName);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsyncDECLHIDDEN(void) supR3HardenedFatalMsgV(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va)
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * First to the log.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync supR3HardenedLog("Error %d in %s! (enmWhat=%d)\n", rc, pszWhere, enmWhat);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * Then to the console.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintF("Error %d in %s!\n", rc, pszWhere);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintStr("Tip! Make sure the kernel module is loaded. It may also help to reinstall VirtualBox.\n");
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintStr("Tip! It may help to reinstall VirtualBox.\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* no hints here */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * Drop any root privileges we might be holding, this won't return
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * if it fails but end up calling supR3HardenedFatal[V].
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync#endif /* SUP_HARDENED_SUID */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * Now try resolve and call the TrustedError entry point if we can
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * find it. We'll fork before we attempt this because that way the
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * session management in main will see us exiting immediately (if
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * it's involved with us).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static volatile bool s_fRecursive = false; /* Loader hooks may cause recursion. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatalMsg(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsgV(pszWhere, enmWhat, rc, pszMsgFmt, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatalV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatal(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedErrorV(int rc, bool fFatal, const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedError(int rc, bool fFatal, const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Attempts to open /dev/vboxdrv (or equvivalent).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks This function will not return on failure.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = suplibOsInit(&g_SupPreInitData.Data, false /*fPreInit*/, true /*fUnrestricted*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo better messages! */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver not installed");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver not accessible");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_VM_DRIVER_LOAD_ERROR");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_VM_DRIVER_OPEN_ERROR");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver version mismatch");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_ACCESS_DENIED");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel memory allocation/mapping failed");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPDRV_HARDENING_EVIL_HANDLE");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Grabs extra non-root capabilities / privileges that we might require.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * This is currently only used for being able to do ICMP from the NAT engine.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @note We still have root privileges at the time of this call.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * We are about to drop all our privileges. Remove all capabilities but
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * keep the cap_net_raw capability for ICMP sockets for the NAT stack.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* XXX cap_net_bind_service */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!cap_set_proc(cap_from_text("all-eip cap_net_raw+ep")))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap_user_header_t hdr = (cap_user_header_t)alloca(sizeof(*hdr));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap_user_data_t cap = (cap_user_data_t)alloca(sizeof(*cap));
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync# endif /* !USE_LIB_PCAP */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Add net_icmpaccess privilege to effective privileges and limit
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * permitted privileges before completely dropping root privileges.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * This requires dropping root privileges temporarily to get the normal
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * user's privileges.
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync /* Order is important, as one can't set a privilege which is
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync * not in the permitted privilege set. */
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set effective privilege set.\n");
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set permitted privilege set.\n");
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to add NET_ICMPACCESS privilege.\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* for memory allocation failures just continue */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Look at the environment for some special options.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3GrabOptions(void)
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync const char *pszOpt;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Do _not_ perform any capability-related system calls for root processes
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * (leaving g_uCaps at 0).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * (Hint: getuid gets the real user id, not the effective.)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * CAP_NET_RAW.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Default: enabled.
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * Can be disabled with 'export VBOX_HARD_CAP_NET_RAW=0'.
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * CAP_NET_BIND_SERVICE.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Default: disabled.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Can be enabled with 'export VBOX_HARD_CAP_NET_BIND_SERVICE=1'.
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync * Drop any root privileges we might be holding.
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync * Try use setre[ug]id since this will clear the save uid/gid and thus
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync * leave fewer traces behind that libs like GTK+ may pick up.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* The really great thing here is that setreuid isn't available on
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync OS X 10.4, libc emulates it. While 10.4 have a slightly different and
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync non-standard setuid implementation compared to 10.5, the following
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync works the same way with both version since we're super user (10.5 req).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync The following will set all three variants of the group and user IDs. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Solaris doesn't have setresuid, but the setreuid interface is BSD
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync compatible and will set the saved uid to euid when we pass it a ruid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync that isn't -1 (which we do). */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* This is the preferred one, full control no questions about semantics.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PORTME: If this isn't work, try join one of two other gangs above. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Check that it worked out all right. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("SUPR3HardenedMain: failed to drop root privileges!"
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync " (euid=%d ruid=%d suid=%d egid=%d rgid=%d sgid=%d; wanted uid=%d and gid=%d)\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Re-enable the cap_net_raw capability which was disabled during setresuid.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo Warn if that does not work? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* XXX cap_net_bind_service */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap_user_header_t hdr = (cap_user_header_t)alloca(sizeof(*hdr));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap_user_data_t cap = (cap_user_data_t)alloca(sizeof(*cap));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo Warn if that does not work? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif /* !USE_LIB_PCAP */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* SUP_HARDENED_SUID */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * and calls RTR3InitEx.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param fFlags The SUPR3HardenedMain fFlags argument, passed to supR3PreInit.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks VBoxRT contains both IPRT and SUPR3.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks This function will not return on failure.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedMainInitRuntime(uint32_t fFlags)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Construct the name.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxRT" SUPLIB_DLL_SUFF));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedStrCat(szPath, "/VBoxRT" SUPLIB_DLL_SUFF);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Open it and resolve the symbols.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_MODULE_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "LoadLibrary \"%s\" failed (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3InitEx"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"RTR3InitEx\" not found in \"%s\" (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)GetProcAddress(hMod, SUP_HARDENED_SYM("supR3PreInit"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"supR3PreInit\" not found in \"%s\" (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* the dlopen crowd */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_MODULE_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "dlopen(\"%s\",) failed: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("RTR3InitEx"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"RTR3InitEx\" not found in \"%s\"!\ndlerror: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("supR3PreInit"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"supR3PreInit\" not found in \"%s\"!\ndlerror: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Make the calls.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV ? 0 : RTR3INIT_FLAGS_SUPLIB,
suplibHardenedStrCopyEx(&szPath[cch], sizeof(szPath) - cch, "/", pszProgName, SUPLIB_DLL_SUFF, NULL);
#if defined(RT_OS_WINDOWS)
if (!hMod)
return NULL;
if (!pfn)
return NULL;
if (!pvMod)
return NULL;
if (!pvSym)
return NULL;
suplibHardenedStrCopyEx(&szPath[cch], sizeof(szPath) - cch, "/", pszProgName, SUPLIB_DLL_SUFF, NULL);
#if defined(RT_OS_WINDOWS)
if (!hMod)
if (!pfn)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\" (rc=%d)\n",
if (!pvMod)
if (!pvSym)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\"!\ndlerror: %s\n",
DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp)
#ifdef SUP_HARDENED_SUID
# ifdef RT_OS_LINUX
#ifdef RT_OS_WINDOWS
#ifdef RT_OS_WINDOWS
#ifdef RT_OS_WINDOWS
#ifdef SUP_HARDENED_SUID