< prev index next >

src/hotspot/share/memory/filemap.cpp

Print this page
rev 52787 : 8226406: JVM fails to detect mismatched or corrupt CDS archive
Summary: Check important archive header fields such as _jvm_ident before processing other fields.
Reviewed-by: iklam, jiangli


 119     current_info()->close();
 120   }
 121   va_end(ap);
 122 }
 123 
 124 // Fill in the fileMapInfo structure with data about this VM instance.
 125 
 126 // This method copies the vm version info into header_version.  If the version is too
 127 // long then a truncated version, which has a hash code appended to it, is copied.
 128 //
 129 // Using a template enables this method to verify that header_version is an array of
 130 // length JVM_IDENT_MAX.  This ensures that the code that writes to the CDS file and
 131 // the code that reads the CDS file will both use the same size buffer.  Hence, will
 132 // use identical truncation.  This is necessary for matching of truncated versions.
 133 template <int N> static void get_header_version(char (&header_version) [N]) {
 134   assert(N == JVM_IDENT_MAX, "Bad header_version size");
 135 
 136   const char *vm_version = VM_Version::internal_vm_info_string();
 137   const int version_len = (int)strlen(vm_version);
 138 


 139   if (version_len < (JVM_IDENT_MAX-1)) {
 140     strcpy(header_version, vm_version);
 141 
 142   } else {
 143     // Get the hash value.  Use a static seed because the hash needs to return the same
 144     // value over multiple jvm invocations.
 145     unsigned int hash = AltHashing::murmur3_32(8191, (const jbyte*)vm_version, version_len);
 146 
 147     // Truncate the ident, saving room for the 8 hex character hash value.
 148     strncpy(header_version, vm_version, JVM_IDENT_MAX-9);
 149 
 150     // Append the hash code as eight hex digits.
 151     sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
 152     header_version[JVM_IDENT_MAX-1] = 0;  // Null terminate.
 153   }


 154 }
 155 
 156 FileMapInfo::FileMapInfo() {
 157   assert(_current_info == NULL, "must be singleton"); // not thread safe
 158   _current_info = this;
 159   memset((void*)this, 0, sizeof(FileMapInfo));
 160   _file_offset = 0;
 161   _file_open = false;
 162   _header = (FileMapHeader*)os::malloc(sizeof(FileMapHeader), mtInternal);
 163   _header->_version = INVALID_CDS_ARCHIVE_VERSION;
 164   _header->_has_platform_or_app_classes = true;
 165 }
 166 
 167 FileMapInfo::~FileMapInfo() {
 168   assert(_current_info == this, "must be singleton"); // not thread safe
 169   _current_info = NULL;
 170 }
 171 
 172 void FileMapInfo::populate_header(size_t alignment) {
 173   _header->populate(this, alignment);


 482       _validating_shared_path_table = false;
 483       _shared_path_table = NULL;
 484       _shared_path_table_size = 0;
 485       return false;
 486     }
 487   }
 488 
 489   _validating_shared_path_table = false;
 490   return true;
 491 }
 492 
 493 // Read the FileMapInfo information from the file.
 494 
 495 bool FileMapInfo::init_from_file(int fd) {
 496   size_t sz = sizeof(FileMapHeader);
 497   size_t n = os::read(fd, _header, (unsigned int)sz);
 498   if (n != sz) {
 499     fail_continue("Unable to read the file header.");
 500     return false;
 501   }














 502   if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {


 503     fail_continue("The shared archive file has the wrong version.");
 504     return false;
 505   }

































 506   _file_offset = (long)n;
 507 
 508   size_t info_size = _header->_paths_misc_info_size;
 509   _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass);
 510   if (_paths_misc_info == NULL) {
 511     fail_continue("Unable to read the file header.");
 512     return false;
 513   }
 514   n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
 515   if (n != info_size) {
 516     fail_continue("Unable to read the shared path info header.");
 517     FREE_C_HEAP_ARRAY(char, _paths_misc_info);
 518     _paths_misc_info = NULL;
 519     return false;
 520   }
 521 
 522   size_t len = lseek(fd, 0, SEEK_END);
 523   CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
 524   // The last space might be empty
 525   if (si->_file_offset > len || len - si->_file_offset < si->_used) {
 526     fail_continue("The shared archive file has been truncated.");
 527     return false;
 528   }
 529 
 530   _file_offset += (long)n;

 531   return true;
 532 }
 533 
 534 
 535 // Read the FileMapInfo information from the file.
 536 bool FileMapInfo::open_for_read() {
 537   _full_path = Arguments::GetSharedArchivePath();
 538   int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
 539   if (fd < 0) {
 540     if (errno == ENOENT) {
 541       // Not locating the shared archive is ok.
 542       fail_continue("Specified shared archive not found.");
 543     } else {
 544       fail_continue("Failed to open shared archive file (%s).",
 545                     os::strerror(errno));
 546     }
 547     return false;
 548   }
 549 
 550   _fd = fd;


1111 char* FileMapHeader::region_addr(int idx) {
1112   if (MetaspaceShared::is_heap_region(idx)) {
1113     return _space[idx]._used > 0 ?
1114              (char*)((void*)CompressedOops::decode_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
1115   } else {
1116     return _space[idx]._addr._base;
1117   }
1118 }
1119 
1120 int FileMapHeader::compute_crc() {
1121   char* start = (char*)this;
1122   // start computing from the field after _crc
1123   char* buf = (char*)&_crc + sizeof(_crc);
1124   size_t sz = sizeof(FileMapHeader) - (buf - start);
1125   int crc = ClassLoader::crc32(0, buf, (jint)sz);
1126   return crc;
1127 }
1128 
1129 // This function should only be called during run time with UseSharedSpaces enabled.
1130 bool FileMapHeader::validate() {
1131   if (VerifySharedSpaces && compute_crc() != _crc) {
1132     FileMapInfo::fail_continue("Header checksum verification failed.");
1133     return false;
1134   }
1135 
1136   if (!Arguments::has_jimage()) {
1137     FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build.");
1138     return false;
1139   }
1140 
1141   if (_version != CURRENT_CDS_ARCHIVE_VERSION) {
1142     FileMapInfo::fail_continue("The shared archive file is the wrong version.");
1143     return false;
1144   }
1145   if (_magic != CDS_ARCHIVE_MAGIC) {
1146     FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
1147     return false;
1148   }
1149   char header_version[JVM_IDENT_MAX];
1150   get_header_version(header_version);
1151   if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
1152     log_info(class, path)("expected: %s", header_version);
1153     log_info(class, path)("actual:   %s", _jvm_ident);
1154     FileMapInfo::fail_continue("The shared archive file was created by a different"
1155                   " version or build of HotSpot");
1156     return false;
1157   }
1158   if (_obj_alignment != ObjectAlignmentInBytes) {
1159     FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
1160                   " does not equal the current ObjectAlignmentInBytes of " INTX_FORMAT ".",
1161                   _obj_alignment, ObjectAlignmentInBytes);
1162     return false;
1163   }
1164   if (_compact_strings != CompactStrings) {
1165     FileMapInfo::fail_continue("The shared archive file's CompactStrings setting (%s)"
1166                   " does not equal the current CompactStrings setting (%s).",
1167                   _compact_strings ? "enabled" : "disabled",
1168                   CompactStrings   ? "enabled" : "disabled");
1169     return false;
1170   }
1171 
1172   // This must be done after header validation because it might change the
1173   // header data
1174   const char* prop = Arguments::get_property("java.system.class.loader");
1175   if (prop != NULL) {
1176     warning("Archived non-system classes are disabled because the "
1177             "java.system.class.loader property is specified (value = \"%s\"). "




 119     current_info()->close();
 120   }
 121   va_end(ap);
 122 }
 123 
 124 // Fill in the fileMapInfo structure with data about this VM instance.
 125 
 126 // This method copies the vm version info into header_version.  If the version is too
 127 // long then a truncated version, which has a hash code appended to it, is copied.
 128 //
 129 // Using a template enables this method to verify that header_version is an array of
 130 // length JVM_IDENT_MAX.  This ensures that the code that writes to the CDS file and
 131 // the code that reads the CDS file will both use the same size buffer.  Hence, will
 132 // use identical truncation.  This is necessary for matching of truncated versions.
 133 template <int N> static void get_header_version(char (&header_version) [N]) {
 134   assert(N == JVM_IDENT_MAX, "Bad header_version size");
 135 
 136   const char *vm_version = VM_Version::internal_vm_info_string();
 137   const int version_len = (int)strlen(vm_version);
 138 
 139   memset(header_version, 0, JVM_IDENT_MAX);
 140 
 141   if (version_len < (JVM_IDENT_MAX-1)) {
 142     strcpy(header_version, vm_version);
 143 
 144   } else {
 145     // Get the hash value.  Use a static seed because the hash needs to return the same
 146     // value over multiple jvm invocations.
 147     unsigned int hash = AltHashing::murmur3_32(8191, (const jbyte*)vm_version, version_len);
 148 
 149     // Truncate the ident, saving room for the 8 hex character hash value.
 150     strncpy(header_version, vm_version, JVM_IDENT_MAX-9);
 151 
 152     // Append the hash code as eight hex digits.
 153     sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash);
 154     header_version[JVM_IDENT_MAX-1] = 0;  // Null terminate.
 155   }
 156 
 157   assert(header_version[JVM_IDENT_MAX-1] == 0, "must be");
 158 }
 159 
 160 FileMapInfo::FileMapInfo() {
 161   assert(_current_info == NULL, "must be singleton"); // not thread safe
 162   _current_info = this;
 163   memset((void*)this, 0, sizeof(FileMapInfo));
 164   _file_offset = 0;
 165   _file_open = false;
 166   _header = (FileMapHeader*)os::malloc(sizeof(FileMapHeader), mtInternal);
 167   _header->_version = INVALID_CDS_ARCHIVE_VERSION;
 168   _header->_has_platform_or_app_classes = true;
 169 }
 170 
 171 FileMapInfo::~FileMapInfo() {
 172   assert(_current_info == this, "must be singleton"); // not thread safe
 173   _current_info = NULL;
 174 }
 175 
 176 void FileMapInfo::populate_header(size_t alignment) {
 177   _header->populate(this, alignment);


 486       _validating_shared_path_table = false;
 487       _shared_path_table = NULL;
 488       _shared_path_table_size = 0;
 489       return false;
 490     }
 491   }
 492 
 493   _validating_shared_path_table = false;
 494   return true;
 495 }
 496 
 497 // Read the FileMapInfo information from the file.
 498 
 499 bool FileMapInfo::init_from_file(int fd) {
 500   size_t sz = sizeof(FileMapHeader);
 501   size_t n = os::read(fd, _header, (unsigned int)sz);
 502   if (n != sz) {
 503     fail_continue("Unable to read the file header.");
 504     return false;
 505   }
 506 
 507   if (!Arguments::has_jimage()) {
 508     FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build.");
 509     return false;
 510   }
 511 
 512   unsigned int expected_magic = CDS_ARCHIVE_MAGIC; // is_static ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC;
 513   if (_header->_magic != expected_magic) {
 514     log_info(cds)("_magic expected: 0x%08x", expected_magic);
 515     log_info(cds)("         actual: 0x%08x", _header->_magic);
 516     FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
 517     return false;
 518   }
 519 
 520   if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {
 521     log_info(cds)("_version expected: %d", CURRENT_CDS_ARCHIVE_VERSION);
 522     log_info(cds)("           actual: %d", _header->_version);
 523     fail_continue("The shared archive file has the wrong version.");
 524     return false;
 525   }
 526 
 527   //if (_header->_header_size != sz) {
 528   //  log_info(cds)("_header_size expected: " SIZE_FORMAT, sz);
 529   //  log_info(cds)("               actual: " SIZE_FORMAT, _header->_header_size);
 530   //  FileMapInfo::fail_continue("The shared archive file has an incorrect header size.");
 531   //  return false;
 532   // }
 533 
 534   if (_header->_jvm_ident[JVM_IDENT_MAX-1] != 0) {
 535     FileMapInfo::fail_continue("JVM version identifier is corrupted.");
 536     return false;
 537   }
 538 
 539   char header_version[JVM_IDENT_MAX];
 540   get_header_version(header_version);
 541   if (strncmp(_header->_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
 542     log_info(cds)("_jvm_ident expected: %s", header_version);
 543     log_info(cds)("             actual: %s", _header->_jvm_ident);
 544     FileMapInfo::fail_continue("The shared archive file was created by a different"
 545                   " version or build of HotSpot");
 546     return false;
 547   }
 548 
 549   if (VerifySharedSpaces) {
 550     int expected_crc = _header->compute_crc();
 551     if (expected_crc != _header->_crc) {
 552       log_info(cds)("_crc expected: %d", expected_crc);
 553       log_info(cds)("       actual: %d", _header->_crc);
 554       FileMapInfo::fail_continue("Header checksum verification failed.");
 555       return false;
 556     }
 557   }
 558 
 559   _file_offset = (long)n;
 560 
 561   size_t info_size = _header->_paths_misc_info_size;
 562   _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass);
 563   if (_paths_misc_info == NULL) {
 564     fail_continue("Unable to read the file header.");
 565     return false;
 566   }
 567   n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
 568   if (n != info_size) {
 569     fail_continue("Unable to read the shared path info header.");
 570     FREE_C_HEAP_ARRAY(char, _paths_misc_info);
 571     _paths_misc_info = NULL;
 572     return false;
 573   }
 574 
 575   size_t len = lseek(fd, 0, SEEK_END);
 576   CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
 577   // The last space might be empty
 578   if (si->_file_offset > len || len - si->_file_offset < si->_used) {
 579     fail_continue("The shared archive file has been truncated.");
 580     return false;
 581   }
 582 
 583   _file_offset += (long)n;
 584 
 585   return true;
 586 }
 587 
 588 
 589 // Read the FileMapInfo information from the file.
 590 bool FileMapInfo::open_for_read() {
 591   _full_path = Arguments::GetSharedArchivePath();
 592   int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
 593   if (fd < 0) {
 594     if (errno == ENOENT) {
 595       // Not locating the shared archive is ok.
 596       fail_continue("Specified shared archive not found.");
 597     } else {
 598       fail_continue("Failed to open shared archive file (%s).",
 599                     os::strerror(errno));
 600     }
 601     return false;
 602   }
 603 
 604   _fd = fd;


1165 char* FileMapHeader::region_addr(int idx) {
1166   if (MetaspaceShared::is_heap_region(idx)) {
1167     return _space[idx]._used > 0 ?
1168              (char*)((void*)CompressedOops::decode_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
1169   } else {
1170     return _space[idx]._addr._base;
1171   }
1172 }
1173 
1174 int FileMapHeader::compute_crc() {
1175   char* start = (char*)this;
1176   // start computing from the field after _crc
1177   char* buf = (char*)&_crc + sizeof(_crc);
1178   size_t sz = sizeof(FileMapHeader) - (buf - start);
1179   int crc = ClassLoader::crc32(0, buf, (jint)sz);
1180   return crc;
1181 }
1182 
1183 // This function should only be called during run time with UseSharedSpaces enabled.
1184 bool FileMapHeader::validate() {



























1185   if (_obj_alignment != ObjectAlignmentInBytes) {
1186     FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
1187                   " does not equal the current ObjectAlignmentInBytes of " INTX_FORMAT ".",
1188                   _obj_alignment, ObjectAlignmentInBytes);
1189     return false;
1190   }
1191   if (_compact_strings != CompactStrings) {
1192     FileMapInfo::fail_continue("The shared archive file's CompactStrings setting (%s)"
1193                   " does not equal the current CompactStrings setting (%s).",
1194                   _compact_strings ? "enabled" : "disabled",
1195                   CompactStrings   ? "enabled" : "disabled");
1196     return false;
1197   }
1198 
1199   // This must be done after header validation because it might change the
1200   // header data
1201   const char* prop = Arguments::get_property("java.system.class.loader");
1202   if (prop != NULL) {
1203     warning("Archived non-system classes are disabled because the "
1204             "java.system.class.loader property is specified (value = \"%s\"). "


< prev index next >