nixpkgs/pkgs/applications/virtualization/virtualbox/hardened.patch
aszlig 63fb845fcf
virtualbox: Rebase hardened.patch on top of 5.1.22
The merge of the version bump in
6fb9f89238 didn't take care of our patch
for the hardening mode and thus enabling VirtualBox without also
force-disabling hardening mode will result in a build error.

While the patch is largely identical with the old version, I've removed
one particular change around the following code:

    if (pFsObjState->Stat.st_mode & S_IWOTH)
        return supR3HardenedSetError3(VERR_SUPLIB_WORLD_WRITABLE, pErrInfo,
                                      "World writable: '", pszPath, "'");

In the old version of the patch we have checked whether the path is
within the Nix store and suppressed the error return if that's the case.

The reason why I did that in the first place was because we had a bunch
of symlinks which were writable.

In VirtualBox 5.1.22 the code specifically checks whether the file is a
symlink, so we can safely drop our change.

Tested via all of the "virtualbox" NixOS VM subtests and they now all
succeed.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
2017-06-23 05:48:54 +02:00

183 lines
8.4 KiB
Diff

diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
index c1daa8f..8618371 100644
--- a/include/iprt/mangling.h
+++ b/include/iprt/mangling.h
@@ -1440,6 +1440,7 @@
# define RTPathStripSuffix RT_MANGLER(RTPathStripSuffix)
# define RTPathStripFilename RT_MANGLER(RTPathStripFilename)
# define RTPathStripTrailingSlash RT_MANGLER(RTPathStripTrailingSlash)
+# define RTPathSuidDir RT_MANGLER(RTPathSuidDir)
# define RTPathTemp RT_MANGLER(RTPathTemp)
# define RTPathTraverseList RT_MANGLER(RTPathTraverseList)
# define RTPathUnlink RT_MANGLER(RTPathUnlink)
@@ -1478,6 +1479,7 @@
# define RTProcGetAffinityMask RT_MANGLER(RTProcGetAffinityMask)
# define RTProcGetExecutablePath RT_MANGLER(RTProcGetExecutablePath)
# define RTProcGetPriority RT_MANGLER(RTProcGetPriority)
+# define RTProcGetSuidPath RT_MANGLER(RTProcGetSuidPath)
# define RTProcIsRunningByName RT_MANGLER(RTProcIsRunningByName)
# define RTProcQueryParent RT_MANGLER(RTProcQueryParent)
# define RTProcQueryUsername RT_MANGLER(RTProcQueryUsername)
diff --git a/include/iprt/path.h b/include/iprt/path.h
index 8bd42bc..2c23d3e 100644
--- a/include/iprt/path.h
+++ b/include/iprt/path.h
@@ -1064,6 +1064,15 @@ RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst,
RTDECL(int) RTPathExecDir(char *pszPath, size_t cchPath);
/**
+ * Gets the path to the NixOS setuid wrappers directory.
+ *
+ * @returns iprt status code.
+ * @param pszPath Buffer where to store the path.
+ * @param cchPath Buffer size in bytes.
+ */
+RTDECL(int) RTPathSuidDir(char *pszPath, size_t cchPath);
+
+/**
* Gets the user home directory.
*
* @returns iprt status code.
diff --git a/include/iprt/process.h b/include/iprt/process.h
index 043653e..1070280 100644
--- a/include/iprt/process.h
+++ b/include/iprt/process.h
@@ -327,6 +327,16 @@ RTR3DECL(const char *) RTProcShortName(void);
RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath);
/**
+ * Gets the path to the NixOS setuid wrappers directory.
+ *
+ * @returns pszExecPath on success. NULL on buffer overflow or other errors.
+ *
+ * @param pszExecPath Where to store the path.
+ * @param cbExecPath The size of the buffer.
+ */
+RTR3DECL(char *) RTProcGetSuidPath(char *pszExecPath, size_t cbExecPath);
+
+/**
* Daemonize the current process, making it a background process.
*
* The way this work is that it will spawn a detached / backgrounded /
diff --git a/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp b/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
index ce0f288..6193108 100644
--- a/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
+++ b/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
@@ -1489,9 +1489,9 @@ static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bo
bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 2 /*bin*/ || suplibHardenedStrCmp(pszPath, "/usr/lib/iconv");
#else
NOREF(fRelaxed);
- bool fBad = true;
+ bool fBad = !(fDir && pFsObjState->Stat.st_mode & S_ISVTX && !suplibHardenedStrCmp(pszPath, "/nix/store"));
#endif
- if (fBad)
+ if (fBad && suplibHardenedStrCmp(pszPath, "/nix/store"))
return supR3HardenedSetError3(VERR_SUPLIB_WRITE_NON_SYS_GROUP, pErrInfo,
"An unknown (and thus untrusted) group has write access to '", pszPath,
"' and we therefore cannot trust the directory content or that of any subdirectory");
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 320c569..9bfe41f 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -7543,7 +7543,7 @@ HRESULT Machine::i_launchVMProcess(IInternalSessionControl *aControl,
/* get the path to the executable */
char szPath[RTPATH_MAX];
- RTPathAppPrivateArch(szPath, sizeof(szPath) - 1);
+ RTStrCopy(szPath, sizeof(szPath) - 1, "/run/wrappers/bin");
size_t cchBufLeft = strlen(szPath);
szPath[cchBufLeft++] = RTPATH_DELIMITER;
szPath[cchBufLeft] = 0;
diff --git a/src/VBox/Main/src-server/NetworkServiceRunner.cpp b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
index 1e38d99..5e43dda 100644
--- a/src/VBox/Main/src-server/NetworkServiceRunner.cpp
+++ b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
@@ -85,7 +85,7 @@ int NetworkServiceRunner::start(bool aKillProcOnStop)
/* get the path to the executable */
char exePathBuf[RTPATH_MAX];
- const char *exePath = RTProcGetExecutablePath(exePathBuf, RTPATH_MAX);
+ const char *exePath = RTProcGetSuidPath(exePathBuf, RTPATH_MAX);
char *substrSl = strrchr(exePathBuf, '/');
char *substrBs = strrchr(exePathBuf, '\\');
char *suffix = substrSl ? substrSl : substrBs;
diff --git a/src/VBox/Main/src-server/generic/NetIf-generic.cpp b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
index 98dc91a..43a819f 100644
--- a/src/VBox/Main/src-server/generic/NetIf-generic.cpp
+++ b/src/VBox/Main/src-server/generic/NetIf-generic.cpp
@@ -47,7 +47,7 @@ static int NetIfAdpCtl(const char * pcszIfName, const char *pszAddr, const char
const char *args[] = { NULL, pcszIfName, pszAddr, pszOption, pszMask, NULL };
char szAdpCtl[RTPATH_MAX];
- int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME));
+ int rc = RTPathSuidDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME));
if (RT_FAILURE(rc))
{
LogRel(("NetIfAdpCtl: failed to get program path, rc=%Rrc.\n", rc));
@@ -89,7 +89,7 @@ static int NetIfAdpCtl(HostNetworkInterface * pIf, const char *pszAddr, const ch
int NetIfAdpCtlOut(const char * pcszName, const char * pcszCmd, char *pszBuffer, size_t cBufSize)
{
char szAdpCtl[RTPATH_MAX];
- int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " ") - strlen(pcszCmd));
+ int rc = RTPathSuidDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " ") - strlen(pcszCmd));
if (RT_FAILURE(rc))
{
LogRel(("NetIfAdpCtlOut: Failed to get program path, rc=%Rrc\n", rc));
@@ -201,7 +201,7 @@ int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVirtualBox,
progress.queryInterfaceTo(aProgress);
char szAdpCtl[RTPATH_MAX];
- int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add"));
+ int rc = RTPathSuidDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add"));
if (RT_FAILURE(rc))
{
progress->i_notifyComplete(E_FAIL,
diff --git a/src/VBox/Runtime/r3/path.cpp b/src/VBox/Runtime/r3/path.cpp
index 944848e..744a261 100644
--- a/src/VBox/Runtime/r3/path.cpp
+++ b/src/VBox/Runtime/r3/path.cpp
@@ -81,6 +81,12 @@ RTDECL(int) RTPathExecDir(char *pszPath, size_t cchPath)
}
+RTDECL(int) RTPathSuidDir(char *pszPath, size_t cchPath)
+{
+ return RTStrCopy(pszPath, cchPath, "/run/wrappers/bin");
+}
+
+
RTDECL(int) RTPathAppPrivateNoArch(char *pszPath, size_t cchPath)
{
#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE)
diff --git a/src/VBox/Runtime/r3/process.cpp b/src/VBox/Runtime/r3/process.cpp
index 2aab645..9795f21 100644
--- a/src/VBox/Runtime/r3/process.cpp
+++ b/src/VBox/Runtime/r3/process.cpp
@@ -111,6 +111,26 @@ RTR3DECL(char *) RTProcGetExecutablePath(char *pszExecPath, size_t cbExecPath)
return NULL;
}
+/*
+ * Note the / at the end! This is important, because the functions using this
+ * will cut off everything after the rightmost / as this function is analogous
+ * to RTProcGetExecutablePath().
+ */
+#define SUIDDIR "/run/wrappers/bin/"
+
+RTR3DECL(char *) RTProcGetSuidPath(char *pszExecPath, size_t cbExecPath)
+{
+ if (cbExecPath >= sizeof(SUIDDIR))
+ {
+ memcpy(pszExecPath, SUIDDIR, sizeof(SUIDDIR));
+ pszExecPath[sizeof(SUIDDIR)] = '\0';
+ return pszExecPath;
+ }
+
+ AssertMsgFailed(("Buffer too small (%zu <= %zu)\n", cbExecPath, sizeof(SUIDDIR)));
+ return NULL;
+}
+
RTR3DECL(const char *) RTProcShortName(void)
{