Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 66525)
+++ /trunk/include/VBox/err.h	(revision 66526)
@@ -1921,4 +1921,11 @@
 /** Unable to establish trusted of VM process (5). */
 #define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_5          (-3775)
+/** Unable to make text memory writeable (hardening). */
+#define VERR_SUPLIB_TEXT_NOT_WRITEABLE              (-3775)
+/** Unable to seal text memory again to protect against write access (hardening). */
+#define VERR_SUPLIB_TEXT_NOT_SEALED                 (-3776)
+/** Unexpected instruction encountered for which there is no patch strategy
+ * implemented (hardening). */
+#define VERR_SUPLIB_UNEXPECTED_INSTRUCTION          (-3777)
 /** @} */
 
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 66526)
@@ -416,4 +416,33 @@
 endif
 
+# Things specific to the posix crowd.
+if1of ($(KBUILD_TARGET), linux darwin solaris)
+ SUPR3HardenedStatic_DEFS += \
+ 	IN_DIS \
+ 	DIS_CORE_ONLY \
+ 	LOG_DISABLED
+ SUPR3HardenedStatic_DEFS.linux += \
+ 	SUP_HARDENED_WITH_DLMOPEN
+ SUPR3HardenedStatic_DEFS.solaris += \
+ 	SUP_HARDENED_WITH_DLMOPEN
+
+ SUPR3HardenedStatic_INCS += $(VBOX_PATH_RUNTIME_SRC)/include
+
+ SUPR3HardenedStatic_SOURCES += \
+ 	posix/SUPR3HardenedMain-posix.cpp \
+	posix/SUPR3HardenedMainA-posix.asm \
+       \
+ 	$(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg1Weak.cpp \
+ 	$(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2.cpp \
+ 	$(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2Weak.cpp \
+ 	$(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2WeakV.cpp \
+ 	$(VBOX_PATH_RUNTIME_SRC)/generic/RTAssertShouldPanic-generic.cpp \
+       \
+ 	../../Disassembler/DisasmCore.cpp \
+ 	../../Disassembler/DisasmTables.cpp \
+ 	../../Disassembler/DisasmTablesX64.cpp \
+ 	../../Disassembler/DisasmReg.cpp
+endif
+
 SUPR3HardenedMain.cpp_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV)
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 66526)
@@ -449,4 +449,8 @@
 DECLHIDDEN(int)     supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
                                             PRTERRINFO pErrInfo);
+#ifdef RT_OS_DARWIN
+DECLHIDDEN(int)     supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
+                                                          PRTERRINFO pErrInfo);
+#endif
 DECLHIDDEN(void)    supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData);
 DECLHIDDEN(int)     supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData);
@@ -484,5 +488,7 @@
 DECLHIDDEN(void)    supR3HardenedWinReportErrorToParent(const char *pszWhere, SUPINITOP enmWhat, int rc,
                                                         const char *pszFormat, va_list va);
-#endif
+#else   /* !RT_OS_WINDOWS */
+DECLHIDDEN(void)    supR3HardenedPosixInit(void);
+#endif  /* !RT_OS_WINDOWS */
 
 SUPR3DECL(int)      supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages);
Index: /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 66526)
@@ -404,4 +404,7 @@
 
 #else /* UNIXes */
+# ifdef RT_OS_DARWIN
+#  define _POSIX_C_SOURCE 1 /* pick the correct prototype for unsetenv. */
+# endif
 # include <iprt/types.h> /* stdint fun on darwin. */
 
