SUPR3HardenedMain.cpp revision bfc39c8324b2a90c8cb3fedf883495d1ed92e724
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/* $Id$ */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @file
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * VirtualBox Support Library - Hardened main().
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Copyright (C) 2006-2014 Oracle Corporation
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
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 *
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 *
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
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Header Files *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if defined(RT_OS_OS2)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define INCL_BASE
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define INCL_ERRORS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <os2.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <stdio.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <stdlib.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <dlfcn.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <unistd.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#elif RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <iprt/nt/nt-and-windows.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else /* UNIXes */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <iprt/types.h> /* stdint fun on darwin. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <stdio.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <stdlib.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <dlfcn.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <limits.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <errno.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <unistd.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/stat.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/time.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/types.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# if defined(RT_OS_LINUX)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# undef USE_LIB_PCAP /* don't depend on libcap as we had to depend on either
dbec828311ed2a5cf6fbc68fe4391d516ba4f92fvboxsync libcap1 or libcap2 */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# undef _POSIX_SOURCE
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <linux/types.h> /* sys/capabilities from uek-headers require this */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/capability.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/prctl.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifndef CAP_TO_MASK
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define CAP_TO_MASK(cap) RT_BIT(cap)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# elif defined(RT_OS_FREEBSD)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/param.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <sys/sysctl.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# elif defined(RT_OS_SOLARIS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <priv.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <pwd.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef RT_OS_DARWIN
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <mach-o/dyld.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <VBox/sup.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <VBox/err.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# include <VBox/version.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync#include <iprt/ctype.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <iprt/string.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <iprt/initterm.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <iprt/param.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include "SUPLibInternal.h"
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
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 */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) && !defined(RT_OS_L4)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# undef SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @def SUP_HARDENED_SYM
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Decorate a symbol that's resolved dynamically.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_OS2
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define SUP_HARDENED_SYM(sym) "_" sym
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# define SUP_HARDENED_SYM(sym) sym
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Structures and Typedefs *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @see RTR3InitEx */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsynctypedef DECLCALLBACK(int) FNRTR3INITEX(uint32_t iVersion, uint32_t fFlags, int cArgs,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char **papszArgs, const char *pszProgramPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsynctypedef FNRTR3INITEX *PFNRTR3INITEX;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Global Variables *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic SUPPREINITDATA g_SupPreInitData;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program executable path. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifndef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncchar g_szSupLibHardenedExePath[RTPATH_MAX];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program directory path. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic char g_szSupLibHardenedDirPath[RTPATH_MAX];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The program name. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic const char *g_pszSupLibHardenedProgName;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The real UID at startup. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic uid_t g_uid;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The real GID at startup. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic gid_t g_gid;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic uint32_t g_uCaps;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The startup log file. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic HANDLE g_hStartupLog = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic int g_hStartupLog = -1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** The current SUPR3HardenedMain state / location. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncSUPR3HARDENEDMAINSTATE g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*******************************************************************************
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync* Internal Functions *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync*******************************************************************************/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedMainDropPrivileges(void);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic PFNSUPTRUSTEDERROR supR3HardenedMainGetTrustedError(const char *pszProgName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Safely copy one or more strings into the given buffer.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
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
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * a NULL.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic int suplibHardenedStrCopyEx(char *pszDst, size_t cbDst, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cbDst == 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_BUFFER_OVERFLOW;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, cbDst);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszSrc = va_arg(va, const char *);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pszSrc)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchSrc = suplibHardenedStrLen(pszSrc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchSrc < cbDst)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszDst, pszSrc, cchSrc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszDst += cchSrc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cbDst -= cchSrc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = VERR_BUFFER_OVERFLOW;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cbDst > 1)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszDst, pszSrc, cbDst - 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszDst += cbDst - 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cbDst = 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *pszDst = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Exit current process in the quickest possible fashion.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param rcExit The exit code.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLNORETURN(void) suplibHardenedExit(RTEXITCODE rcExit)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ExitProcess(rcExit);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync _Exit(rcExit);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a substring to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pch The start of the substring.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param cch The length of the substring.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintStrN(const char *pch, size_t cch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HANDLE hStdOut = NtCurrentPeb()->ProcessParameters->StandardOutput;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (hStdOut != NULL)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
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# else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync DWORD cbWritten;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync WriteFile(hStdOut, pch, (DWORD)cch, &cbWritten, NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync (void)write(2, pch, cch);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a string to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param psz The string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintStr(const char *psz)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(psz, suplibHardenedStrLen(psz));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a char to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param ch The character value to write.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintChr(char ch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(&ch, 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a decimal number to stdard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uValue The value.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintDecimal(uint64_t uValue)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szBuf[64];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *pszEnd = &szBuf[sizeof(szBuf) - 1];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *psz = pszEnd;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync do
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = '0' + (uValue % 10);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue /= 10;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync } while (uValue > 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync psz++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(psz, pszEnd - psz);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
11c2b573e2625474a51ae55ee1f3f82936f125davboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a hexadecimal or octal number to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uValue The value.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param uBase The base (16 or 8).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param fFlags Format flags.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintHexOctal(uint64_t uValue, unsigned uBase, uint32_t fFlags)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
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 unsigned cShift = uBase == 16 ? 4 : 3;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync unsigned fDigitMask = uBase == 16 ? 0xf : 7;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szBuf[64];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *pszEnd = &szBuf[sizeof(szBuf) - 1];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *psz = pszEnd;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync do
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = pchDigits[uValue & fDigitMask];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue >>= cShift;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync } while (uValue > 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if ((fFlags & RTSTR_F_SPECIAL) && uBase == 16)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = !(fFlags & RTSTR_F_CAPITAL) ? 'x' : 'X';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *psz-- = '0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync psz++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(psz, pszEnd - psz);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Writes a wide character string to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pwsz The string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPrintWideStr(PCRTUTF16 pwsz)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTUTF16 wc = *pwsz++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!wc)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if ( (wc < 0x7f && wc >= 0x20)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || wc == '\n'
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || wc == '\r')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintChr((char)wc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(RT_STR_TUPLE("\\x"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintHexOctal(wc, 16, 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef IPRT_NO_CRT
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** Buffer structure used by suplibHardenedOutput. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstruct SUPLIBHARDENEDOUTPUTBUF
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t off;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szBuf[2048];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync};
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** Callback for RTStrFormatV, see FNRTSTROUTPUT. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic DECLCALLBACK(size_t) suplibHardenedOutput(void *pvArg, const char *pachChars, size_t cbChars)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync SUPLIBHARDENEDOUTPUTBUF *pBuf = (SUPLIBHARDENEDOUTPUTBUF *)pvArg;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cbTodo = cbChars;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cbSpace = sizeof(pBuf->szBuf) - pBuf->off - 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Flush the buffer? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if ( cbSpace == 0
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || (cbTodo == 0 && pBuf->off))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(pBuf->szBuf, pBuf->off);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync OutputDebugString(pBuf->szBuf);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pBuf->off = 0;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cbSpace = sizeof(pBuf->szBuf) - 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Copy the string into the buffer. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cbTodo == 1)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pBuf->szBuf[pBuf->off++] = *pachChars;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cbSpace >= cbTodo)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbTodo);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pBuf->off += cbTodo;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memcpy(&pBuf->szBuf[pBuf->off], pachChars, cbSpace);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pBuf->off += cbSpace;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cbTodo -= cbSpace;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pBuf->szBuf[pBuf->off] = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return cbChars;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* IPRT_NO_CRT */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Simple printf to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszFormat The format string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param va Arguments to format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) suplibHardenedPrintFV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef IPRT_NO_CRT
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Use buffered output here to avoid character mixing on the windows
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * console and to enable us to use OutputDebugString.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync SUPLIBHARDENEDOUTPUTBUF Buf;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Buf.off = 0;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Buf.szBuf[0] = '\0';
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync RTStrFormatV(suplibHardenedOutput, &Buf, NULL, NULL, pszFormat, va);
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync#else /* !IPRT_NO_CRT */
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync /*
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync * Format loop.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char ch;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszLast = pszFormat;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!ch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == '%')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * Format argument.
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Flush unwritten bits. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync if (pszLast != pszFormat - 1)
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast - 1);
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync pszLast = pszFormat;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync ch = *pszFormat++;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* flags. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync uint32_t fFlags = 0;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == '#') fFlags |= RTSTR_F_SPECIAL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else if (ch == '-') fFlags |= RTSTR_F_LEFT;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else if (ch == '+') fFlags |= RTSTR_F_PLUS;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else if (ch == ' ') fFlags |= RTSTR_F_BLANK;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else if (ch == '0') fFlags |= RTSTR_F_ZEROPAD;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else if (ch == '\'') fFlags |= RTSTR_F_THOUSAND_SEP;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync else break;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync ch = *pszFormat++;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync }
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Width and precision - ignored. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync while (RT_C_IS_DIGIT(ch))
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync ch = *pszFormat++;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync if (ch == '*')
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync va_arg(va, int);
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync if (ch == '.')
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync {
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync do ch = *pszFormat++;
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync while (RT_C_IS_DIGIT(ch));
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync if (ch == '*')
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync va_arg(va, int);
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync }
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /* Size. */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync char chArgSize = 0;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync switch (ch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'z':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'L':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'j':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 't':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync chArgSize = ch;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'l':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync chArgSize = ch;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == 'l')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync chArgSize = 'L';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'h':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync chArgSize = ch;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == 'h')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync chArgSize = 'H';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = *pszFormat++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Do type specific formatting.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync switch (ch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'c':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ch = (char)va_arg(va, int);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintChr(ch);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 's':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (chArgSize == 'l')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PCRTUTF16 pwszStr = va_arg(va, PCRTUTF16 );
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (RT_VALID_PTR(pwszStr))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintWideStr(pwszStr);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr("<NULL>");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszStr = va_arg(va, const char *);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!RT_VALID_PTR(pszStr))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszStr = "<NULL>";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr(pszStr);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'd':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'i':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int64_t iValue;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (chArgSize == 'L' || chArgSize == 'j')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = va_arg(va, int64_t);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else if (chArgSize == 'l')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = va_arg(va, signed long);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else if (chArgSize == 'z' || chArgSize == 't')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = va_arg(va, intptr_t);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = va_arg(va, signed int);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (iValue < 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintChr('-');
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = -iValue;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintDecimal(iValue);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'p':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'x':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'X':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'u':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'o':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync unsigned uBase = 10;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uint64_t uValue;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync switch (ch)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'p':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync fFlags |= RTSTR_F_ZEROPAD; /* Note not standard behaviour (but I like it this way!) */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uBase = 16;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'X':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync fFlags |= RTSTR_F_CAPITAL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'x':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uBase = 16;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'u':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uBase = 10;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'o':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uBase = 8;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (ch == 'p' || chArgSize == 'z' || chArgSize == 't')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue = va_arg(va, uintptr_t);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else if (chArgSize == 'L' || chArgSize == 'j')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue = va_arg(va, uint64_t);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else if (chArgSize == 'l')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue = va_arg(va, unsigned long);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uValue = va_arg(va, unsigned int);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (uBase == 10)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintDecimal(uValue);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintHexOctal(uValue, uBase, fFlags);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case 'R':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pszFormat[0] == 'r' && pszFormat[1] == 'c')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int iValue = va_arg(va, int);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (iValue < 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintChr('-');
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iValue = -iValue;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintDecimal(iValue);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszFormat += 2;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* fall thru */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Custom format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync default:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr("[bad format: ");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintChr(']');
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* continue */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszLast = pszFormat;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Flush the last bits of the string. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pszLast != pszFormat)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStrN(pszLast, pszFormat - pszLast);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* !IPRT_NO_CRT */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Prints to standard error.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszFormat The format string.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param ... Arguments to format.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) suplibHardenedPrintF(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, pszFormat);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintFV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathStripFilename.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void suplibHardenedPathStripFilename(char *pszPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *psz = pszPath;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *pszLastSep = pszPath;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;; psz++)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync switch (*psz)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* handle separators. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case ':':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszLastSep = psz + 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case '\\':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case '/':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszLastSep = psz;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* the end */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case '\0':
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pszLastSep == pszPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *pszLastSep++ = '.';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *pszLastSep = '\0';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* will never get here */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathFilename
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(char *) supR3HardenedPathFilename(const char *pszPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *psz = pszPath;
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync const char *pszLastComp = pszPath;
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync for (;; psz++)
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync {
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync switch (*psz)
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync {
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync /* handle separators. */
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync case ':':
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync pszLastComp = psz + 1;
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync break;
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync case '\\':
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync#endif
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync case '/':
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync pszLastComp = psz + 1;
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync break;
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync /* the end */
dbec828311ed2a5cf6fbc68fe4391d516ba4f92fvboxsync case '\0':
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync if (*pszLastComp)
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync return (char *)(void *)pszLastComp;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* will never get here */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppPrivateNoArch
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppPrivateNoArch(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszSrcPath = RTPATH_APP_PRIVATE;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathPrivateNoArch = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchPathPrivateNoArch >= cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppPrivateNoArch: Buffer overflow, %zu >= %zu\n", cchPathPrivateNoArch, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathPrivateNoArch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return supR3HardenedPathExecDir(pszPath, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppPrivateArch
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppPrivateArch(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE_ARCH)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszSrcPath = RTPATH_APP_PRIVATE_ARCH;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathPrivateArch = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchPathPrivateArch >= cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppPrivateArch: Buffer overflow, %zu >= %zu\n", cchPathPrivateArch, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathPrivateArch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return supR3HardenedPathExecDir(pszPath, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathSharedLibs
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathSharedLibs(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_SHARED_LIBS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszSrcPath = RTPATH_SHARED_LIBS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathSharedLibs = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchPathSharedLibs >= cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathSharedLibs: Buffer overflow, %zu >= %zu\n", cchPathSharedLibs, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathSharedLibs + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return supR3HardenedPathExecDir(pszPath, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathAppDocs
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathAppDocs(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_DOCS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszSrcPath = RTPATH_APP_DOCS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cchPathAppDocs = suplibHardenedStrLen(pszSrcPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchPathAppDocs >= cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathAppDocs: Buffer overflow, %zu >= %zu\n", cchPathAppDocs, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, pszSrcPath, cchPathAppDocs + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return supR3HardenedPathExecDir(pszPath, cchPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Returns the full path to the executable.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns IPRT status code.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param pszPath Where to store it.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param cchPath How big that buffer is.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedGetFullExePath(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Get the program filename.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
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 *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Darwin, OS/2 and Windows all have proper APIs for getting the program file name.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink("/proc/self/exe", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# elif defined(RT_OS_SOLARIS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szFileBuf[PATH_MAX + 1];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink(szFileBuf, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# else /* RT_OS_FREEBSD */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int aiName[4];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync aiName[0] = CTL_KERN;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync aiName[1] = KERN_PROC;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync aiName[2] = KERN_PROC_PATHNAME;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync aiName[3] = getpid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cbPath = sizeof(g_szSupLibHardenedExePath);
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
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedExePath) - 1)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: couldn't read \"%s\", errno=%d cchLink=%d\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_szSupLibHardenedExePath, errno, cchLink);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_szSupLibHardenedExePath[cchLink] = '\0';
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#elif defined(RT_OS_OS2) || defined(RT_OS_L4)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync _execname(g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#elif defined(RT_OS_DARWIN)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszImageName = _dyld_get_image_name(0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pszImageName)
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
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#elif defined(RT_OS_WINDOWS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char *pszDst = g_szSupLibHardenedExePath;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = RTUtf16ToUtf8Ex(g_wszSupLibHardenedExePath, RTSTR_MAX, &pszDst, sizeof(g_szSupLibHardenedExePath), NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (RT_FAILURE(rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedExecDir: RTUtf16ToUtf8Ex failed, rc=%Rrc\n", rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# error needs porting.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Strip off the filename part (RTPathStripFilename()).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedStrCopy(g_szSupLibHardenedDirPath, g_szSupLibHardenedExePath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPathStripFilename(g_szSupLibHardenedDirPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * Checks if we can read /proc/self/exe.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync *
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * This is used on linux to see if we have to call init
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * with program path or not.
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns true / false.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic bool supR3HardenedMainIsProcSelfExeAccssible(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szPath[RTPATH_MAX];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cchLink = readlink("/proc/self/exe", szPath, sizeof(szPath));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return cchLink != -1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* RT_OS_LINUX */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @copydoc RTPathExecDir
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedPathExecDir(char *pszPath, size_t cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Lazy init (probably not required).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!g_szSupLibHardenedDirPath[0])
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedGetFullExePath();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Calc the length and check if there is space before copying.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync size_t cch = suplibHardenedStrLen(g_szSupLibHardenedDirPath) + 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (cch <= cchPath)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedMemCopy(pszPath, g_szSupLibHardenedDirPath, cch + 1);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatal("supR3HardenedPathExecDir: Buffer too small (%u < %u)\n", cchPath, cch);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_BUFFER_OVERFLOW;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncextern "C" uint32_t g_uNtVerCombined;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedOpenLog(int *pcArgs, char **papszArgs)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static const char s_szLogOption[] = "--sup-startup-log=";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Scan the argument vector.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int cArgs = *pcArgs;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (int iArg = 1; iArg < cArgs; iArg++)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (strncmp(papszArgs[iArg], s_szLogOption, sizeof(s_szLogOption) - 1) == 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszLogFile = &papszArgs[iArg][sizeof(s_szLogOption) - 1];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Drop the argument from the vector (has trailing NULL entry).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memmove(&papszArgs[iArg], &papszArgs[iArg + 1], (cArgs - iArg) * sizeof(papszArgs[0]));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *pcArgs -= 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cArgs -= 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Open the log file, unless we've already opened one.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * First argument takes precedence
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (g_hStartupLog == NULL)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PRTUTF16 pwszPath;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = RTStrToUtf16(pszLogFile, &pwszPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (RT_SUCCESS(rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_hStartupLog = CreateFileW(pwszPath,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync GENERIC_WRITE,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync FILE_SHARE_READ | FILE_SHARE_WRITE,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NULL,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync OPEN_ALWAYS,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTUtf16Free(pwszPath);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync SUP_DPRINTF(("Log file opened: " VBOX_VERSION_STRING "r%u g_hStartupLog=%p g_uNtVerCombined=%#x\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync VBOX_SVN_REV, g_hStartupLog, g_uNtVerCombined));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync //g_hStartupLog = open()
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedLogV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_WINDOWS
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (g_hStartupLog)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szBuf[5120];
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
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if ((size_t)cch >= sizeof(szBuf))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cch = sizeof(szBuf) - 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!cch || szBuf[cch - 1] != '\n')
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szBuf[cch++] = '\n';
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LARGE_INTEGER Offset;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Offset.QuadPart = -1; /* Write to end of file. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NtWriteFile(g_hStartupLog, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync &Ios, szBuf, (ULONG)cch, &Offset, NULL /*Key*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* later */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedLog(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, pszFormat);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedLogV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Prints the message prefix.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsyncstatic void suplibHardenedPrintPrefix(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (g_pszSupLibHardenedProgName)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr(g_pszSupLibHardenedProgName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintStr(": ");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsyncDECLHIDDEN(void) supR3HardenedFatalMsgV(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va)
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync{
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync /*
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * First to the log.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync */
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync supR3HardenedLog("Error %d in %s! (enmWhat=%d)\n", rc, pszWhere, enmWhat);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync va_list vaCopy;
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync va_copy(vaCopy, va);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync supR3HardenedLogV(pszMsgFmt, vaCopy);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync va_end(vaCopy);
11c2b573e2625474a51ae55ee1f3f82936f125davboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync /*
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync * Then to the console.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync */
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintPrefix();
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintF("Error %d in %s!\n", rc, pszWhere);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintPrefix();
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync va_copy(vaCopy, va);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintFV(pszMsgFmt, vaCopy);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync va_end(vaCopy);
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintChr('\n');
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync switch (enmWhat)
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync {
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync case kSupInitOp_Driver:
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintChr('\n');
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintPrefix();
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintStr("Tip! Make sure the kernel module is loaded. It may also help to reinstall VirtualBox.\n");
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync break;
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync case kSupInitOp_Misc:
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync case kSupInitOp_IPRT:
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync case kSupInitOp_Integrity:
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync case kSupInitOp_RootCheck:
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintChr('\n');
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintPrefix();
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync suplibHardenedPrintStr("Tip! It may help to reinstall VirtualBox.\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync default:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* no hints here */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync#ifdef SUP_HARDENED_SUID
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /*
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * Drop any root privileges we might be holding, this won't return
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync * if it fails but end up calling supR3HardenedFatal[V].
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync supR3HardenedMainDropPrivileges();
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync#endif /* SUP_HARDENED_SUID */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync /*
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).
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync */
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int pid = fork();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pid <= 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync static volatile bool s_fRecursive = false; /* Loader hooks may cause recursion. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!s_fRecursive)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync s_fRecursive = true;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPTRUSTEDERROR pfnTrustedError = supR3HardenedMainGetTrustedError(g_pszSupLibHardenedProgName);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pfnTrustedError)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pfnTrustedError(pszWhere, enmWhat, rc, pszMsgFmt, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync s_fRecursive = false;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Quit
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedExit(RTEXITCODE_FAILURE);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatalMsg(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, pszMsgFmt);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsgV(pszWhere, enmWhat, rc, pszMsgFmt, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatalV(const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedLog("Fatal error:\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list vaCopy;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_copy(vaCopy, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedLogV(pszFormat, vaCopy);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(vaCopy);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintPrefix();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintFV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedExit(RTEXITCODE_FAILURE);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(void) supR3HardenedFatal(const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, pszFormat);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedErrorV(int rc, bool fFatal, const char *pszFormat, va_list va)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (fFatal)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedLog("Error (rc=%d):\n", rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list vaCopy;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_copy(vaCopy, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedLogV(pszFormat, vaCopy);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(vaCopy);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintPrefix();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedPrintFV(pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncDECLHIDDEN(int) supR3HardenedError(int rc, bool fFatal, const char *pszFormat, ...)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_list va;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_start(va, pszFormat);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedErrorV(rc, fFatal, pszFormat, va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync va_end(va);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Attempts to open /dev/vboxdrv (or equvivalent).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks This function will not return on failure.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedMainOpenDevice(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = suplibOsInit(&g_SupPreInitData.Data, false /*fPreInit*/, true /*fUnrestricted*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (RT_SUCCESS(rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync switch (rc)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo better messages! */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_VM_DRIVER_NOT_INSTALLED:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver not installed");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_VM_DRIVER_NOT_ACCESSIBLE:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver not accessible");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_VM_DRIVER_LOAD_ERROR:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_VM_DRIVER_LOAD_ERROR");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_VM_DRIVER_OPEN_ERROR:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_VM_DRIVER_OPEN_ERROR");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_VM_DRIVER_VERSION_MISMATCH:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel driver version mismatch");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_ACCESS_DENIED:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "VERR_ACCESS_DENIED");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_NO_MEMORY:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Kernel memory allocation/mapping failed");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_SUPDRV_HARDENING_EVIL_HANDLE:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPDRV_HARDENING_EVIL_HANDLE");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync case VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc, "VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync default:
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("suplibOsInit", kSupInitOp_Driver, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Unknown rc=%d", rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef SUP_HARDENED_SUID
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Grabs extra non-root capabilities / privileges that we might require.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * This is currently only used for being able to do ICMP from the NAT engine.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @note We still have root privileges at the time of this call.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedMainGrabCapabilites(void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# if defined(RT_OS_LINUX)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
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.
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (g_uCaps != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef USE_LIB_PCAP
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* XXX cap_net_bind_service */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!cap_set_proc(cap_from_text("all-eip cap_net_raw+ep")))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync prctl(PR_SET_KEEPCAPS, 1 /*keep=*/, 0, 0, 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync prctl(PR_SET_DUMPABLE, 1 /*dump*/, 0, 0, 0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# else
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));
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync memset(hdr, 0, sizeof(*hdr));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync hdr->version = _LINUX_CAPABILITY_VERSION;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memset(cap, 0, sizeof(*cap));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap->effective = g_uCaps;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap->permitted = g_uCaps;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!capset(hdr, cap))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync prctl(PR_SET_KEEPCAPS, 1 /*keep*/, 0, 0, 0);
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync prctl(PR_SET_DUMPABLE, 1 /*dump*/, 0, 0, 0);
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync# endif /* !USE_LIB_PCAP */
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync }
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync# elif defined(RT_OS_SOLARIS)
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync /*
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.
b2e90826ea719b22452d1ff7b977d4f40995b428vboxsync */
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync seteuid(g_uid);
02e851310fa6b70ff20500172a9758a50731a451vboxsync priv_set_t *pPrivEffective = priv_allocset();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync priv_set_t *pPrivNew = priv_allocset();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pPrivEffective && pPrivNew)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync int rc = getppriv(PRIV_EFFECTIVE, pPrivEffective);
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync seteuid(0);
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync if (!rc)
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync {
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync priv_copyset(pPrivEffective, pPrivNew);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync rc = priv_addset(pPrivNew, PRIV_NET_ICMPACCESS);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync if (!rc)
a144bb4a097a1818739e00ba31bea88ce63f5345vboxsync {
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync /* Order is important, as one can't set a privilege which is
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync * not in the permitted privilege set. */
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync rc = setppriv(PRIV_SET, PRIV_EFFECTIVE, pPrivNew);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync if (rc)
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set effective privilege set.\n");
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync rc = setppriv(PRIV_SET, PRIV_PERMITTED, pPrivNew);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync if (rc)
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to set permitted privilege set.\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync supR3HardenedError(rc, false, "SUPR3HardenedMain: failed to add NET_ICMPACCESS privilege.\n");
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync else
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* for memory allocation failures just continue */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync seteuid(0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
090c459b9e90ca46e2ce2b8c81533ade3b23f3e9vboxsync if (pPrivEffective)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync priv_freeset(pPrivEffective);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync if (pPrivNew)
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync priv_freeset(pPrivNew);
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync# endif
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync}
daf1b2aee694fc8aca9e056e825b3359170ecf37vboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Look at the environment for some special options.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3GrabOptions(void)
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync{
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync const char *pszOpt;
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_uCaps = 0;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
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 */
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync if (getuid() != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * CAP_NET_RAW.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Default: enabled.
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * Can be disabled with 'export VBOX_HARD_CAP_NET_RAW=0'.
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszOpt = getenv("VBOX_HARD_CAP_NET_RAW");
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync if ( !pszOpt
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync || memcmp(pszOpt, "0", sizeof("0")) != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_uCaps = CAP_TO_MASK(CAP_NET_RAW);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync * CAP_NET_BIND_SERVICE.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Default: disabled.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Can be enabled with 'export VBOX_HARD_CAP_NET_BIND_SERVICE=1'.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync pszOpt = getenv("VBOX_HARD_CAP_NET_BIND_SERVICE");
af0a09edb4c1431b606fe207d4138da008f67f13vboxsync if ( pszOpt
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync && memcmp(pszOpt, "0", sizeof("0")) != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync g_uCaps |= CAP_TO_MASK(CAP_NET_BIND_SERVICE);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync/**
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync * Drop any root privileges we might be holding.
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync */
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsyncstatic void supR3HardenedMainDropPrivileges(void)
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync{
564cc620447c495b6ff9cbb9274e225692fe38dfvboxsync /*
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 */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync uid_t euid, ruid, suid;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync gid_t egid, rgid, sgid;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# if defined(RT_OS_DARWIN)
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 setgid(g_gid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync setuid(g_uid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync euid = geteuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ruid = suid = getuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync egid = getegid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rgid = sgid = getgid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# elif defined(RT_OS_SOLARIS)
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 setregid(g_gid, g_gid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync setreuid(g_uid, g_uid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync euid = geteuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ruid = suid = getuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync egid = getegid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rgid = sgid = getgid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# else
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 setresgid(g_gid, g_gid, g_gid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync setresuid(g_uid, g_uid, g_uid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (getresuid(&ruid, &euid, &suid) != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync euid = geteuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ruid = suid = getuid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (getresgid(&rgid, &egid, &sgid) != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync egid = getegid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rgid = sgid = getgid();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* Check that it worked out all right. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if ( euid != g_uid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || ruid != g_uid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || suid != g_uid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || egid != g_gid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || rgid != g_gid
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || sgid != g_gid)
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 euid, ruid, suid, egid, rgid, sgid, g_uid, g_gid);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# if RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Re-enable the cap_net_raw capability which was disabled during setresuid.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (g_uCaps != 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# ifdef USE_LIB_PCAP
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo Warn if that does not work? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* XXX cap_net_bind_service */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap_set_proc(cap_from_text("cap_net_raw+ep"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# else
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 memset(hdr, 0, sizeof(*hdr));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync hdr->version = _LINUX_CAPABILITY_VERSION;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync memset(cap, 0, sizeof(*cap));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap->effective = g_uCaps;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync cap->permitted = g_uCaps;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo Warn if that does not work? */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync capset(hdr, cap);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif /* !USE_LIB_PCAP */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync# endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif /* SUP_HARDENED_SUID */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * and calls RTR3InitEx.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param fFlags The SUPR3HardenedMain fFlags argument, passed to supR3PreInit.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks VBoxRT contains both IPRT and SUPR3.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @remarks This function will not return on failure.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic void supR3HardenedMainInitRuntime(uint32_t fFlags)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Construct the name.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync char szPath[RTPATH_MAX];
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxRT" SUPLIB_DLL_SUFF));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync suplibHardenedStrCat(szPath, "/VBoxRT" SUPLIB_DLL_SUFF);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Open it and resolve the symbols.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#if defined(RT_OS_WINDOWS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!hMod)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_MODULE_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "LoadLibrary \"%s\" failed (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, GetLastError());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3InitEx"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pfnRTInitEx)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"RTR3InitEx\" not found in \"%s\" (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, GetLastError());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)GetProcAddress(hMod, SUP_HARDENED_SYM("supR3PreInit"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pfnSUPPreInit)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"supR3PreInit\" not found in \"%s\" (rc=%d)",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, GetLastError());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* the dlopen crowd */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pvMod)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_MODULE_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "dlopen(\"%s\",) failed: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, dlerror());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("RTR3InitEx"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pfnRTInitEx)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"RTR3InitEx\" not found in \"%s\"!\ndlerror: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, dlerror());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("supR3PreInit"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pfnSUPPreInit)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, VERR_SYMBOL_NOT_FOUND,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "Entrypoint \"supR3PreInit\" not found in \"%s\"!\ndlerror: %s",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync szPath, dlerror());
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Make the calls.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedGetPreInitData(&g_SupPreInitData);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = pfnSUPPreInit(&g_SupPreInitData, fFlags);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (RT_FAILURE(rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, rc,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync "supR3PreInit failed with rc=%d", rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync const char *pszExePath = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#ifdef RT_OS_LINUX
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!supR3HardenedMainIsProcSelfExeAccssible())
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pszExePath = g_szSupLibHardenedExePath;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#endif
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = pfnRTInitEx(RTR3INIT_VER_1,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV ? 0 : RTR3INIT_FLAGS_SUPLIB,
0 /*cArgs*/, NULL /*papszArgs*/, pszExePath);
if (RT_FAILURE(rc))
supR3HardenedFatalMsg("supR3HardenedMainInitRuntime", kSupInitOp_IPRT, rc,
"RTR3InitEx failed with rc=%d", rc);
}
/**
* Loads the DLL/SO/DYLIB containing the actual program and
* resolves the TrustedError symbol.
*
* This is very similar to supR3HardenedMainGetTrustedMain().
*
* @returns Pointer to the trusted error symbol if it is exported, NULL
* and no error messages otherwise.
* @param pszProgName The program name.
*/
static PFNSUPTRUSTEDERROR supR3HardenedMainGetTrustedError(const char *pszProgName)
{
/*
* Construct the name.
*/
char szPath[RTPATH_MAX];
supR3HardenedPathAppPrivateArch(szPath, sizeof(szPath) - 10);
size_t cch = suplibHardenedStrLen(szPath);
suplibHardenedStrCopyEx(&szPath[cch], sizeof(szPath) - cch, "/", pszProgName, SUPLIB_DLL_SUFF, NULL);
/*
* Open it and resolve the symbol.
*/
#if defined(RT_OS_WINDOWS)
HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
if (!hMod)
return NULL;
FARPROC pfn = GetProcAddress(hMod, SUP_HARDENED_SYM("TrustedError"));
if (!pfn)
return NULL;
return (PFNSUPTRUSTEDERROR)pfn;
#else
/* the dlopen crowd */
void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
if (!pvMod)
return NULL;
void *pvSym = dlsym(pvMod, SUP_HARDENED_SYM("TrustedError"));
if (!pvSym)
return NULL;
return (PFNSUPTRUSTEDERROR)(uintptr_t)pvSym;
#endif
}
/**
* Loads the DLL/SO/DYLIB containing the actual program and
* resolves the TrustedMain symbol.
*
* @returns Pointer to the trusted main of the actual program.
* @param pszProgName The program name.
* @remarks This function will not return on failure.
*/
static PFNSUPTRUSTEDMAIN supR3HardenedMainGetTrustedMain(const char *pszProgName)
{
/*
* Construct the name.
*/
char szPath[RTPATH_MAX];
supR3HardenedPathAppPrivateArch(szPath, sizeof(szPath) - 10);
size_t cch = suplibHardenedStrLen(szPath);
suplibHardenedStrCopyEx(&szPath[cch], sizeof(szPath) - cch, "/", pszProgName, SUPLIB_DLL_SUFF, NULL);
/*
* Open it and resolve the symbol.
*/
#if defined(RT_OS_WINDOWS)
HMODULE hMod = (HMODULE)supR3HardenedWinLoadLibrary(szPath, false /*fSystem32Only*/);
if (!hMod)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibrary \"%s\" failed, rc=%d\n",
szPath, GetLastError());
FARPROC pfn = GetProcAddress(hMod, SUP_HARDENED_SYM("TrustedMain"));
if (!pfn)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\" (rc=%d)\n",
szPath, GetLastError());
return (PFNSUPTRUSTEDMAIN)pfn;
#else
/* the dlopen crowd */
void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
if (!pvMod)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: dlopen(\"%s\",) failed: %s\n",
szPath, dlerror());
void *pvSym = dlsym(pvMod, SUP_HARDENED_SYM("TrustedMain"));
if (!pvSym)
supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\"!\ndlerror: %s\n",
szPath, dlerror());
return (PFNSUPTRUSTEDMAIN)(uintptr_t)pvSym;
#endif
}
/**
* Secure main.
*
* This is used for the set-user-ID-on-execute binaries on unixy systems
* and when using the open-vboxdrv-via-root-service setup on Windows.
*
* This function will perform the integrity checks of the VirtualBox
* installation, open the support driver, open the root service (later),
* and load the DLL corresponding to \a pszProgName and execute its main
* function.
*
* @returns Return code appropriate for main().
*
* @param pszProgName The program name. This will be used to figure out which
* DLL/SO/DYLIB to load and execute.
* @param fFlags Flags.
* @param argc The argument count.
* @param argv The argument vector.
* @param envp The environment vector.
*/
DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp)
{
SUP_DPRINTF(("SUPR3HardenedMain: pszProgName=%s fFlags=%#x\n", pszProgName, fFlags));
/*
* Note! At this point there is no IPRT, so we will have to stick
* to basic CRT functions that everyone agree upon.
*/
g_pszSupLibHardenedProgName = pszProgName;
g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC;
g_SupPreInitData.Data.hDevice = SUP_HDEVICE_NIL;
g_SupPreInitData.u32EndMagic = SUPPREINITDATA_MAGIC;
#ifdef SUP_HARDENED_SUID
# ifdef RT_OS_LINUX
/*
* On linux we have to make sure the path is initialized because we
* *might* not be able to access /proc/self/exe after the seteuid call.
*/
supR3HardenedGetFullExePath();
# endif
/*
* Grab any options from the environment.
*/
supR3GrabOptions();
/*
* Check that we're root, if we aren't then the installation is butchered.
*/
g_uid = getuid();
g_gid = getgid();
if (geteuid() != 0 /* root */)
supR3HardenedFatalMsg("SUPR3HardenedMain", kSupInitOp_RootCheck, VERR_PERMISSION_DENIED,
"Effective UID is not root (euid=%d egid=%d uid=%d gid=%d)",
geteuid(), getegid(), g_uid, g_gid);
#endif /* SUP_HARDENED_SUID */
#ifdef RT_OS_WINDOWS
/*
* Windows: First respawn. On Windows we will respawn the process twice to establish
* something we can put some kind of reliable trust in. The first respawning aims
* at dropping compatibility layers and process "security" solutions.
*/
if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
&& supR3HardenedWinIsReSpawnNeeded(1 /*iWhich*/, argc, argv))
{
SUP_DPRINTF(("SUPR3HardenedMain: Respawn #1\n"));
supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV);
supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
return supR3HardenedWinReSpawn(1 /*iWhich*/);
}
/*
* Windows: Initialize the image verification global data so we can verify the
* signature of the process image and hook the core of the DLL loader API so we
* can check the signature of all DLLs mapped into the process.
*/
supR3HardenedWinInit(fFlags);
#endif /* RT_OS_WINDOWS */
/*
* Validate the installation.
*/
supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
/*
* The next steps are only taken if we actually need to access the support
* driver.
*/
if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
{
#ifdef RT_OS_WINDOWS
/*
* Windows: Verify the process (repeated by the kernel later.
*/
supR3HardenedWinVerifyProcess();
/*
* Windows: The second respawn. This time we make a special arrangement
* with vboxdrv to monitor access to the new process from its inception.
*/
if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv))
{
SUP_DPRINTF(("SUPR3HardenedMain: Respawn #2\n"));
return supR3HardenedWinReSpawn(2 /* iWhich*/);
}
SUP_DPRINTF(("SUPR3HardenedMain: Final process, opening VBoxDrv...\n"));
supR3HardenedWinFlushLoaderCache();
#endif /* RT_OS_WINDOWS */
/*
* Open the vboxdrv device.
*/
supR3HardenedMainOpenDevice();
}
#ifdef RT_OS_WINDOWS
/*
* Windows: Enable the use of windows APIs to verify images at load time.
*/
supR3HardenedWinFlushLoaderCache();
supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(g_pszSupLibHardenedProgName);
g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY;
#endif
#ifdef SUP_HARDENED_SUID
/*
* Grab additional capabilities / privileges.
*/
supR3HardenedMainGrabCapabilites();
/*
* Drop any root privileges we might be holding (won't return on failure)
*/
supR3HardenedMainDropPrivileges();
#endif
/*
* Load the IPRT, hand the SUPLib part the open driver and
* call RTR3InitEx.
*/
SUP_DPRINTF(("SUPR3HardenedMain: Load Runtime...\n"));
g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_INIT_RUNTIME;
supR3HardenedMainInitRuntime(fFlags);
/*
* Load the DLL/SO/DYLIB containing the actual program
* and pass control to it.
*/
SUP_DPRINTF(("SUPR3HardenedMain: Load TrustedMain...\n"));
g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_GET_TRUSTED_MAIN;
PFNSUPTRUSTEDMAIN pfnTrustedMain = supR3HardenedMainGetTrustedMain(pszProgName);
SUP_DPRINTF(("SUPR3HardenedMain: Calling TrustedMain (%p)...\n", pfnTrustedMain));
g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_CALLED_TRUSTED_MAIN;
return pfnTrustedMain(argc, argv, envp);
}