summary refs log tree commit diff
path: root/pkgs/applications/virtualization/virtualbox/hardened.patch
blob: a788a1df3caa659aa38ed850db1fb1f771c98b6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
index 70c596a..78972ed 100644
--- a/include/iprt/mangling.h
+++ b/include/iprt/mangling.h
@@ -1068,6 +1068,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)
@@ -1105,6 +1106,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 7e42754..b4de4c8 100644
--- a/include/iprt/path.h
+++ b/include/iprt/path.h
@@ -1049,6 +1049,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 2760306..0ce6c92 100644
--- a/include/iprt/process.h
+++ b/include/iprt/process.h
@@ -313,6 +313,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 c39d2f7..896b352 100644
--- a/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
+++ b/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
@@ -1415,18 +1415,19 @@ static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bo
         NOREF(fRelaxed);
 #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");
     }
 
     /*
-     * World must not have write access.  There is no relaxing this rule.
+     * World must not have write access.
+     * There is no relaxing this rule, except when it comes to the Nix store.
      */
-    if (pFsObjState->Stat.st_mode & S_IWOTH)
+    if (pFsObjState->Stat.st_mode & S_IWOTH && suplibHardenedStrCmp(pszPath, "/nix/store"))
         return supR3HardenedSetError3(VERR_SUPLIB_WORLD_WRITABLE, pErrInfo,
                                       "World writable: '", pszPath, "'");
 
diff --git a/src/VBox/Main/src-server/MachineImpl.cpp b/src/VBox/Main/src-server/MachineImpl.cpp
index 95dc9a7..39170bc 100644
--- a/src/VBox/Main/src-server/MachineImpl.cpp
+++ b/src/VBox/Main/src-server/MachineImpl.cpp
@@ -7326,7 +7326,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");
     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 e9e1ba62..4d1c1e1 100644
--- a/src/VBox/Main/src-server/NetworkServiceRunner.cpp
+++ b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
@@ -79,7 +79,7 @@ int NetworkServiceRunner::start()
 
     /* 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 8559d2a..2177f27 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));
@@ -90,7 +90,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));
@@ -202,7 +202,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 be2ad8f..7ddf105 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");
+}
+
+
 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 7bde6af..2656cae 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/"
+
+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)
 {