@@ -487,4 +490,41 @@
 
 
+/**
+ * Descriptor of an environment variable to purge.
+ */
+typedef struct SUPENVPURGEDESC
+{
+    /** Name of the environment variable to purge. */
+    const char         *pszEnv;
+    /** The length of the variable name. */
+    uint8_t             cchEnv;
+    /** Flag whether a failure in purging the variable leads to
+     * a fatal error resulting in an process exit. */
+    bool                fPurgeErrFatal;
+} SUPENVPURGEDESC;
+/** Pointer to a environment variable purge descriptor. */
+typedef SUPENVPURGEDESC *PSUPENVPURGEDESC;
+/** Pointer to a const environment variable purge descriptor. */
+typedef const SUPENVPURGEDESC *PCSUPENVPURGEDESC;
+
+/**
+ * Descriptor of an command line argument to purge.
+ */
+typedef struct SUPARGPURGEDESC
+{
+    /** Name of the argument to purge. */
+    const char         *pszArg;
+    /** The length of the argument name. */
+    uint8_t             cchArg;
+    /** Flag whether the argument is followed by an extra argument
+     * which must be purged too */
+    bool                fTakesValue;
+} SUPARGPURGEDESC;
+/** Pointer to a environment variable purge descriptor. */
+typedef SUPARGPURGEDESC *PSUPARGPURGEDESC;
+/** Pointer to a const environment variable purge descriptor. */
+typedef const SUPARGPURGEDESC *PCSUPARGPURGEDESC;
+
+
 /*********************************************************************************************************************************
 *   Global Variables                                                                                                             *
@@ -537,4 +577,25 @@
 #endif
 
+/** Environment variables to purge from the process because
+ * they are known to be harmful. */
+static const SUPENVPURGEDESC g_aSupEnvPurgeDescs[] =
+{
+    /* pszEnv                                       fPurgeErrFatal */
+    /* Qt related environment variables: */
+    { RT_STR_TUPLE("QT_QPA_PLATFORM_PLUGIN_PATH"),  true },
+    { RT_STR_TUPLE("QT_PLUGIN_PATH"),               true },
+    /* ALSA related environment variables: */
+    { RT_STR_TUPLE("ALSA_MIXER_SIMPLE_MODULES"),    true },
+    { RT_STR_TUPLE("LADSPA_PATH"),                  true },
+};
+
+/** Arguments to purge from the argument vector because
+ * they are known to be harmful. */
+static const SUPARGPURGEDESC g_aSupArgPurgeDescs[] =
+{
+    /* pszArg                        fTakesValue */
+    /* Qt related environment variables: */
+    { RT_STR_TUPLE("-platformpluginpath"),          true },
+};
 
 /*********************************************************************************************************************************
@@ -2004,4 +2065,135 @@
 
 /**
+ * Purge the process environment from any environment vairable which can lead
+ * to loading untrusted binaries compromising the process address space.
+ *
+ * @param   envp        The initial environment vector. (Can be NULL.)
+ */
+static void supR3HardenedMainPurgeEnvironment(char **envp)
+{
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aSupEnvPurgeDescs); i++)
+    {
+        /*
+         * Update the initial environment vector, just in case someone actually cares about it.
+         */
+        if (envp)
+        {
+            const char * const  pszEnv = g_aSupEnvPurgeDescs[i].pszEnv;
+            size_t const        cchEnv = g_aSupEnvPurgeDescs[i].cchEnv;
+            unsigned            iSrc   = 0;
+            unsigned            iDst   = 0;
+            char               *pszTmp;
+
+            while ((pszTmp = envp[iSrc]) != NULL)
+            {
+                if (   memcmp(pszTmp, pszEnv, cchEnv) != 0
+                    || (pszTmp[cchEnv] != '=' && pszTmp[cchEnv] != '\0'))
+                {
+                    if (iDst != iSrc)
+                        envp[iDst] = pszTmp;
+                    iDst++;
+                }
+                else
+                    SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropping envp[%d]=%s\n", iSrc, pszTmp));
+                iSrc++;
+            }
+
+            if (iDst != iSrc)
+                while (iDst <= iSrc)
+                    envp[iDst++] = NULL;
+        }
+
+        /*
+         * Remove from the process environment if present.
+         */
+#ifndef RT_OS_WINDOWS
+        const char *pszTmp = getenv(g_aSupEnvPurgeDescs[i].pszEnv);
+        if (pszTmp != NULL)
+        {
+            if (unsetenv((char *)g_aSupEnvPurgeDescs[i].pszEnv) == 0)
+                SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropped %s\n", pszTmp));
+            else
+                if (g_aSupEnvPurgeDescs[i].fPurgeErrFatal)
+                    supR3HardenedFatal("SUPR3HardenedMain: failed to purge %s environment variable! (errno=%d %s)\n",
+                                       g_aSupEnvPurgeDescs[i].pszEnv, errno, strerror(errno));
+                else
+                    SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropping %s failed! errno=%d\n", pszTmp, errno));
+        }
+#else
+        /** @todo Call NT API to do the same. */
+#endif
+    }
+}
+
+
+/**
+ * Returns the argument purge descriptor of the given argument if available.
+ *
+ * @retval 0 if it should not be purged.
+ * @retval 1 if it only the current argument should be purged.
+ * @retval 2 if the argument and the following (if present) should be purged.
+ * @param   pszArg           The argument to look for.
+ */
+static unsigned supR3HardenedMainShouldPurgeArg(const char *pszArg)
+{
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aSupArgPurgeDescs); i++)
+    {
+        size_t const cchPurge = g_aSupArgPurgeDescs[i].cchArg;
+        if (!memcmp(pszArg, g_aSupArgPurgeDescs[i].pszArg, cchPurge))
+        {
+            if (pszArg[cchPurge] == '\0')
+                return 1 + g_aSupArgPurgeDescs[i].fTakesValue;
+            if (   g_aSupArgPurgeDescs[i].fTakesValue
+                && (pszArg[cchPurge] == ':' || pszArg[cchPurge] == '='))
+                return 1;
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+ * Purges any command line arguments considered harmful.
+ *
+ * @returns nothing.
+ * @param   cArgsOrig        The original number of arguments.
+ * @param   papszArgsOrig    The original argument vector.
+ * @param   pcArgsNew        Where to store the new number of arguments on success.
+ * @param   ppapszArgsNew    Where to store the pointer to the purged argument vector.
+ */
+static void supR3HardenedMainPurgeArgs(int cArgsOrig, char **papszArgsOrig, int *pcArgsNew, char ***ppapszArgsNew)
+{
+    int    iDst = 0;
+#ifdef RT_OS_WINDOWS
+    char **papszArgsNew = papszArgsOrig; /* We allocated this, no need to allocate again. */
+#else
+    char **papszArgsNew = (char **)malloc((cArgsOrig + 1) * sizeof(char *));
+#endif
+    if (papszArgsNew)
+    {
+        for (int iSrc = 0; iSrc < cArgsOrig; iSrc++)
+        {
+            unsigned cPurgedArgs = supR3HardenedMainShouldPurgeArg(papszArgsOrig[iSrc]);
+            if (!cPurgedArgs)
+                papszArgsNew[iDst++] = papszArgsOrig[iSrc];
+            else
+                iSrc += cPurgedArgs - 1;
+        }
+
+        papszArgsNew[iDst] = NULL; /* The array is NULL terminated, just like envp. */
+    }
+    else
+        supR3HardenedFatal("SUPR3HardenedMain: failed to allocate memory for purged command line!\n");
+    *pcArgsNew     = iDst;
+    *ppapszArgsNew = papszArgsNew;
+
+#ifdef RT_OS_WINDOWS
+    /** @todo Update command line pointers in PEB, wont really work without it. */
+#endif
+}
+
+
+/**
  * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver,
  * and calls RTR3InitEx.
@@ -2368,5 +2560,12 @@
     supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(g_pszSupLibHardenedProgName);
     g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_VERIFY_TRUST_READY;
-#endif
+#else /* !RT_OS_WINDOWS */
+# ifndef RT_OS_FREEBSD /** @todo portme */
+    /*
+     * Posix: Hook the load library interface interface.
+     */
+    supR3HardenedPosixInit();
+# endif
+#endif /* !RT_OS_WINDOWS */
 
 #ifdef SUP_HARDENED_SUID
@@ -2381,4 +2580,11 @@
     supR3HardenedMainDropPrivileges();
 #endif
+
+    /*
+     * Purge any environment variables and command line arguments considered harmful.
+     */
+    /** @todo May need to move this to a much earlier stage on windows.  */
+    supR3HardenedMainPurgeEnvironment(envp);
+    supR3HardenedMainPurgeArgs(argc, argv, &argc, &argv);
 
     /*
Index: /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp	(revision 66526)
@@ -1036,7 +1036,7 @@
 }
 
-
-/**
- * Copies the three messages into the error buffer and returns @a rc.
+#ifdef RT_OS_DARWIN
+/**
+ * Copies the four messages into the error buffer and returns @a rc.
  *
  * @returns Returns @a rc
@@ -1046,15 +1046,16 @@
  * @param   pszMsg2             The second message part.
  * @param   pszMsg3             The third message part.
- */
-static int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
-                                  const char *pszMsg2, const char *pszMsg3)
-{
-    return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
-}
-
-#ifdef SOME_UNUSED_FUNCTION
-
-/**
- * Copies the two messages into the error buffer and returns @a rc.
+ * @param   pszMsg4             The fourth message part.
+ */
+static int supR3HardenedSetError4(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
+                                  const char *pszMsg2, const char *pszMsg3, const char *pszMsg4)
+{
+    return supR3HardenedSetErrorN(rc, pErrInfo, 4, pszMsg1, pszMsg2, pszMsg3, pszMsg4);
+}
+#endif /* RT_OS_DARWIN */
+
+
+/**
+ * Copies the three messages into the error buffer and returns @a rc.
  *
  * @returns Returns @a rc
@@ -1063,4 +1064,22 @@
  * @param   pszMsg1             The first message part.
  * @param   pszMsg2             The second message part.
+ * @param   pszMsg3             The third message part.
+ */
+static int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
+                                  const char *pszMsg2, const char *pszMsg3)
+{
+    return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
+}
+
+#ifdef SOME_UNUSED_FUNCTION
+
+/**
+ * Copies the two messages into the error buffer and returns @a rc.
+ *
+ * @returns Returns @a rc
+ * @param   rc                  The return code.
+ * @param   pErrInfo            The error info structure.
+ * @param   pszMsg1             The first message part.
+ * @param   pszMsg2             The second message part.
  */
 static int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
