| 1 | Index: src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp (revision 115126)
|
|---|
| 4 | +++ src/VBox/HostDrivers/Support/posix/SUPR3HardenedMain-posix.cpp (revision 115307)
|
|---|
| 5 | @@ -341,6 +341,7 @@
|
|---|
| 6 | * Patch 64-bit hosts.
|
|---|
| 7 | */
|
|---|
| 8 | uint32_t cRipRelMovs = 0;
|
|---|
| 9 | + uint32_t cRelCalls = 0;
|
|---|
| 10 |
|
|---|
| 11 | /* Just use the disassembler to skip 12 bytes or more, we might need to
|
|---|
| 12 | rewrite mov instructions using RIP relative addressing. */
|
|---|
| 13 | @@ -349,7 +350,8 @@
|
|---|
| 14 | cbInstr = 1;
|
|---|
| 15 | int rc = DISInstr(pbTarget + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr);
|
|---|
| 16 | if ( RT_FAILURE(rc)
|
|---|
| 17 | - || (Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW)
|
|---|
| 18 | + || ( Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW
|
|---|
| 19 | + && Dis.pCurInstr->uOpcode != OP_CALL)
|
|---|
| 20 | || ( Dis.ModRM.Bits.Mod == 0
|
|---|
| 21 | && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */
|
|---|
| 22 | && Dis.pCurInstr->uOpcode != OP_MOV))
|
|---|
| 23 | @@ -357,15 +359,23 @@
|
|---|
| 24 |
|
|---|
| 25 | if (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */)
|
|---|
| 26 | cRipRelMovs++;
|
|---|
| 27 | + if ( Dis.pCurInstr->uOpcode == OP_CALL
|
|---|
| 28 | + && (Dis.pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW))
|
|---|
| 29 | + cRelCalls++;
|
|---|
| 30 |
|
|---|
| 31 | offJmpBack += cbInstr;
|
|---|
| 32 | cbPatchMem += cbInstr;
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| 35 | + /*
|
|---|
| 36 | + * Each relative call requires extra bytes as it is converted to a pushq imm32
|
|---|
| 37 | + * + mov [RSP+4], imm32 + a jmp qword [$+8 wrt RIP] to avoid clobbering registers.
|
|---|
| 38 | + */
|
|---|
| 39 | + cbPatchMem += cRelCalls * RT_ALIGN_32(13 + 6 + 8, 8);
|
|---|
| 40 | cbPatchMem += 14; /* jmp qword [$+8 wrt RIP] + 8 byte address to jump to. */
|
|---|
| 41 | cbPatchMem = RT_ALIGN_32(cbPatchMem, 8);
|
|---|
| 42 |
|
|---|
| 43 | - /* Allocate suitable exectuable memory available. */
|
|---|
| 44 | + /* Allocate suitable executable memory available. */
|
|---|
| 45 | bool fConvRipRelMovs = false;
|
|---|
| 46 | uint8_t *pbPatchMem = supR3HardenedMainPosixExecMemAlloc(cbPatchMem, pbTarget, cRipRelMovs > 0);
|
|---|
| 47 | if (!pbPatchMem)
|
|---|
| 48 | @@ -396,7 +406,8 @@
|
|---|
| 49 | cbInstr = 1;
|
|---|
| 50 | int rc = DISInstr(pbTarget + offInsn, DISCPUMODE_64BIT, &Dis, &cbInstr);
|
|---|
| 51 | if ( RT_FAILURE(rc)
|
|---|
| 52 | - || (Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW))
|
|---|
| 53 | + || ( Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW
|
|---|
| 54 | + && Dis.pCurInstr->uOpcode != OP_CALL))
|
|---|
| 55 | return VERR_SUPLIB_UNEXPECTED_INSTRUCTION;
|
|---|
| 56 |
|
|---|
| 57 | if ( Dis.ModRM.Bits.Mod == 0
|
|---|
| 58 | @@ -439,6 +450,34 @@
|
|---|
| 59 | pbPatchMem += sizeof(int32_t);
|
|---|
| 60 | }
|
|---|
| 61 | }
|
|---|
| 62 | + else if ( Dis.pCurInstr->uOpcode == OP_CALL
|
|---|
| 63 | + && (Dis.pCurInstr->fOpType & DISOPTYPE_RELATIVE_CONTROLFLOW))
|
|---|
| 64 | + {
|
|---|
| 65 | + /* Convert to absolute jump. */
|
|---|
| 66 | + uintptr_t uAddr = (uintptr_t)&pbTarget[offInsn + cbInstr] + (intptr_t)Dis.Param1.uValue;
|
|---|
| 67 | +
|
|---|
| 68 | + /* Skip the push instructions till the return address is known. */
|
|---|
| 69 | + uint8_t *pbPatchMemPush = pbPatchMem;
|
|---|
| 70 | + pbPatchMem += 13;
|
|---|
| 71 | +
|
|---|
| 72 | + *pbPatchMem++ = 0xff; /* jmp qword [$+8 wrt RIP] */
|
|---|
| 73 | + *pbPatchMem++ = 0x25;
|
|---|
| 74 | + *(uint32_t *)pbPatchMem = (uint32_t)(RT_ALIGN_PT(pbPatchMem + 4, 8, uint8_t *) - (pbPatchMem + 4));
|
|---|
| 75 | + pbPatchMem = RT_ALIGN_PT(pbPatchMem + 4, 8, uint8_t *);
|
|---|
| 76 | + *(uint64_t *)pbPatchMem = uAddr;
|
|---|
| 77 | + pbPatchMem += sizeof(uint64_t);
|
|---|
| 78 | +
|
|---|
| 79 | + /* Push the return address onto stack. Difficult on amd64 without clobbering registers... */
|
|---|
| 80 | + uintptr_t uAddrReturn = (uintptr_t)pbPatchMem;
|
|---|
| 81 | + *pbPatchMemPush++ = 0x68; /* push imm32 sign-extended as 64-bit*/
|
|---|
| 82 | + *(uint32_t *)pbPatchMemPush = RT_LO_U32(uAddrReturn);
|
|---|
| 83 | + pbPatchMemPush += sizeof(uint32_t);
|
|---|
| 84 | + *pbPatchMemPush++ = 0xc7;
|
|---|
| 85 | + *pbPatchMemPush++ = 0x44;
|
|---|
| 86 | + *pbPatchMemPush++ = 0x24;
|
|---|
| 87 | + *pbPatchMemPush++ = 0x04; /* movl [RSP+4], imm32 */
|
|---|
| 88 | + *(uint32_t *)pbPatchMemPush = RT_HI_U32(uAddrReturn);
|
|---|
| 89 | + }
|
|---|
| 90 | else
|
|---|
| 91 | {
|
|---|
| 92 | memcpy(pbPatchMem, pbTarget + offInsn, cbInstr);
|
|---|
| 93 | Index: src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
|
|---|
| 94 | ===================================================================
|
|---|
| 95 | --- src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp (revision 115126)
|
|---|
| 96 | +++ src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp (revision 115307)
|
|---|
| 97 | @@ -86,6 +86,9 @@
|
|---|
| 98 | /** The max path length acceptable for a trusted path. */
|
|---|
| 99 | #define SUPR3HARDENED_MAX_PATH 260U
|
|---|
| 100 |
|
|---|
| 101 | +/** Enable to resolve symlinks using realpath() instead of cooking our own stuff. */
|
|---|
| 102 | +#define SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH 1
|
|---|
| 103 | +
|
|---|
| 104 | #ifdef RT_OS_SOLARIS
|
|---|
| 105 | # define dirfd(d) ((d)->d_fd)
|
|---|
| 106 | #endif
|
|---|
| 107 | @@ -1091,7 +1094,8 @@
|
|---|
| 108 | #endif
|
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 | -#if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX)
|
|---|
| 112 | +#ifndef SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH
|
|---|
| 113 | +# if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX)
|
|---|
| 114 | /**
|
|---|
| 115 | * Copies the error message to the error buffer and returns @a rc.
|
|---|
| 116 | *
|
|---|
| 117 | @@ -1104,6 +1108,7 @@
|
|---|
| 118 | {
|
|---|
| 119 | return supR3HardenedSetErrorN(rc, pErrInfo, 1, pszMsg);
|
|---|
| 120 | }
|
|---|
| 121 | +# endif
|
|---|
| 122 | #endif
|
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 | @@ -1893,7 +1898,9 @@
|
|---|
| 126 | /*
|
|---|
| 127 | * Verify each component from the root up.
|
|---|
| 128 | */
|
|---|
| 129 | +#ifndef SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH
|
|---|
| 130 | uint32_t iLoops = 0;
|
|---|
| 131 | +#endif
|
|---|
| 132 | SUPR3HARDENEDFSOBJSTATE FsObjState;
|
|---|
| 133 | uint32_t iComponent = 0;
|
|---|
| 134 | while (iComponent < Info.cComponents)
|
|---|
| 135 | @@ -1915,6 +1922,24 @@
|
|---|
| 136 | if ( RT_SUCCESS(rc)
|
|---|
| 137 | && S_ISLNK(FsObjState.Stat.st_mode))
|
|---|
| 138 | {
|
|---|
| 139 | +#if SUP_HARDENED_VERIFY_FOLLOW_SYMLINKS_USE_REALPATH /* Another approach using realpath() and verifying the result when encountering a symlink. */
|
|---|
| 140 | + char *pszFilenameResolved = realpath(pszFilename, NULL);
|
|---|
| 141 | + if (pszFilenameResolved)
|
|---|
| 142 | + {
|
|---|
| 143 | + rc = supR3HardenedVerifyFile(pszFilenameResolved, hNativeFile, fMaybe3rdParty, pErrInfo);
|
|---|
| 144 | + free(pszFilenameResolved);
|
|---|
| 145 | + return rc;
|
|---|
| 146 | + }
|
|---|
| 147 | + else
|
|---|
| 148 | + {
|
|---|
| 149 | + int iErr = errno;
|
|---|
| 150 | + supR3HardenedError(VERR_ACCESS_DENIED, false /*fFatal*/,
|
|---|
| 151 | + "supR3HardenedVerifyFileFollowSymlinks: Failed to resolve the real path '%s': %s (%d)\n",
|
|---|
| 152 | + pszFilename, strerror(iErr), iErr);
|
|---|
| 153 | + return supR3HardenedSetError4(VERR_ACCESS_DENIED, pErrInfo,
|
|---|
| 154 | + "realpath failed for '", pszFilename, "': ", strerror(iErr));
|
|---|
| 155 | + }
|
|---|
| 156 | +#else
|
|---|
| 157 | /* Don't loop forever. */
|
|---|
| 158 | iLoops++;
|
|---|
| 159 | if (iLoops < 8)
|
|---|
| 160 | @@ -1989,6 +2014,7 @@
|
|---|
| 161 | else
|
|---|
| 162 | return supR3HardenedSetError3(VERR_TOO_MANY_SYMLINKS, pErrInfo,
|
|---|
| 163 | "Too many symbolic links: '", pszFilename, "'");
|
|---|
| 164 | +#endif
|
|---|
| 165 | }
|
|---|
| 166 | }
|
|---|
| 167 | if (RT_FAILURE(rc))
|
|---|