VirtualBox

Changeset 63635 in vbox


Ignore:
Timestamp:
Aug 25, 2016 1:44:59 PM (8 years ago)
Author:
vboxsync
Message:

Storage/QCOW,Parallels: Fix a few possible crashes possible when opening corrupted image files

Location:
trunk/src/VBox/Storage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/Parallels.cpp

    r63567 r63635  
    198198    if (RT_FAILURE(rc))
    199199        goto out;
    200     AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
     200    if (pImage->cbFileCurrent % 512 != 0)
     201    {
     202        rc = VERR_VD_PARALLELS_INVALID_HEADER;
     203        goto out;
     204    }
    201205
    202206    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0,
  • trunk/src/VBox/Storage/QCOW.cpp

    r63567 r63635  
    10291029
    10301030/**
     1031 * Validates the header.
     1032 *
     1033 * @returns VBox status code.
     1034 * @param   pImage    Image backend instance data.
     1035 * @param   pHdr      The header to validate.
     1036 * @param   cbFile    The image file size in bytes.
     1037 */
     1038static int qcowHdrValidate(PQCOWIMAGE pImage, PQCowHeader pHdr, uint64_t cbFile)
     1039{
     1040    if (pHdr->u32Version == 1)
     1041    {
     1042        /* Check that the backing filename is contained in the file. */
     1043        if (pHdr->Version.v1.u64BackingFileOffset + pHdr->Version.v1.u32BackingFileSize > cbFile)
     1044            return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1045                             N_("QCOW: Backing file offset and size exceed size of image '%s' (%u vs %u)"),
     1046                             pImage->pszFilename, pHdr->Version.v1.u64BackingFileOffset + pHdr->Version.v1.u32BackingFileSize,
     1047                             cbFile);
     1048
     1049        /* Check that the cluster bits indicate at least a 512byte sector size. */
     1050        if (RT_BIT_32(pHdr->Version.v1.u8ClusterBits) < 512)
     1051            return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1052                             N_("QCOW: Cluster size is too small for image  '%s' (%u vs %u)"),
     1053                             pImage->pszFilename, RT_BIT_32(pHdr->Version.v1.u8ClusterBits), 512);
     1054
     1055        /*
     1056         * Check for possible overflow when multiplying cluster size and L2 entry count because it is used
     1057         * to calculate the number of L1 table entries later on.
     1058         */
     1059        if (RT_BIT_32(pHdr->Version.v1.u8L2Bits) * RT_BIT_32(pHdr->Version.v1.u8ClusterBits) == 0)
     1060            return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1061                             N_("QCOW: Overflow during L1 table size calculation for image '%s'"),
     1062                             pImage->pszFilename);
     1063    }
     1064    else if (pHdr->u32Version == 2)
     1065    {
     1066        /* Check that the backing filename is contained in the file. */
     1067        if (pHdr->Version.v2.u64BackingFileOffset + pHdr->Version.v2.u32BackingFileSize > cbFile)
     1068            return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1069                             N_("QCOW: Backing file offset and size exceed size of image '%s' (%u vs %u)"),
     1070                             pImage->pszFilename, pHdr->Version.v2.u64BackingFileOffset + pHdr->Version.v2.u32BackingFileSize,
     1071                             cbFile);
     1072
     1073        /* Check that the cluster bits indicate at least a 512byte sector size. */
     1074        if (RT_BIT_32(pHdr->Version.v2.u32ClusterBits) < 512)
     1075            return vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1076                             N_("QCOW: Cluster size is too small for image  '%s' (%u vs %u)"),
     1077                             pImage->pszFilename, RT_BIT_32(pHdr->Version.v2.u32ClusterBits), 512);
     1078    }
     1079    else
     1080        return vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
     1081                         N_("QCOW: Version %u in image '%s' is not supported"),
     1082                         pHdr->u32Version, pImage->pszFilename);
     1083
     1084    return VINF_SUCCESS;
     1085}
     1086
     1087/**
    10311088 * Internal: Open an image, constructing all necessary data structures.
    10321089 */
     
    10721129            Assert(pImage->offNextCluster >= cbFile);
    10731130
    1074             if (Header.u32Version == 1)
     1131            rc = qcowHdrValidate(pImage, &Header, cbFile);
     1132            if (RT_SUCCESS(rc))
    10751133            {
    1076                 if (!Header.Version.v1.u32CryptMethod)
     1134                if (Header.u32Version == 1)
    10771135                {
    1078                     pImage->uVersion           = 1;
    1079                     pImage->offBackingFilename = Header.Version.v1.u64BackingFileOffset;
    1080                     pImage->cbBackingFilename  = Header.Version.v1.u32BackingFileSize;
    1081                     pImage->MTime              = Header.Version.v1.u32MTime;
    1082                     pImage->cbSize             = Header.Version.v1.u64Size;
    1083                     pImage->cbCluster          = RT_BIT_32(Header.Version.v1.u8ClusterBits);
    1084                     pImage->cL2TableEntries    = RT_BIT_32(Header.Version.v1.u8L2Bits);
    1085                     pImage->cbL2Table          = RT_ALIGN_64(pImage->cL2TableEntries * sizeof(uint64_t), pImage->cbCluster);
    1086                     pImage->offL1Table         = Header.Version.v1.u64L1TableOffset;
    1087                     pImage->cL1TableEntries    = pImage->cbSize / (pImage->cbCluster * pImage->cL2TableEntries);
    1088                     if (pImage->cbSize % (pImage->cbCluster * pImage->cL2TableEntries))
    1089                         pImage->cL1TableEntries++;
    1090                     pImage->cbL1Table          = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
     1136                    if (!Header.Version.v1.u32CryptMethod)
     1137                    {
     1138                        pImage->uVersion           = 1;
     1139                        pImage->offBackingFilename = Header.Version.v1.u64BackingFileOffset;
     1140                        pImage->cbBackingFilename  = Header.Version.v1.u32BackingFileSize;
     1141                        pImage->MTime              = Header.Version.v1.u32MTime;
     1142                        pImage->cbSize             = Header.Version.v1.u64Size;
     1143                        pImage->cbCluster          = RT_BIT_32(Header.Version.v1.u8ClusterBits);
     1144                        pImage->cL2TableEntries    = RT_BIT_32(Header.Version.v1.u8L2Bits);
     1145                        pImage->cbL2Table          = RT_ALIGN_64(pImage->cL2TableEntries * sizeof(uint64_t), pImage->cbCluster);
     1146                        pImage->offL1Table         = Header.Version.v1.u64L1TableOffset;
     1147                        pImage->cL1TableEntries    = pImage->cbSize / (pImage->cbCluster * pImage->cL2TableEntries);
     1148                        if (pImage->cbSize % (pImage->cbCluster * pImage->cL2TableEntries))
     1149                            pImage->cL1TableEntries++;
     1150                    }
     1151                    else
     1152                        rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
     1153                                       N_("QCow: Encrypted image '%s' is not supported"),
     1154                                       pImage->pszFilename);
     1155                }
     1156                else if (Header.u32Version == 2)
     1157                {
     1158                    if (Header.Version.v2.u32CryptMethod)
     1159                        rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
     1160                                       N_("QCow: Encrypted image '%s' is not supported"),
     1161                                       pImage->pszFilename);
     1162                    else if (Header.Version.v2.u32NbSnapshots)
     1163                        rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
     1164                                       N_("QCow: Image '%s' contains snapshots which is not supported"),
     1165                                       pImage->pszFilename);
     1166                    else
     1167                    {
     1168                        pImage->uVersion              = 2;
     1169                        pImage->offBackingFilename    = Header.Version.v2.u64BackingFileOffset;
     1170                        pImage->cbBackingFilename     = Header.Version.v2.u32BackingFileSize;
     1171                        pImage->cbSize                = Header.Version.v2.u64Size;
     1172                        pImage->cbCluster             = RT_BIT_32(Header.Version.v2.u32ClusterBits);
     1173                        pImage->cL2TableEntries       = pImage->cbCluster / sizeof(uint64_t);
     1174                        pImage->cbL2Table             = pImage->cbCluster;
     1175                        pImage->offL1Table            = Header.Version.v2.u64L1TableOffset;
     1176                        pImage->cL1TableEntries       = Header.Version.v2.u32L1Size;
     1177                        pImage->offRefcountTable      = Header.Version.v2.u64RefcountTableOffset;
     1178                        pImage->cbRefcountTable       = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters);
     1179                        pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t);
     1180                    }
    10911181                }
    10921182                else
    10931183                    rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
    1094                                    N_("QCow: Encrypted image '%s' is not supported"),
     1184                                   N_("QCow: Image '%s' uses version %u which is not supported"),
     1185                                   pImage->pszFilename, Header.u32Version);
     1186
     1187                pImage->cbL1Table = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
     1188                if ((uint64_t)pImage->cbL1Table != RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster))
     1189                    rc = vdIfError(pImage->pIfError, VERR_INVALID_STATE, RT_SRC_POS,
     1190                                   N_("QCOW: L1 table size overflow in image '%s'"),
    10951191                                   pImage->pszFilename);
    10961192            }
    1097             else if (Header.u32Version == 2)
    1098             {
    1099                 if (Header.Version.v2.u32CryptMethod)
    1100                     rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
    1101                                    N_("QCow: Encrypted image '%s' is not supported"),
    1102                                    pImage->pszFilename);
    1103                 else if (Header.Version.v2.u32NbSnapshots)
    1104                     rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
    1105                                    N_("QCow: Image '%s' contains snapshots which is not supported"),
    1106                                    pImage->pszFilename);
    1107                 else
    1108                 {
    1109                     pImage->uVersion              = 2;
    1110                     pImage->offBackingFilename    = Header.Version.v2.u64BackingFileOffset;
    1111                     pImage->cbBackingFilename     = Header.Version.v2.u32BackingFileSize;
    1112                     pImage->cbSize                = Header.Version.v2.u64Size;
    1113                     pImage->cbCluster             = RT_BIT_32(Header.Version.v2.u32ClusterBits);
    1114                     pImage->cL2TableEntries       = pImage->cbCluster / sizeof(uint64_t);
    1115                     pImage->cbL2Table             = pImage->cbCluster;
    1116                     pImage->offL1Table            = Header.Version.v2.u64L1TableOffset;
    1117                     pImage->cL1TableEntries       = Header.Version.v2.u32L1Size;
    1118                     pImage->cbL1Table             = RT_ALIGN_64(pImage->cL1TableEntries * sizeof(uint64_t), pImage->cbCluster);
    1119                     pImage->offRefcountTable      = Header.Version.v2.u64RefcountTableOffset;
    1120                     pImage->cbRefcountTable       = qcowCluster2Byte(pImage, Header.Version.v2.u32RefcountTableClusters);
    1121                     pImage->cRefcountTableEntries = pImage->cbRefcountTable / sizeof(uint64_t);
    1122                 }
    1123             }
    1124             else
    1125                 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS,
    1126                                N_("QCow: Image '%s' uses version %u which is not supported"),
    1127                                pImage->pszFilename, Header.u32Version);
    11281193
    11291194            /** @todo Check that there are no compressed clusters in the image
Note: See TracChangeset for help on using the changeset viewer.

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