@@ -1070,4 +1089,7 @@
 }
 
+#endif /* SOME_UNUSED_FUNCTION */
+
+#ifdef RT_OS_DARWIN
 
 /**
@@ -1084,5 +1106,6 @@
 }
 
-#endif /* SOME_UNUSED_FUNCTION */
+#endif
+
 
 /**
@@ -1371,4 +1394,6 @@
  *                              directory (only used for grand parent
  *                              directories).
+ * @param   fSymlinksAllowed    Flag whether symlinks are allowed or not.
+ *                              If allowed the symlink object is verified not the target.
  * @param   pszPath             The path to the object. For error messages and
  *                              securing a couple of hacks.
@@ -1376,5 +1401,5 @@
  */
 static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed,
-                                       const char *pszPath, PRTERRINFO pErrInfo)
+                                       bool fSymlinksAllowed, const char *pszPath, PRTERRINFO pErrInfo)
 {
 #if defined(RT_OS_WINDOWS)
@@ -1398,23 +1423,29 @@
 
     /*
-     * The object type must be directory or file, no symbolic links or other
-     * risky stuff (sorry dude, but we're paranoid on purpose here).
-     */
-    if (   !S_ISDIR(pFsObjState->Stat.st_mode)
-        && !S_ISREG(pFsObjState->Stat.st_mode))
-    {
-        if (S_ISLNK(pFsObjState->Stat.st_mode))
-            return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
-                                          "Symlinks are not permitted: '", pszPath, "'");
-        return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
-                                      "Not regular file or directory: '", pszPath, "'");
-    }
-    if (fDir != !!S_ISDIR(pFsObjState->Stat.st_mode))
-    {
-        if (S_ISDIR(pFsObjState->Stat.st_mode))
-            return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
-                                          "Expected file but found directory: '", pszPath, "'");
-        return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
-                                      "Expected directory but found file: '", pszPath, "'");
+     * The object type must be directory or file. It can be a symbolic link
+     * if explicitely allowed. Otherwise this and other risky stuff is not allowed
+     * (sorry dude, but we're paranoid on purpose here).
+     */
+    if (   !S_ISLNK(pFsObjState->Stat.st_mode)
+        || !fSymlinksAllowed)
+    {
+
+        if (   !S_ISDIR(pFsObjState->Stat.st_mode)
+            && !S_ISREG(pFsObjState->Stat.st_mode))
+        {
+            if (S_ISLNK(pFsObjState->Stat.st_mode))
+                return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
+                                              "Symlinks are not permitted: '", pszPath, "'");
+            return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
+                                          "Not regular file or directory: '", pszPath, "'");
+        }
+        if (fDir != !!S_ISDIR(pFsObjState->Stat.st_mode))
+        {
+            if (S_ISDIR(pFsObjState->Stat.st_mode))
+                return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
+                                              "Expected file but found directory: '", pszPath, "'");
+            return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
+                                          "Expected directory but found file: '", pszPath, "'");
+        }
     }
 
