VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp@ 11889

Last change on this file since 11889 was 11843, checked in by vboxsync, 16 years ago

#3076: Deal with /proc/self/exe becomming inaccessible on some systems.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/* $Id: SUPR3HardenedMain.cpp 11843 2008-08-29 18:05:18Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Hardened main().
4 */
5
6/*
7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#if defined(RT_OS_OS2)
35# define INCL_BASE
36# define INCL_ERRORS
37# include <os2.h>
38# include <stdio.h>
39
40#elif RT_OS_WINDOWS
41# include <Windows.h>
42# include <stdio.h>
43
44#else /* UNIXes */
45# include <iprt/types.h> /* stdint fun on darwin. */
46
47# include <stdio.h>
48# include <stdlib.h>
49# include <dlfcn.h>
50# include <limits.h>
51# include <errno.h>
52# include <unistd.h>
53# include <sys/stat.h>
54# include <sys/time.h>
55# include <stdio.h>
56# include <sys/types.h>
57# include <pwd.h>
58# ifdef RT_OS_DARWIN
59# include <mach-o/dyld.h>
60# endif
61
62#endif
63
64#include <VBox/sup.h>
65#include <VBox/err.h>
66#include <iprt/string.h>
67#include <iprt/param.h>
68
69#include "SUPLibInternal.h"
70
71
72/*******************************************************************************
73* Defined Constants And Macros *
74*******************************************************************************/
75/** @def SUP_HARDENED_SUID
76 * Whether we're employing set-user-ID-on-execute in the hardening.
77 */
78#if !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS) && !defined(RT_OS_L4)
79# define SUP_HARDENED_SUID
80#else
81# undef SUP_HARDENED_SUID
82#endif
83
84/** @def SUP_HARDENED_SYM
85 * Decorate a symbol that's resolved dynamically.
86 */
87#ifdef RT_OS_OS2
88# define SUP_HARDENED_SYM(sym) "_" ## sym
89#else
90# define SUP_HARDENED_SYM(sym) sym
91#endif
92
93
94/*******************************************************************************
95* Structures and Typedefs *
96*******************************************************************************/
97typedef DECLCALLBACK(int) FNTRUSTEDMAIN(int argc, char **argv, char **envp);
98typedef FNTRUSTEDMAIN *PFNTRUSTEDMAIN;
99
100/** @see RTR3InitEx */
101typedef DECLCALLBACK(int) FNRTR3INITEX(uint32_t iVersion, const char *pszProgramPath, bool fInitSUPLib);
102typedef FNRTR3INITEX *PFNRTR3INITEX;
103
104
105/*******************************************************************************
106* Global Variables *
107*******************************************************************************/
108/** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */
109static SUPPREINITDATA g_SupPreInitData;
110/** The progam executable path. */
111static char g_szSupLibHardenedExePath[RTPATH_MAX];
112/** The program directory path. */
113static char g_szSupLibHardenedDirPath[RTPATH_MAX];
114
115/** The program name. */
116static const char *g_pszSupLibHardenedProgName;
117
118
119/**
120 * @copydoc RTPathStripFilename.
121 */
122static void suplibHardenedPathStripFilename(char *pszPath)
123{
124 char *psz = pszPath;
125 char *pszLastSep = pszPath;
126
127 for (;; psz++)
128 {
129 switch (*psz)
130 {
131 /* handle separators. */
132#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
133 case ':':
134 pszLastSep = psz + 1;
135 break;
136
137 case '\\':
138#endif
139 case '/':
140 pszLastSep = psz;
141 break;
142
143 /* the end */
144 case '\0':
145 if (pszLastSep == pszPath)
146 *pszLastSep++ = '.';
147 *pszLastSep = '\0';
148 return;
149 }
150 }
151 /* will never get here */
152}
153
154
155/**
156 * @copydoc RTPathFilename
157 */
158DECLHIDDEN(char *) supR3HardenedPathFilename(const char *pszPath)
159{
160 const char *psz = pszPath;
161 const char *pszLastComp = pszPath;
162
163 for (;; psz++)
164 {
165 switch (*psz)
166 {
167 /* handle separators. */
168#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
169 case ':':
170 pszLastComp = psz + 1;
171 break;
172
173 case '\\':
174#endif
175 case '/':
176 pszLastComp = psz + 1;
177 break;
178
179 /* the end */
180 case '\0':
181 if (*pszLastComp)
182 return (char *)(void *)pszLastComp;
183 return NULL;
184 }
185 }
186
187 /* will never get here */
188 return NULL;
189}
190
191
192/**
193 * @copydoc RTPathAppPrivateNoArch
194 */
195DECLHIDDEN(int) supR3HardenedPathAppPrivateNoArch(char *pszPath, size_t cchPath)
196{
197#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE)
198 const char *pszSrcPath = RTPATH_APP_PRIVATE;
199 size_t cchPathPrivateNoArch = strlen(pszSrcPath);
200 if (cchPathPrivateNoArch >= cchPath)
201 supR3HardenedFatal("supR3HardenedPathAppPrivateNoArch: Buffer overflow, %lu >= %lu\n",
202 (unsigned long)cchPathPrivateNoArch, (unsigned long)cchPath);
203 memcpy(pszPath, pszSrcPath, cchPathPrivateNoArch + 1);
204 return VINF_SUCCESS;
205
206#else
207 return supR3HardenedPathProgram(pszPath, cchPath);
208#endif
209}
210
211
212/**
213 * @copydoc RTPathAppPrivateArch
214 */
215DECLHIDDEN(int) supR3HardenedPathAppPrivateArch(char *pszPath, size_t cchPath)
216{
217#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_PRIVATE_ARCH)
218 const char *pszSrcPath = RTPATH_APP_PRIVATE_ARCH;
219 size_t cchPathPrivateArch = strlen(pszSrcPath);
220 if (cchPathPrivateArch >= cchPath)
221 supR3HardenedFatal("supR3HardenedPathAppPrivateArch: Buffer overflow, %lu >= %lu\n",
222 (unsigned long)cchPathPrivateArch, (unsigned long)cchPath);
223 memcpy(pszPath, pszSrcPath, cchPathPrivateArch + 1);
224 return VINF_SUCCESS;
225
226#else
227 return supR3HardenedPathProgram(pszPath, cchPath);
228#endif
229}
230
231
232/**
233 * @copydoc RTPathSharedLibs
234 */
235DECLHIDDEN(int) supR3HardenedPathSharedLibs(char *pszPath, size_t cchPath)
236{
237#if !defined(RT_OS_WINDOWS) && defined(RTPATH_SHARED_LIBS)
238 const char *pszSrcPath = RTPATH_SHARED_LIBS;
239 size_t cchPathSharedLibs = strlen(pszSrcPath);
240 if (cchPathSharedLibs >= cchPath)
241 supR3HardenedFatal("supR3HardenedPathSharedLibs: Buffer overflow, %lu >= %lu\n",
242 (unsigned long)cchPathSharedLibs, (unsigned long)cchPath);
243 memcpy(pszPath, pszSrcPath, cchPathSharedLibs + 1);
244 return VINF_SUCCESS;
245
246#else
247 return supR3HardenedPathProgram(pszPath, cchPath);
248#endif
249}
250
251
252/**
253 * @copydoc RTPathAppDocs
254 */
255DECLHIDDEN(int) supR3HardenedPathAppDocs(char *pszPath, size_t cchPath)
256{
257#if !defined(RT_OS_WINDOWS) && defined(RTPATH_APP_DOCS)
258 const char *pszSrcPath = RTPATH_APP_DOCS;
259 size_t cchPathAppDocs = strlen(pszSrcPath);
260 if (cchPathAppDocs >= cchPath)
261 supR3HardenedFatal("supR3HardenedPathAppDocs: Buffer overflow, %lu >= %lu\n",
262 (unsigned long)cchPathAppDocs, (unsigned long)cchPath);
263 memcpy(pszPath, pszSrcPath, cchPathAppDocs + 1);
264 return VINF_SUCCESS;
265
266#else
267 return supR3HardenedPathProgram(pszPath, cchPath);
268#endif
269}
270
271
272/**
273 * Returns the full path to the executable.
274 *
275 * @returns IPRT status code.
276 * @param pszPath Where to store it.
277 * @param cchPath How big that buffer is.
278 */
279static void supR3HardenedGetFullExePath(void)
280{
281 /*
282 * Get the program filename.
283 *
284 * Most UNIXes have no API for obtaining the executable path, but provides a symbolic
285 * link in the proc file system that tells who was exec'ed. The bad thing about this
286 * is that we have to use readlink, one of the weirder UNIX APIs.
287 *
288 * Darwin, OS/2 and Windows all have proper APIs for getting the program file name.
289 */
290#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
291# ifdef RT_OS_LINUX
292 int cchLink = readlink("/proc/self/exe", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
293# elif defined(RT_OS_SOLARIS)
294 char szFileBuf[PATH_MAX + 1];
295 sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid());
296 int cchLink = readlink(szFileBuf, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
297# else /* RT_OS_FREEBSD: */
298 int cchLink = readlink("/proc/curproc/file", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1);
299# endif
300 if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedExePath) - 1)
301 supR3HardenedFatal("supR3HardenedPathProgram: couldn't read \"%s\", errno=%d cchLink=%d\n",
302 g_szSupLibHardenedExePath, errno, cchLink);
303 g_szSupLibHardenedExePath[cchLink] = '\0';
304
305#elif defined(RT_OS_OS2) || defined(RT_OS_L4)
306 _execname(g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath));
307
308#elif defined(RT_OS_DARWIN)
309 const char *pszImageName = _dyld_get_image_name(0);
310 if (!pszImageName)
311 supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed\n");
312 size_t cchImageName = strlen(pszImageName);
313 if (!cchImageName || cchImageName >= sizeof(g_szSupLibHardenedExePath))
314 supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed, cchImageName=%d\n", cchImageName);
315 memcpy(g_szSupLibHardenedExePath, pszImageName, cchImageName + 1);
316
317#elif defined(RT_OS_WINDOWS)
318 HMODULE hExe = GetModuleHandle(NULL);
319 if (!GetModuleFileName(hExe, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath)))
320 supR3HardenedFatal("supR3HardenedPathProgram: GetModuleFileName failed, rc=%d\n", GetLastError());
321#else
322# error needs porting.
323#endif
324
325 /*
326 * Strip off the filename part (RTPathStripFilename()).
327 */
328 strcpy(g_szSupLibHardenedDirPath, g_szSupLibHardenedExePath);
329 suplibHardenedPathStripFilename(g_szSupLibHardenedDirPath);
330}
331
332
333#ifdef RT_OS_LINUX
334/**
335 * Checks if we can read /proc/self/exe.
336 *
337 * This is used on linux to see if we have to call init
338 * with program path or not.
339 *
340 * @returns true / false.
341 */
342static bool supR3HardenedMainIsProcSelfExeAccssible(void)
343{
344 char szPath[RTPATH_MAX];
345 int cchLink = readlink("/proc/self/exe", szPath, sizeof(szPath));
346 return cchLink != -1;
347}
348#endif /* RT_OS_LINUX */
349
350
351
352/**
353 * @copydoc RTPathProgram
354 */
355DECLHIDDEN(int) supR3HardenedPathProgram(char *pszPath, size_t cchPath)
356{
357 /*
358 * Lazy init (probably not required).
359 */
360 if (!g_szSupLibHardenedDirPath[0])
361 supR3HardenedGetFullExePath();
362
363 /*
364 * Calc the length and check if there is space before copying.
365 */
366 unsigned cch = strlen(g_szSupLibHardenedDirPath) + 1;
367 if (cch <= cchPath)
368 {
369 memcpy(pszPath, g_szSupLibHardenedDirPath, cch + 1);
370 return VINF_SUCCESS;
371 }
372
373 supR3HardenedFatal("supR3HardenedPathProgram: Buffer too small (%u < %u)\n", cchPath, cch);
374 return VERR_BUFFER_OVERFLOW;
375}
376
377
378
379DECLHIDDEN(void) supR3HardenedFatalV(const char *pszFormat, va_list va)
380{
381 fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName);
382 vfprintf(stderr, pszFormat, va);
383 for (;;)
384#ifdef _MSC_VER
385 exit(1);
386#else
387 _Exit(1);
388#endif
389}
390
391
392DECLHIDDEN(void) supR3HardenedFatal(const char *pszFormat, ...)
393{
394 va_list va;
395 va_start(va, pszFormat);
396 supR3HardenedFatalV(pszFormat, va);
397 va_end(va);
398}
399
400
401DECLHIDDEN(int) supR3HardenedErrorV(int rc, bool fFatal, const char *pszFormat, va_list va)
402{
403 if (fFatal)
404 supR3HardenedFatalV(pszFormat, va);
405
406 fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName);
407 vfprintf(stderr, pszFormat, va);
408 return rc;
409}
410
411
412DECLHIDDEN(int) supR3HardenedError(int rc, bool fFatal, const char *pszFormat, ...)
413{
414 va_list va;
415 va_start(va, pszFormat);
416 supR3HardenedErrorV(rc, fFatal, pszFormat, va);
417 va_end(va);
418 return rc;
419}
420
421
422/**
423 * Wrapper around snprintf which will throw a fatal error on buffer overflow.
424 *
425 * @returns Number of chars in the result string.
426 * @param pszDst The destination buffer.
427 * @param cchDst The size of the buffer.
428 * @param pszFormat The format string.
429 * @param ... Format arguments.
430 */
431static size_t supR3HardenedStrPrintf(char *pszDst, size_t cchDst, const char *pszFormat, ...)
432{
433 va_list va;
434 va_start(va, pszFormat);
435#ifdef _MSC_VER
436 int cch = _vsnprintf(pszDst, cchDst, pszFormat, va);
437#else
438 int cch = vsnprintf(pszDst, cchDst, pszFormat, va);
439#endif
440 va_end(va);
441 if ((unsigned)cch >= cchDst || cch < 0)
442 supR3HardenedFatal("supR3HardenedStrPrintf: buffer overflow, %d >= %lu\n", cch, (long)cchDst);
443 return cch;
444}
445
446
447/**
448 * Attempts to open /dev/vboxdrv (or equvivalent).
449 *
450 * @remarks This function will not return on failure.
451 */
452static void supR3HardenedMainOpenDevice(void)
453{
454 int rc = suplibOsInit(&g_SupPreInitData.Data, false);
455 if (RT_SUCCESS(rc))
456 return;
457
458 switch (rc)
459 {
460 case VERR_VM_DRIVER_NOT_INSTALLED:
461 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_VM_DRIVER_NOT_INSTALLED\n");
462 case VERR_VM_DRIVER_NOT_ACCESSIBLE:
463 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_VM_DRIVER_NOT_ACCESSIBLE\n");
464 case VERR_VM_DRIVER_LOAD_ERROR:
465 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_VM_DRIVER_LOAD_ERROR\n");
466 case VERR_VM_DRIVER_OPEN_ERROR:
467 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_VM_DRIVER_OPEN_ERROR\n");
468 case VERR_VM_DRIVER_VERSION_MISMATCH:
469 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_VM_DRIVER_VERSION_MISMATCH\n");
470 case VERR_ACCESS_DENIED:
471 supR3HardenedFatal("supR3HardenedMainOpenDevice: VERR_ACCESS_DENIED\n");
472 default:
473 supR3HardenedFatal("supR3HardenedMainOpenDevice: rc=%d\n", rc);
474 }
475}
476
477
478/**
479 * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver,
480 * and calls RTR3Init.
481 *
482 * @param fFlags The SUPR3HardenedMain fFlags argument, passed to supR3PreInit.
483 *
484 * @remarks VBoxRT contains both IPRT and SUPR3.
485 * @remarks This function will not return on failure.
486 */
487static void supR3HardenedMainInitRuntime(uint32_t fFlags)
488{
489 /*
490 * Construct the name.
491 */
492 char szPath[RTPATH_MAX];
493 supR3HardenedPathSharedLibs(szPath, sizeof(szPath) - sizeof("/VBoxRT" SUPLIB_DLL_SUFF));
494 strcat(szPath, "/VBoxRT" SUPLIB_DLL_SUFF);
495
496 /*
497 * Open it and resolve the symbols.
498 */
499#if defined(RT_OS_WINDOWS)
500 /** @todo consider using LOAD_WITH_ALTERED_SEARCH_PATH here! */
501 HMODULE hMod = LoadLibraryEx(szPath, NULL /*hFile*/, 0 /* dwFlags */);
502 if (!hMod)
503 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibraryEx(\"%s\",,) failed, rc=%d\n",
504 szPath, GetLastError());
505 PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3InitEx"));
506 if (!pfnRTInitEx)
507 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3InitEx\" not found in \"%s\" (rc=%d)\n",
508 szPath, GetLastError());
509
510 PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)GetProcAddress(hMod, SUP_HARDENED_SYM("supR3PreInit"));
511 if (!pfnSUPPreInit)
512 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"supR3PreInit\" not found in \"%s\" (rc=%d)\n",
513 szPath, GetLastError());
514
515#else
516 /* the dlopen crowd */
517 void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
518 if (!pvMod)
519 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: dlopen(\"%s\",) failed: %s\n",
520 szPath, dlerror());
521 PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("RTR3InitEx"));
522 if (!pfnRTInitEx)
523 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3InitEx\" not found in \"%s\"!\ndlerror: %s\n",
524 szPath, dlerror());
525 PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("supR3PreInit"));
526 if (!pfnSUPPreInit)
527 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"supR3PreInit\" not found in \"%s\"!\ndlerror: %s\n",
528 szPath, dlerror());
529#endif
530
531 /*
532 * Make the calls.
533 */
534 supR3HardenedGetPreInitData(&g_SupPreInitData);
535 int rc = pfnSUPPreInit(&g_SupPreInitData, fFlags);
536 if (RT_FAILURE(rc))
537 supR3HardenedFatal("supR3PreInit: Failed with rc=%d\n", rc);
538 const char *pszExePath = NULL;
539#ifdef RT_OS_LINUX
540 if (!supR3HardenedMainIsProcSelfExeAccssible())
541 pszExePath = g_szSupLibHardenedExePath;
542#endif
543 rc = pfnRTInitEx(0, pszExePath, !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV));
544 if (RT_FAILURE(rc))
545 supR3HardenedFatal("RTR3Init: Failed with rc=%d\n", rc);
546}
547
548
549/**
550 * Loads the DLL/SO/DYLIB containing the actual program and
551 * resolves the TrustedMain symbol.
552 *
553 * @returns Pointer to the trusted main of the actual program.
554 * @param pszProgName The program name.
555 * @remarks This function will not return on failure.
556 */
557static PFNTRUSTEDMAIN supR3HardenedMainGetTrustedMain(const char *pszProgName)
558{
559 /*
560 * Construct the name.
561 */
562 char szPath[RTPATH_MAX];
563 supR3HardenedPathAppPrivateArch(szPath, sizeof(szPath) - 10);
564 size_t cch = strlen(szPath);
565 supR3HardenedStrPrintf(&szPath[cch], sizeof(szPath) - cch, "/%s%s", pszProgName, SUPLIB_DLL_SUFF);
566
567 /*
568 * Open it and resolve the symbol.
569 */
570#if defined(RT_OS_WINDOWS)
571 /** @todo consider using LOAD_WITH_ALTERED_SEARCH_PATH here! */
572 HMODULE hMod = LoadLibraryEx(szPath, NULL /*hFile*/, 0 /* dwFlags */);
573 if (!hMod)
574 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibraryEx(\"%s\",,) failed, rc=%d\n",
575 szPath, GetLastError());
576 FARPROC pfn = GetProcAddress(hMod, SUP_HARDENED_SYM("TrustedMain"));
577 if (!pfn)
578 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\" (rc=%d)\n",
579 szPath, GetLastError());
580 return (PFNTRUSTEDMAIN)pfn;
581
582#else
583 /* the dlopen crowd */
584 void *pvMod = dlopen(szPath, RTLD_NOW | RTLD_GLOBAL);
585 if (!pvMod)
586 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: dlopen(\"%s\",) failed: %s\n",
587 szPath, dlerror());
588 void *pvSym = dlsym(pvMod, SUP_HARDENED_SYM("TrustedMain"));
589 if (!pvSym)
590 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"TrustedMain\" not found in \"%s\"!\ndlerror: %s\n",
591 szPath, dlerror());
592 return (PFNTRUSTEDMAIN)(uintptr_t)pvSym;
593#endif
594}
595
596
597/**
598 * Secure main.
599 *
600 * This is used for the set-user-ID-on-execute binaries on unixy systems
601 * and when using the open-vboxdrv-via-root-service setup on Windows.
602 *
603 * This function will perform the integrity checks of the VirtualBox
604 * installation, open the support driver, open the root service (later),
605 * and load the DLL corresponding to \a pszProgName and execute its main
606 * function.
607 *
608 * @returns Return code appropriate for main().
609 *
610 * @param pszProgName The program name. This will be used to figure out which
611 * DLL/SO/DYLIB to load and execute.
612 * @param fFlags Flags.
613 * @param argc The argument count.
614 * @param argv The argument vector.
615 * @param envp The environment vector.
616 */
617DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp)
618{
619 /*
620 * Note! At this point there is no IPRT, so we will have to stick
621 * to basic CRT functions that everyone agree upon.
622 */
623 g_pszSupLibHardenedProgName = pszProgName;
624 g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC;
625 g_SupPreInitData.Data.hDevice = NIL_RTFILE;
626 g_SupPreInitData.u32EndMagic = SUPPREINITDATA_MAGIC;
627
628#ifdef SUP_HARDENED_SUID
629 /*
630 * Check that we're root, if we aren't then the installation is butchered.
631 */
632 uid_t const uid = getuid();
633 gid_t const gid = getgid();
634 if (geteuid() != 0 /* root */)
635 supR3HardenedFatal("SUPR3HardenedMain: effective uid is not root (euid=%d egid=%d uid=%d gid=%d)\n",
636 geteuid(), getegid(), uid, gid);
637
638# ifdef RT_OS_LINUX
639 /*
640 * On linux we have to make sure the path is initialized because we
641 * *might* not be able to access /proc/self/exe after the seteuid call.
642 */
643 supR3HardenedGetFullExePath();
644# endif
645#endif
646
647 /*
648 * Validate the installation.
649 */
650 supR3HardenedVerifyAll(true /* fFatal */, false /* fLeaveFilesOpen */, pszProgName);
651
652 /*
653 * Open the vboxdrv device.
654 */
655 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
656 supR3HardenedMainOpenDevice();
657
658 /*
659 * Open the root service connection.
660 */
661 //if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_SVC))
662 //supR3HardenedMainOpenService(&g_SupPreInitData, true /* fFatal */);
663
664#ifdef SUP_HARDENED_SUID
665 /*
666 * Drop any root privileges we might be holding.
667 */
668 setegid(gid);
669 seteuid(uid);
670 if ( geteuid() != uid
671 || getegid() != gid)
672 supR3HardenedFatal("SUPR3HardenedMain: failed to drop root privileges! (euid=%d egid=%d; wanted %d and %d)\n",
673 geteuid(), getegid(), uid, gid);
674#endif
675
676 /*
677 * Load the IPRT, hand the SUPLib part the open driver and
678 * call RTR3Init.
679 */
680 supR3HardenedMainInitRuntime(fFlags);
681
682 /*
683 * Load the DLL/SO/DYLIB containing the actual program
684 * and pass control to it.
685 */
686 PFNTRUSTEDMAIN pfnTrustedMain = supR3HardenedMainGetTrustedMain(pszProgName);
687 return pfnTrustedMain(argc, argv, envp);
688}
689
690
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette