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)
{
|