@@ -1601,5 +1632,5 @@
             break;
         rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/,
-                                         pszDirPath, pErrInfo);
+                                         false /*fSymlinksAllowed*/, pszDirPath, pErrInfo);
         if (RT_FAILURE(rc))
             break;
@@ -1659,5 +1690,6 @@
         rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
         if (RT_SUCCESS(rc))
-            rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
+            rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed,
+                                             false /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
         if (RT_FAILURE(rc))
             return rc;
@@ -1720,5 +1752,6 @@
         rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
         if (RT_SUCCESS(rc))
-            rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
+            rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed,
+                                             false /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
         if (RT_FAILURE(rc))
             return rc;
@@ -1799,4 +1832,162 @@
 
 
+#ifdef RT_OS_DARWIN
+/**
+ * Verfies a file following symlinks.
+ *
+ * @returns VBox status code, error buffer filled on failure.
+ * @param   pszFilename         The file to verify.
+ * @param   hNativeFile         Handle to the file, verify that it's the same
+ *                              as we ended up with when verifying the path.
+ *                              RTHCUINTPTR_MAX means NIL here.
+ * @param   fMaybe3rdParty      Set if the file is could be a supplied by a
+ *                              third party.  Different validation rules may
+ *                              apply to 3rd party code on some platforms.
+ * @param   pErrInfo            Where to return extended error information.
+ *                              Optional.
+ *
+ * @note    This is only used on OS X for libraries loaded with dlopen() because
+ *          the frameworks use symbolic links to point to the relevant library.
+ *
+ * @sa      supR3HardenedVerifyFile
+ */
+DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
+                                                      PRTERRINFO pErrInfo)
+{
+    RT_NOREF1(fMaybe3rdParty);
+
+    /*
+     * Validate the input path and parse it.
+     */
+    SUPR3HARDENEDPATHINFO Info;
+    int rc = supR3HardenedVerifyPathSanity(pszFilename, pErrInfo, &Info);
+    if (RT_FAILURE(rc))
+        return rc;
+    if (Info.fDirSlash)
+        return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
+                                      "The file path specifies a directory: '", pszFilename, "'");
+
+    /*
+     * Verify each component from the root up.
+     */
+    uint32_t                iLoops = 0;
+    SUPR3HARDENEDFSOBJSTATE FsObjState;
+    uint32_t                iComponent = 0;
+    while (iComponent < Info.cComponents)
+    {
+        bool fFinal   = iComponent + 1 == Info.cComponents;
+        bool fRelaxed = iComponent + 2 < Info.cComponents;
+        Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
+        rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * In case the component is a symlink expand it and start from the beginning after
+             * verifying it has the proper access rights.
+             * Furthermore only allow symlinks which don't contain any .. or . in the target
+             * (enforced by supR3HardenedVerifyPathSanity).
+             */
+            rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed,
+                                             true /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
+            if (   RT_SUCCESS(rc)
+                && S_ISLNK(FsObjState.Stat.st_mode))
+            {
+                /* Don't loop forever. */
+                iLoops++;
+                if (iLoops < 8)
+                {
+                    /*
+                     * Construct new path by replacing the current component by the symlink value.
+                     * Note! readlink() is a weird API that doesn't necessarily indicates if the
+                     *       buffer is too small.
+                     */
+                    char   szPath[RTPATH_MAX];
+                    size_t const cchBefore = Info.aoffComponents[iComponent]; /* includes slash */
+                    size_t const cchAfter  = fFinal ? 0 : 1 /*slash*/ + Info.cch - Info.aoffComponents[iComponent + 1];
+                    if (sizeof(szPath) > cchBefore + cchAfter + 2)
+                    {
+                        ssize_t cchTarget = readlink(Info.szPath, szPath, sizeof(szPath) - 1);
+                        if (cchTarget > 0)
+                        {
+                            /* Some serious paranoia against embedded zero terminator and weird return values. */
+                            szPath[cchTarget] = '\0';
+                            size_t cchLink = strlen(szPath);
+
+                            /* Strip trailing dirslashes of non-final link. */
+                            if (!fFinal)
+                                while (cchLink > 1 and szPath[cchLink - 1] == '/')
+                                    cchLink--;
+
+                            /* Check link value sanity and buffer size. */
+                            if (cchLink == 0)
+                                return supR3HardenedSetError3(VERR_ACCESS_DENIED, pErrInfo,
+                                                              "Bad readlink return for '", Info.szPath, "'");
+                            if (szPath[0] == '/')
+                                return supR3HardenedSetError3(VERR_ACCESS_DENIED, pErrInfo,
+                                                              "Absolute symbolic link not allowed: '", szPath, "'");
+                            if (cchBefore + cchLink + cchAfter + 1 /*terminator*/ > sizeof(szPath))
+                                return supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
+                                                             "Symlinks causing too long path!");
+
+                            /* Construct the new path. */
+                            if (cchBefore)
+                                memmove(&szPath[cchBefore], &szPath[0], cchLink);
+                            memcpy(&szPath[0], Info.szPath, cchBefore);
+                            if (!cchAfter)
+                                szPath[cchBefore + cchLink] = '\0';
+                            else
+                            {
+                                szPath[cchBefore + cchLink] = RTPATH_SLASH;
+                                memcpy(&szPath[cchBefore + cchLink + 1],
+                                       &Info.szPath[Info.aoffComponents[iComponent + 1]],
+                                       cchAfter); /* cchAfter includes a zero terminator */
+                            }
+
+                            /* Parse, copy and check the sanity (no '..' or '.') of the altered path. */
+                            rc = supR3HardenedVerifyPathSanity(szPath, pErrInfo, &Info);
+                            if (RT_FAILURE(rc))
+                                return rc;
+                            if (Info.fDirSlash)
+                                return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
+                                                              "The file path specifies a directory: '", szPath, "'");
+
+                            /* Restart from the current component. */
+                            continue;
+                        }
+                        int iErr = errno;
+                        supR3HardenedError(VERR_ACCESS_DENIED, false /*fFatal*/,
+                                           "supR3HardenedVerifyFileFollowSymlinks: Failed to readlink '%s': %s (%d)\n",
+                                           Info.szPath, strerror(iErr), iErr);
+                        return supR3HardenedSetError4(VERR_ACCESS_DENIED, pErrInfo,
+                                                      "readlink failed for '", Info.szPath, "': ", strerror(iErr));
+                    }
+                    return supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo, "Path too long for symlink replacing!");
+                }
+                else
+                    return supR3HardenedSetError3(VERR_TOO_MANY_SYMLINKS, pErrInfo,
+                                                  "Too many symbolic links: '", pszFilename, "'");
+            }
+        }
+        if (RT_FAILURE(rc))
+            return rc;
+        Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = !fFinal ? RTPATH_SLASH : '\0';
+        iComponent++;
+    }
+
+    /*
+     * Verify the file handle against the last component, if specified.
+     */
+    if (hNativeFile != RTHCUINTPTR_MAX)
+    {
+        rc = supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
+        if (RT_FAILURE(rc))
+            return rc;
+    }
+
+    return VINF_SUCCESS;
+}
+#endif /* RT_OS_DARWIN */
+
+
 /**
  * Gets the pre-init data for the hand-over to the other version
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp	(revision 66526)
@@ -32,5 +32,7 @@
 #ifdef IN_SUP_HARDENED_R3
 # undef DEBUG /* Warning: disables RT_STRICT */
-# define LOG_DISABLED
+# ifndef LOG_DISABLED
+#  define LOG_DISABLED
+# endif
 # define RTLOG_REL_DISABLED
 # include <iprt/log.h>
Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp	(revision 66526)
@@ -33,5 +33,7 @@
 # undef DEBUG /* Warning: disables RT_STRICT */
 # undef RT_STRICT
-# define LOG_DISABLED
+# ifndef LOG_DISABLED
+#  define LOG_DISABLED
+# endif
 # define RTLOG_REL_DISABLED
 # include <iprt/log.h>
Index: /trunk/src/VBox/HostDrivers/Support/solaris/SUPLib-solaris.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/solaris/SUPLib-solaris.cpp	(revision 66525)
+++ /trunk/src/VBox/HostDrivers/Support/solaris/SUPLib-solaris.cpp	(revision 66526)
@@ -32,5 +32,7 @@
 #ifdef IN_SUP_HARDENED_R3
 # undef DEBUG /* Warning: disables RT_STRICT */
-# define LOG_DISABLED
+# ifndef LOG_DISABLED
+#  define LOG_DISABLED
+# endif
 # define RTLOG_REL_DISABLED
 # include <iprt/log.h>
