Changeset 33701 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Nov 2, 2010 4:47:11 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 67327
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r33623 r33701 1428 1428 */ 1429 1429 #ifdef VBOX_WITH_HARDENING 1430 int rc = supR3HardenedVerifyFi le(pszFilename, false /* fFatal */);1430 int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */); 1431 1431 if (RT_FAILURE(rc)) 1432 1432 LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc)); … … 1451 1451 */ 1452 1452 #ifdef VBOX_WITH_HARDENING 1453 /** @todo implement me! */ 1454 return VINF_SUCCESS; 1453 int rc = supR3HardenedVerifyDir(pszDirPath, fRecursive, fCheckFiles, pszErr, cbErr); 1454 if (RT_FAILURE(rc) && (!pszErr || !cbErr)) 1455 LogRel(("supR3HardenedVerifyDir: Verification of \"%s\" failed, rc=%Rrc\n", pszDirPath, rc)); 1456 return rc; 1455 1457 #else 1456 1458 return VINF_SUCCESS; … … 1472 1474 */ 1473 1475 #ifdef VBOX_WITH_HARDENING 1474 /** @todo implement me! */ 1475 return VINF_SUCCESS; 1476 int rc = supR3HardenedVerifyFile(pszFilename, pszErr, cbErr); 1477 if (RT_FAILURE(rc) && (!pszErr || !cbErr)) 1478 LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc)); 1479 return rc; 1476 1480 #else 1477 1481 return VINF_SUCCESS; … … 1487 1491 * Check that the module can be trusted. 1488 1492 */ 1489 rc = supR3HardenedVerifyFi le(pszFilename, false /* fFatal */);1493 rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */); 1490 1494 #endif 1491 1495 if (RT_SUCCESS(rc)) … … 1507 1511 * Check that the module can be trusted. 1508 1512 */ 1509 rc = supR3HardenedVerifyFi le(pszFilename, false /* fFatal */);1513 rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */); 1510 1514 #endif 1511 1515 if (RT_SUCCESS(rc)) … … 2016 2020 * Verify the image file. 2017 2021 */ 2018 int rc = supR3HardenedVerifyFi le(pszFilename, false /* fFatal */);2022 int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */); 2019 2023 if (RT_FAILURE(rc)) 2020 2024 { -
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r28800 r33701 90 90 # define supR3HardenedError supR3HardenedStaticError 91 91 # define supR3HardenedVerifyAll supR3HardenedStaticVerifyAll 92 # define supR3HardenedVerifyFixedDir supR3HardenedStaticVerifyFixedDir 93 # define supR3HardenedVerifyFixedFile supR3HardenedStaticVerifyFixedFile 92 94 # define supR3HardenedVerifyDir supR3HardenedStaticVerifyDir 93 # define supR3HardenedVerify File supR3HardenedStaticVerifyFile95 # define supR3HardenedVerifyPlugIn supR3HardenedStaticVerifyPlugIn 94 96 # define supR3HardenedGetPreInitData supR3HardenedStaticGetPreInitData 95 97 # define supR3HardenedRecvPreInitData supR3HardenedStaticRecvPreInitData … … 316 318 DECLHIDDEN(int) supR3HardenedError(int rc, bool fFatal, const char *pszFormat, ...); 317 319 DECLHIDDEN(int) supR3HardenedVerifyAll(bool fFatal, bool fLeaveFilesOpen, const char *pszProgName); 318 DECLHIDDEN(int) supR3HardenedVerifyDir(SUPINSTDIR enmDir, bool fFatal); 319 DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, bool fFatal); 320 DECLHIDDEN(int) supR3HardenedVerifyFixedDir(SUPINSTDIR enmDir, bool fFatal); 321 DECLHIDDEN(int) supR3HardenedVerifyFixedFile(const char *pszFilename, bool fFatal); 322 DECLHIDDEN(int) supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, char *pszErr, size_t cbErr); 323 DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, char *pszErr, size_t cbErr); 320 324 DECLHIDDEN(void) supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData); 321 325 DECLHIDDEN(int) supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData); -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
r33590 r33701 47 47 # include <stdio.h> 48 48 # include <stdlib.h> 49 # include <dirent.h> 49 50 # include <dlfcn.h> 50 51 # include <fcntl.h> … … 68 69 #include <iprt/string.h> 69 70 #include <iprt/param.h> 71 #include <iprt/path.h> 70 72 71 73 #include "SUPLibInternal.h" … … 292 294 * fatal (true) or not (false). 293 295 */ 294 DECLHIDDEN(int) supR3HardenedVerify Dir(SUPINSTDIR enmDir, bool fFatal)296 DECLHIDDEN(int) supR3HardenedVerifyFixedDir(SUPINSTDIR enmDir, bool fFatal) 295 297 { 296 298 /* … … 439 441 * use openat if we wish.) 440 442 */ 441 int rc = supR3HardenedVerify Dir(pFile->enmDir, fFatal);443 int rc = supR3HardenedVerifyFixedDir(pFile->enmDir, fFatal); 442 444 if (RT_SUCCESS(rc)) 443 445 { … … 618 620 * fatal (true) or not (false). 619 621 */ 620 DECLHIDDEN(int) supR3HardenedVerifyFi le(const char *pszFilename, bool fFatal)622 DECLHIDDEN(int) supR3HardenedVerifyFixedFile(const char *pszFilename, bool fFatal) 621 623 { 622 624 /* … … 704 706 705 707 706 707 708 /** 708 709 * Verifies all the known files. … … 744 745 745 746 return rc; 747 } 748 749 750 /** Wrapper macro that adds the message length argument. */ 751 #define supR3HardenedSetError(rc, pszErr, cbErr, szMsg) \ 752 supR3HardenedSetErrorInt(rc, pszErr, cbErr, szMsg, sizeof(szMsg) - 1) 753 754 /** 755 * Copies the error message to the error buffer and returns @a rc. 756 * 757 * @returns Returns @a rc 758 * @param rc The return code. 759 * @param pszErr The error buffer. 760 * @param cbErr The size of the error buffer. 761 * @param pszMsg The message. 762 * @param cchMsg The length of the message text. 763 */ 764 static int supR3HardenedSetErrorInt(int rc, char *pszErr, size_t cbErr, const char *pszMsg, size_t cchMsg) 765 { 766 if (cbErr <= cchMsg) 767 cchMsg = cbErr - 1; 768 memcpy(pszErr, pszMsg, cchMsg); 769 pszErr[cchMsg] = '\0'; 770 771 return rc; 772 } 773 774 775 /** 776 * Verifies that the path is absolutely sane. 777 * 778 * A sane path starts at the root (w/ drive letter on DOS derived systems) and 779 * does not have any relative bits (/../) or unnecessary slashes (/bin//ls). 780 * Sane paths are less or equal to 260 bytes in length. UNC paths are not 781 * supported. 782 * 783 * @returns VBox status code. 784 * @param pszPath The path to check. 785 * @param pszErr The error buffer. 786 * @param cbErr The size of the error buffer. 787 * @param pcchPath Where to return the path length. 788 */ 789 static int supR3HardenedVerifyPathSanity(const char *pszPath, char *pszErr, size_t cbErr, size_t *pcchPath) 790 { 791 const char * const pszPathStart = pszPath; 792 793 /* 794 * Check that it's an absolute path. 795 */ 796 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 797 if ( !( (pszPath[0] >= 'A' && pszPath[0] <= 'Z') 798 || (pszPath[0] >= 'a' && pszPath[0] <= 'z')) 799 || pszPath[1] != ':' 800 || !RTPATH_IS_SLASH(pszPath[2])) 801 return supR3HardenedSetError(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pszErr, cbErr, "The path is not absolute"); 802 size_t const cchRootSpec = 3; 803 #else 804 if (!RTPATH_IS_SLASH(pszPath[0])) 805 return supR3HardenedSetError(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pszErr, cbErr, "The path is not absolute"); 806 size_t const cchRootSpec = 1; 807 #endif 808 pszPath += cchRootSpec; 809 810 /* 811 * Check each component. No parent references or double slashes. 812 */ 813 while (pszPath[0]) 814 { 815 if ( pszPath[0] == '.' 816 && pszPath[1] == '.' 817 && RTPATH_IS_SLASH(pszPath[2])) 818 return supR3HardenedSetError(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pszErr, cbErr, "The path is not absolute"); 819 if (RTPATH_IS_SLASH(pszPath[0])) 820 return supR3HardenedSetError(VERR_SUPLIB_PATH_NOT_CLEAN, pszErr, cbErr, "The path is not clean of double slashes"); 821 while (pszPath[0]) 822 { 823 if (RTPATH_IS_SLASH(pszPath[0])) 824 { 825 pszPath++; 826 break; 827 } 828 pszPath++; 829 } 830 } 831 832 /* 833 * Check the path length, root specifications are not permitted and we 834 * think paths longer than 260 bytes for are insane. 835 */ 836 size_t cchPath = pszPath - pszPathStart; 837 if (cchPath <= cchRootSpec) 838 return supR3HardenedSetError(VERR_SUPLIB_PATH_IS_ROOT, pszErr, cbErr, "The path is too root"); 839 if (cchPath > 260) 840 return supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pszErr, cbErr, "The path is too long"); 841 842 if (pcchPath) 843 *pcchPath = (size_t)(pszPath - pszPathStart); 844 return VINF_SUCCESS; 845 } 846 847 848 /** 849 * Verifies on file system object (file or directory). 850 * 851 * @returns VBox status code, error buffer filled on failure. 852 * @param pszPath The path to the object. 853 * @param fDir Whether this is a directory or a file. 854 * @param pszErr The error buffer. 855 * @param cbErr The size of the error buffer. 856 */ 857 static int supR3HardenedVerifyFsObject(char *pszPath, bool fDir, char *pszErr, size_t cbErr) 858 { 859 #if defined(RT_OS_WINDOWS) 860 /** @todo Windows hardening. */ 861 return VINF_SUCCESS; 862 863 #elif defined(RT_OS_OS2) 864 /* No hardening here - it's a single user system. */ 865 return VINF_SUCCESS; 866 867 #else 868 /* 869 * Stat the file and check that only root can modify it. 870 */ 871 struct stat st; 872 if (stat(pszPath, &st) != 0) 873 { 874 /* Ignore access errors */ 875 if (errno != EACCES) 876 return supR3HardenedSetError(VERR_SUPLIB_STAT_FAILED, pszErr, cbErr, pszPath); 877 } 878 879 /** @todo continue here tomorrow. */ 880 881 return VINF_SUCCESS; 882 #endif 883 } 884 885 886 /** 887 * Does the recursive directory enumeration. 888 * 889 * @returns VBox status code, error buffer filled on failure. 890 * @param pszDirPath The path buffer containing the subdirectory to 891 * enumerate followed by a slash (this is never 892 * the root slash). The buffer is RTPATH_MAX in 893 * size and anything starting at @a cchDirPath 894 * - 1 and beyond is scratch space. 895 * @param cchDirPath The length of the directory path + slash. 896 * @param fRecursive Whether to recurse into subdirectories. 897 * @param fCheckFiles Whether to check files. 898 * @param pszErr The error buffer. 899 * @param cbErr The size of the error buffer. 900 */ 901 static int supR3HardenedVerifyDirRecursive(char *pszDirPath, size_t cchDirPath, bool fRecursive, bool fCheckFiles, 902 char *pszErr, size_t cbErr) 903 { 904 #if defined(RT_OS_WINDOWS) 905 /** @todo Windows hardening. */ 906 return VINF_SUCCESS; 907 908 #elif defined(RT_OS_OS2) 909 /* No hardening here - it's a single user system. */ 910 return VINF_SUCCESS; 911 912 #else 913 DIR *pDir = opendir(pszDirPath); 914 if (!pDir) 915 { 916 /* Ignore access errors. */ 917 if (errno == EACCES) 918 return VINF_SUCCESS; 919 return supR3HardenedSetError(VERR_SUPLIB_DIR_ENUM_FAILED, pszErr, cbErr, pszDirPath); 920 } 921 922 int rc = VINF_SUCCESS; 923 for (;;) 924 { 925 struct dirent Entry; 926 struct dirent *pEntry; 927 int iErr = readdir_r(pDir, &Entry, &pEntry); 928 if (iErr) 929 { 930 rc = supR3HardenedSetError(VERR_SUPLIB_DIR_ENUM_FAILED, pszErr, cbErr, pszDirPath); 931 break; 932 } 933 if (!pEntry) 934 break; 935 936 /* 937 * Check the length and copy it into the path buffer so it can be 938 * stat()'ed. 939 */ 940 size_t cchName = strlen(pEntry->d_name); 941 if (cchName + cchDirPath > 260) 942 { 943 rc = supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pszErr, cbErr, pszDirPath); 944 break; 945 } 946 memcpy(&pszDirPath[cchName], pEntry->d_name, cchName + 1); 947 948 struct stat st; 949 if (stat(pszDirPath, &st) != 0) 950 { 951 /* Ignore access errors */ 952 if (errno == EACCES) 953 continue; 954 rc = supR3HardenedSetError(VERR_SUPLIB_STAT_ENUM_FAILED, pszErr, cbErr, pszDirPath); 955 break; 956 } 957 958 /* 959 * Only files and directories are allowed. 960 */ 961 if (!S_ISDIR(st.st_mode) && S_ISREG(st.st_mode)) 962 { 963 if (S_ISLNK(st.st_mode)) 964 rc = supR3HardenedSetError(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pszErr, cbErr, pszDirPath); 965 rc = supR3HardenedSetError(VERR_SUPLIB_NOT_DIR_NOT_FILE, pszErr, cbErr, pszDirPath); 966 break; 967 } 968 969 /* 970 * Verify it. 971 */ 972 if ( S_ISDIR(st.st_mode) 973 || fCheckFiles) 974 { 975 rc = supR3HardenedVerifyFsObject(pszDirPath, S_ISDIR(st.st_mode), pszErr, cbErr); 976 if (RT_FAILURE(rc)) 977 break; 978 } 979 980 /* 981 * Recurse. 982 */ 983 if ( fRecursive 984 && S_ISDIR(st.st_mode) 985 && strcmp(pEntry->d_name, ".") 986 && strcmp(pEntry->d_name, "..")) 987 { 988 pszDirPath[cchDirPath + cchName] = RTPATH_SLASH; 989 pszDirPath[cchDirPath + cchName + 1] = '\0'; 990 991 rc = supR3HardenedVerifyDirRecursive(pszDirPath, cchDirPath + cchName + 1, fRecursive, fCheckFiles, pszErr, cbErr); 992 if (RT_FAILURE(rc)) 993 break; 994 } 995 } 996 997 closedir(pDir); 998 return VINF_SUCCESS; 999 #endif 1000 } 1001 1002 1003 /** 1004 * Worker for SUPR3HardenedVerifyDir. 1005 * 1006 * @returns See SUPR3HardenedVerifyDir. 1007 * @param pszDirPath See SUPR3HardenedVerifyDir. 1008 * @param fRecursive See SUPR3HardenedVerifyDir. 1009 * @param fCheckFiles See SUPR3HardenedVerifyDir. 1010 * @param pszErr See SUPR3HardenedVerifyDir. 1011 * @param cbErr See SUPR3HardenedVerifyDir. 1012 */ 1013 DECLHIDDEN(int) supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, char *pszErr, size_t cbErr) 1014 { 1015 /* 1016 * Validate the input so we can be lazy when parsing it. 1017 */ 1018 size_t cchDirPath; 1019 int rc = supR3HardenedVerifyPathSanity(pszDirPath, pszErr, cbErr, &cchDirPath); 1020 if (RT_FAILURE(rc)) 1021 return rc; 1022 1023 /* 1024 * Make a copy of the input path and verify each component from the 1025 * root and up. This is the same as for supR3HardenedVerifyFile. 1026 */ 1027 char szPath[RTPATH_MAX]; 1028 memcpy(szPath, pszDirPath, cchDirPath + 1); 1029 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 1030 size_t off = 3; 1031 #else 1032 size_t off = 1; 1033 #endif 1034 while (off < cchDirPath) 1035 { 1036 size_t offSlash = off + 1; 1037 while (szPath[offSlash] && !RTPATH_IS_SLASH(szPath[offSlash])) 1038 offSlash++; 1039 1040 char chSaved = szPath[offSlash]; 1041 szPath[offSlash] = '\0'; 1042 1043 rc = supR3HardenedVerifyFsObject(szPath, true /*fDir*/, pszErr, cbErr); 1044 if (RT_FAILURE(rc)) 1045 return rc; 1046 1047 szPath[offSlash] = chSaved; 1048 off = offSlash + 1; 1049 } 1050 1051 /* 1052 * Do we need to check files or/and recurse into subdirectories? 1053 */ 1054 if (fCheckFiles || fRecursive) 1055 { 1056 if (!RTPATH_IS_SLASH(szPath[cchDirPath - 1])) 1057 { 1058 szPath[cchDirPath++] = RTPATH_SLASH; 1059 szPath[cchDirPath] = '\0'; 1060 } 1061 return supR3HardenedVerifyDirRecursive(szPath, cchDirPath, fRecursive, fCheckFiles, pszErr, cbErr); 1062 } 1063 1064 return VINF_SUCCESS; 1065 } 1066 1067 1068 /** 1069 * Verfies a file. 1070 * 1071 * @returns VBox status code, error buffer filled on failure. 1072 * @param pszFilename The file to verify. 1073 * @param pszErr The error buffer. 1074 * @param cbErr The size of the error buffer. 1075 */ 1076 DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, char *pszErr, size_t cbErr) 1077 { 1078 /* 1079 * Validate the input so we can be lazy when parsing it. 1080 */ 1081 size_t cchFilename; 1082 int rc = supR3HardenedVerifyPathSanity(pszFilename, pszErr, cbErr, &cchFilename); 1083 if (RT_FAILURE(rc)) 1084 return rc; 1085 1086 /* 1087 * Make a copy of the input filename and verify each component from the 1088 * root and up. 1089 */ 1090 char szPath[RTPATH_MAX]; 1091 memcpy(szPath, pszFilename, cchFilename + 1); 1092 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 1093 size_t off = 3; 1094 #else 1095 size_t off = 1; 1096 #endif 1097 while (off < cchFilename) 1098 { 1099 size_t offSlash = off + 1; 1100 while (szPath[offSlash] && !RTPATH_IS_SLASH(szPath[offSlash])) 1101 offSlash++; 1102 1103 char chSaved = szPath[offSlash]; 1104 szPath[offSlash] = '\0'; 1105 1106 rc = supR3HardenedVerifyFsObject(szPath, offSlash < cchFilename /*fDir*/, pszErr, cbErr); 1107 if (RT_FAILURE(rc)) 1108 return rc; 1109 1110 szPath[offSlash] = chSaved; 1111 off = offSlash + 1; 1112 } 1113 1114 return VINF_SUCCESS; 746 1115 } 747 1116
Note:
See TracChangeset
for help on using the changeset viewer.