8044269: Analysis of archive files.

Tue, 12 Aug 2014 17:46:16 -0400

author
jiangli
date
Tue, 12 Aug 2014 17:46:16 -0400
changeset 7444
8210e5f2e21b
parent 7443
609faa407cfd
child 7445
42c091d63c72
child 7446
cafabb1a240d

8044269: Analysis of archive files.
Summary: Add checksum verification.
Reviewed-by: iklam, dholmes, mschoene

src/share/vm/classfile/classLoader.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/classLoader.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/filemap.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/filemap.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/metaspaceShared.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/classLoader.cpp	Fri Aug 08 15:15:52 2014 -0700
     1.2 +++ b/src/share/vm/classfile/classLoader.cpp	Tue Aug 12 17:46:16 2014 -0400
     1.3 @@ -84,6 +84,7 @@
     1.4  typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
     1.5  typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
     1.6  typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
     1.7 +typedef jint     (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
     1.8  
     1.9  static ZipOpen_t         ZipOpen            = NULL;
    1.10  static ZipClose_t        ZipClose           = NULL;
    1.11 @@ -92,6 +93,7 @@
    1.12  static ReadMappedEntry_t ReadMappedEntry    = NULL;
    1.13  static GetNextEntry_t    GetNextEntry       = NULL;
    1.14  static canonicalize_fn_t CanonicalizeEntry  = NULL;
    1.15 +static Crc32_t           Crc32              = NULL;
    1.16  
    1.17  // Globals
    1.18  
    1.19 @@ -632,9 +634,11 @@
    1.20    ReadEntry    = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry"));
    1.21    ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry"));
    1.22    GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
    1.23 +  Crc32        = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
    1.24  
    1.25    // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
    1.26 -  if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) {
    1.27 +  if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
    1.28 +      GetNextEntry == NULL || Crc32 == NULL) {
    1.29      vm_exit_during_initialization("Corrupted ZIP library", path);
    1.30    }
    1.31  
    1.32 @@ -644,6 +648,11 @@
    1.33    // This lookup only works on 1.3. Do not check for non-null here
    1.34  }
    1.35  
    1.36 +int ClassLoader::crc32(int crc, const char* buf, int len) {
    1.37 +  assert(Crc32 != NULL, "ZIP_CRC32 is not found");
    1.38 +  return (*Crc32)(crc, (const jbyte*)buf, len);
    1.39 +}
    1.40 +
    1.41  // PackageInfo data exists in order to support the java.lang.Package
    1.42  // class.  A Package object provides information about a java package
    1.43  // (version, vendor, etc.) which originates in the manifest of the jar
     2.1 --- a/src/share/vm/classfile/classLoader.hpp	Fri Aug 08 15:15:52 2014 -0700
     2.2 +++ b/src/share/vm/classfile/classLoader.hpp	Tue Aug 12 17:46:16 2014 -0400
     2.3 @@ -215,6 +215,7 @@
     2.4    // to avoid confusing the zip library
     2.5    static bool get_canonical_path(char* orig, char* out, int len);
     2.6   public:
     2.7 +  static int crc32(int crc, const char* buf, int len);
     2.8    // Used by the kernel jvm.
     2.9    static void update_class_path_entry_list(char *path,
    2.10                                             bool check_for_duplicates);
     3.1 --- a/src/share/vm/memory/filemap.cpp	Fri Aug 08 15:15:52 2014 -0700
     3.2 +++ b/src/share/vm/memory/filemap.cpp	Tue Aug 12 17:46:16 2014 -0400
     3.3 @@ -177,7 +177,14 @@
     3.4      fail_continue("The shared archive file has the wrong version.");
     3.5      return false;
     3.6    }
     3.7 -  _file_offset = (long)n;
     3.8 +  size_t len = lseek(fd, 0, SEEK_END);
     3.9 +  struct FileMapInfo::FileMapHeader::space_info* si =
    3.10 +    &_header._space[MetaspaceShared::mc];
    3.11 +  if (si->_file_offset >= len || len - si->_file_offset < si->_used) {
    3.12 +    fail_continue("The shared archive file has been truncated.");
    3.13 +    return false;
    3.14 +  }
    3.15 +  _file_offset = n;
    3.16    return true;
    3.17  }
    3.18  
    3.19 @@ -268,6 +275,7 @@
    3.20    si->_capacity = capacity;
    3.21    si->_read_only = read_only;
    3.22    si->_allow_exec = allow_exec;
    3.23 +  si->_crc = ClassLoader::crc32(0, base, (jint)size);
    3.24    write_bytes_aligned(base, (int)size);
    3.25  }
    3.26  
    3.27 @@ -292,14 +300,15 @@
    3.28  // Align file position to an allocation unit boundary.
    3.29  
    3.30  void FileMapInfo::align_file_position() {
    3.31 -  long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity());
    3.32 +  size_t new_file_offset = align_size_up(_file_offset,
    3.33 +                                         os::vm_allocation_granularity());
    3.34    if (new_file_offset != _file_offset) {
    3.35      _file_offset = new_file_offset;
    3.36      if (_file_open) {
    3.37        // Seek one byte back from the target and write a byte to insure
    3.38        // that the written file is the correct length.
    3.39        _file_offset -= 1;
    3.40 -      if (lseek(_fd, _file_offset, SEEK_SET) < 0) {
    3.41 +      if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) {
    3.42          fail_stop("Unable to seek.", NULL);
    3.43        }
    3.44        char zero = 0;
    3.45 @@ -406,6 +415,19 @@
    3.46    return base;
    3.47  }
    3.48  
    3.49 +bool FileMapInfo::verify_region_checksum(int i) {
    3.50 +  if (!VerifySharedSpaces) {
    3.51 +    return true;
    3.52 +  }
    3.53 +  const char* buf = _header._space[i]._base;
    3.54 +  size_t sz = _header._space[i]._used;
    3.55 +  int crc = ClassLoader::crc32(0, buf, (jint)sz);
    3.56 +  if (crc != _header._space[i]._crc) {
    3.57 +    fail_continue("Checksum verification failed.");
    3.58 +    return false;
    3.59 +  }
    3.60 +  return true;
    3.61 +}
    3.62  
    3.63  // Unmap a memory region in the address space.
    3.64  
    3.65 @@ -457,8 +479,20 @@
    3.66    return true;
    3.67  }
    3.68  
    3.69 +int FileMapInfo::compute_header_crc() {
    3.70 +  char* header = (char*)&_header;
    3.71 +  // start computing from the field after _crc
    3.72 +  char* buf = (char*)&_header._crc + sizeof(int);
    3.73 +  size_t sz = sizeof(FileMapInfo::FileMapHeader) - (buf - header);
    3.74 +  int crc = ClassLoader::crc32(0, buf, (jint)sz);
    3.75 +  return crc;
    3.76 +}
    3.77  
    3.78  bool FileMapInfo::validate() {
    3.79 +  if (VerifySharedSpaces && compute_header_crc() != _header._crc) {
    3.80 +    fail_continue("Header checksum verification failed.");
    3.81 +    return false;
    3.82 +  }
    3.83    if (_header._version != current_version()) {
    3.84      fail_continue("The shared archive file is the wrong version.");
    3.85      return false;
     4.1 --- a/src/share/vm/memory/filemap.hpp	Fri Aug 08 15:15:52 2014 -0700
     4.2 +++ b/src/share/vm/memory/filemap.hpp	Tue Aug 12 17:46:16 2014 -0400
     4.3 @@ -54,7 +54,7 @@
     4.4  
     4.5    bool  _file_open;
     4.6    int   _fd;
     4.7 -  long  _file_offset;
     4.8 +  size_t  _file_offset;
     4.9  
    4.10    // FileMapHeader describes the shared space data in the file to be
    4.11    // mapped.  This structure gets written to a file.  It is not a class, so
    4.12 @@ -62,12 +62,14 @@
    4.13  
    4.14    struct FileMapHeader {
    4.15      int    _magic;                    // identify file type.
    4.16 +    int    _crc;                      // header crc checksum.
    4.17      int    _version;                  // (from enum, above.)
    4.18      size_t _alignment;                // how shared archive should be aligned
    4.19      int    _obj_alignment;            // value of ObjectAlignmentInBytes
    4.20  
    4.21      struct space_info {
    4.22 -      int    _file_offset;   // sizeof(this) rounded to vm page size
    4.23 +      int    _crc;           // crc checksum of the current space
    4.24 +      size_t _file_offset;   // sizeof(this) rounded to vm page size
    4.25        char*  _base;          // copy-on-write base address
    4.26        size_t _capacity;      // for validity checking
    4.27        size_t _used;          // for setting space top on read
    4.28 @@ -104,6 +106,8 @@
    4.29    }
    4.30  
    4.31    static int current_version()        { return _current_version; }
    4.32 +  int    compute_header_crc();
    4.33 +  void   set_header_crc(int crc)      { _header._crc = crc; }
    4.34    void   populate_header(size_t alignment);
    4.35    bool   validate();
    4.36    void   invalidate();
    4.37 @@ -136,6 +140,7 @@
    4.38    void  write_bytes_aligned(const void* buffer, int count);
    4.39    char* map_region(int i);
    4.40    void  unmap_region(int i);
    4.41 +  bool  verify_region_checksum(int i);
    4.42    void  close();
    4.43    bool  is_open() { return _file_open; }
    4.44    ReservedSpace reserve_shared_memory();
     5.1 --- a/src/share/vm/memory/metaspaceShared.cpp	Fri Aug 08 15:15:52 2014 -0700
     5.2 +++ b/src/share/vm/memory/metaspaceShared.cpp	Tue Aug 12 17:46:16 2014 -0400
     5.3 @@ -585,6 +585,7 @@
     5.4  
     5.5    // Pass 2 - write data.
     5.6    mapinfo->open_for_write();
     5.7 +  mapinfo->set_header_crc(mapinfo->compute_header_crc());
     5.8    mapinfo->write_header();
     5.9    mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true);
    5.10    mapinfo->write_space(MetaspaceShared::rw, _loader_data->rw_metaspace(), false);
    5.11 @@ -863,9 +864,13 @@
    5.12  
    5.13    // Map each shared region
    5.14    if ((_ro_base = mapinfo->map_region(ro)) != NULL &&
    5.15 +       mapinfo->verify_region_checksum(ro) &&
    5.16        (_rw_base = mapinfo->map_region(rw)) != NULL &&
    5.17 +       mapinfo->verify_region_checksum(rw) &&
    5.18        (_md_base = mapinfo->map_region(md)) != NULL &&
    5.19 +       mapinfo->verify_region_checksum(md) &&
    5.20        (_mc_base = mapinfo->map_region(mc)) != NULL &&
    5.21 +       mapinfo->verify_region_checksum(mc) &&
    5.22        (image_alignment == (size_t)max_alignment())) {
    5.23      // Success (no need to do anything)
    5.24      return true;
     6.1 --- a/src/share/vm/runtime/arguments.cpp	Fri Aug 08 15:15:52 2014 -0700
     6.2 +++ b/src/share/vm/runtime/arguments.cpp	Tue Aug 12 17:46:16 2014 -0400
     6.3 @@ -3581,6 +3581,11 @@
     6.4      return JNI_ENOMEM;
     6.5    }
     6.6  
     6.7 +  // Set up VerifySharedSpaces
     6.8 +  if (FLAG_IS_DEFAULT(VerifySharedSpaces) && SharedArchiveFile != NULL) {
     6.9 +    VerifySharedSpaces = true;
    6.10 +  }
    6.11 +
    6.12    // Delay warning until here so that we've had a chance to process
    6.13    // the -XX:-PrintWarnings flag
    6.14    if (needs_hotspotrc_warning) {
     7.1 --- a/src/share/vm/runtime/globals.hpp	Fri Aug 08 15:15:52 2014 -0700
     7.2 +++ b/src/share/vm/runtime/globals.hpp	Tue Aug 12 17:46:16 2014 -0400
     7.3 @@ -3745,6 +3745,10 @@
     7.4    product(bool, UseSharedSpaces, true,                                      \
     7.5            "Use shared spaces for metadata")                                 \
     7.6                                                                              \
     7.7 +  product(bool, VerifySharedSpaces, false,                                  \
     7.8 +          "Verify shared spaces (false for default archive, true for "      \
     7.9 +          "archive specified by -XX:SharedArchiveFile)")                    \
    7.10 +                                                                            \
    7.11    product(bool, RequireSharedSpaces, false,                                 \
    7.12            "Require shared spaces for metadata")                             \
    7.13                                                                              \

mercurial