提交 c2ab91a0 编写于 作者: J jiangli

8044269: Analysis of archive files.

Summary: Add checksum verification.
Reviewed-by: iklam, dholmes, mschoene
上级 bf3684a5
...@@ -84,6 +84,7 @@ typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *siz ...@@ -84,6 +84,7 @@ typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *siz
typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
static ZipOpen_t ZipOpen = NULL; static ZipOpen_t ZipOpen = NULL;
static ZipClose_t ZipClose = NULL; static ZipClose_t ZipClose = NULL;
...@@ -92,6 +93,7 @@ static ReadEntry_t ReadEntry = NULL; ...@@ -92,6 +93,7 @@ static ReadEntry_t ReadEntry = NULL;
static ReadMappedEntry_t ReadMappedEntry = NULL; static ReadMappedEntry_t ReadMappedEntry = NULL;
static GetNextEntry_t GetNextEntry = NULL; static GetNextEntry_t GetNextEntry = NULL;
static canonicalize_fn_t CanonicalizeEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL;
static Crc32_t Crc32 = NULL;
// Globals // Globals
...@@ -632,9 +634,11 @@ void ClassLoader::load_zip_library() { ...@@ -632,9 +634,11 @@ void ClassLoader::load_zip_library() {
ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry"));
ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry"));
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) { if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
GetNextEntry == NULL || Crc32 == NULL) {
vm_exit_during_initialization("Corrupted ZIP library", path); vm_exit_during_initialization("Corrupted ZIP library", path);
} }
...@@ -644,6 +648,11 @@ void ClassLoader::load_zip_library() { ...@@ -644,6 +648,11 @@ void ClassLoader::load_zip_library() {
// This lookup only works on 1.3. Do not check for non-null here // This lookup only works on 1.3. Do not check for non-null here
} }
int ClassLoader::crc32(int crc, const char* buf, int len) {
assert(Crc32 != NULL, "ZIP_CRC32 is not found");
return (*Crc32)(crc, (const jbyte*)buf, len);
}
// PackageInfo data exists in order to support the java.lang.Package // PackageInfo data exists in order to support the java.lang.Package
// class. A Package object provides information about a java package // class. A Package object provides information about a java package
// (version, vendor, etc.) which originates in the manifest of the jar // (version, vendor, etc.) which originates in the manifest of the jar
......
...@@ -215,6 +215,7 @@ class ClassLoader: AllStatic { ...@@ -215,6 +215,7 @@ class ClassLoader: AllStatic {
// to avoid confusing the zip library // to avoid confusing the zip library
static bool get_canonical_path(char* orig, char* out, int len); static bool get_canonical_path(char* orig, char* out, int len);
public: public:
static int crc32(int crc, const char* buf, int len);
// Used by the kernel jvm. // Used by the kernel jvm.
static void update_class_path_entry_list(char *path, static void update_class_path_entry_list(char *path,
bool check_for_duplicates); bool check_for_duplicates);
......
...@@ -177,7 +177,14 @@ bool FileMapInfo::init_from_file(int fd) { ...@@ -177,7 +177,14 @@ bool FileMapInfo::init_from_file(int fd) {
fail_continue("The shared archive file has the wrong version."); fail_continue("The shared archive file has the wrong version.");
return false; return false;
} }
_file_offset = (long)n; size_t len = lseek(fd, 0, SEEK_END);
struct FileMapInfo::FileMapHeader::space_info* si =
&_header._space[MetaspaceShared::mc];
if (si->_file_offset >= len || len - si->_file_offset < si->_used) {
fail_continue("The shared archive file has been truncated.");
return false;
}
_file_offset = n;
return true; return true;
} }
...@@ -268,6 +275,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size, ...@@ -268,6 +275,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
si->_capacity = capacity; si->_capacity = capacity;
si->_read_only = read_only; si->_read_only = read_only;
si->_allow_exec = allow_exec; si->_allow_exec = allow_exec;
si->_crc = ClassLoader::crc32(0, base, (jint)size);
write_bytes_aligned(base, (int)size); write_bytes_aligned(base, (int)size);
} }
...@@ -292,14 +300,15 @@ void FileMapInfo::write_bytes(const void* buffer, int nbytes) { ...@@ -292,14 +300,15 @@ void FileMapInfo::write_bytes(const void* buffer, int nbytes) {
// Align file position to an allocation unit boundary. // Align file position to an allocation unit boundary.
void FileMapInfo::align_file_position() { void FileMapInfo::align_file_position() {
long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity()); size_t new_file_offset = align_size_up(_file_offset,
os::vm_allocation_granularity());
if (new_file_offset != _file_offset) { if (new_file_offset != _file_offset) {
_file_offset = new_file_offset; _file_offset = new_file_offset;
if (_file_open) { if (_file_open) {
// Seek one byte back from the target and write a byte to insure // Seek one byte back from the target and write a byte to insure
// that the written file is the correct length. // that the written file is the correct length.
_file_offset -= 1; _file_offset -= 1;
if (lseek(_fd, _file_offset, SEEK_SET) < 0) { if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) {
fail_stop("Unable to seek.", NULL); fail_stop("Unable to seek.", NULL);
} }
char zero = 0; char zero = 0;
...@@ -406,6 +415,19 @@ char* FileMapInfo::map_region(int i) { ...@@ -406,6 +415,19 @@ char* FileMapInfo::map_region(int i) {
return base; return base;
} }
bool FileMapInfo::verify_region_checksum(int i) {
if (!VerifySharedSpaces) {
return true;
}
const char* buf = _header._space[i]._base;
size_t sz = _header._space[i]._used;
int crc = ClassLoader::crc32(0, buf, (jint)sz);
if (crc != _header._space[i]._crc) {
fail_continue("Checksum verification failed.");
return false;
}
return true;
}
// Unmap a memory region in the address space. // Unmap a memory region in the address space.
...@@ -457,8 +479,20 @@ bool FileMapInfo::initialize() { ...@@ -457,8 +479,20 @@ bool FileMapInfo::initialize() {
return true; return true;
} }
int FileMapInfo::compute_header_crc() {
char* header = (char*)&_header;
// start computing from the field after _crc
char* buf = (char*)&_header._crc + sizeof(int);
size_t sz = sizeof(FileMapInfo::FileMapHeader) - (buf - header);
int crc = ClassLoader::crc32(0, buf, (jint)sz);
return crc;
}
bool FileMapInfo::validate() { bool FileMapInfo::validate() {
if (VerifySharedSpaces && compute_header_crc() != _header._crc) {
fail_continue("Header checksum verification failed.");
return false;
}
if (_header._version != current_version()) { if (_header._version != current_version()) {
fail_continue("The shared archive file is the wrong version."); fail_continue("The shared archive file is the wrong version.");
return false; return false;
......
...@@ -54,7 +54,7 @@ private: ...@@ -54,7 +54,7 @@ private:
bool _file_open; bool _file_open;
int _fd; int _fd;
long _file_offset; size_t _file_offset;
// FileMapHeader describes the shared space data in the file to be // FileMapHeader describes the shared space data in the file to be
// mapped. This structure gets written to a file. It is not a class, so // mapped. This structure gets written to a file. It is not a class, so
...@@ -62,12 +62,14 @@ private: ...@@ -62,12 +62,14 @@ private:
struct FileMapHeader { struct FileMapHeader {
int _magic; // identify file type. int _magic; // identify file type.
int _crc; // header crc checksum.
int _version; // (from enum, above.) int _version; // (from enum, above.)
size_t _alignment; // how shared archive should be aligned size_t _alignment; // how shared archive should be aligned
int _obj_alignment; // value of ObjectAlignmentInBytes int _obj_alignment; // value of ObjectAlignmentInBytes
struct space_info { struct space_info {
int _file_offset; // sizeof(this) rounded to vm page size int _crc; // crc checksum of the current space
size_t _file_offset; // sizeof(this) rounded to vm page size
char* _base; // copy-on-write base address char* _base; // copy-on-write base address
size_t _capacity; // for validity checking size_t _capacity; // for validity checking
size_t _used; // for setting space top on read size_t _used; // for setting space top on read
...@@ -104,6 +106,8 @@ public: ...@@ -104,6 +106,8 @@ public:
} }
static int current_version() { return _current_version; } static int current_version() { return _current_version; }
int compute_header_crc();
void set_header_crc(int crc) { _header._crc = crc; }
void populate_header(size_t alignment); void populate_header(size_t alignment);
bool validate(); bool validate();
void invalidate(); void invalidate();
...@@ -136,6 +140,7 @@ public: ...@@ -136,6 +140,7 @@ public:
void write_bytes_aligned(const void* buffer, int count); void write_bytes_aligned(const void* buffer, int count);
char* map_region(int i); char* map_region(int i);
void unmap_region(int i); void unmap_region(int i);
bool verify_region_checksum(int i);
void close(); void close();
bool is_open() { return _file_open; } bool is_open() { return _file_open; }
ReservedSpace reserve_shared_memory(); ReservedSpace reserve_shared_memory();
......
...@@ -585,6 +585,7 @@ void VM_PopulateDumpSharedSpace::doit() { ...@@ -585,6 +585,7 @@ void VM_PopulateDumpSharedSpace::doit() {
// Pass 2 - write data. // Pass 2 - write data.
mapinfo->open_for_write(); mapinfo->open_for_write();
mapinfo->set_header_crc(mapinfo->compute_header_crc());
mapinfo->write_header(); mapinfo->write_header();
mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true); mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true);
mapinfo->write_space(MetaspaceShared::rw, _loader_data->rw_metaspace(), false); mapinfo->write_space(MetaspaceShared::rw, _loader_data->rw_metaspace(), false);
...@@ -863,9 +864,13 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { ...@@ -863,9 +864,13 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
// Map each shared region // Map each shared region
if ((_ro_base = mapinfo->map_region(ro)) != NULL && if ((_ro_base = mapinfo->map_region(ro)) != NULL &&
mapinfo->verify_region_checksum(ro) &&
(_rw_base = mapinfo->map_region(rw)) != NULL && (_rw_base = mapinfo->map_region(rw)) != NULL &&
mapinfo->verify_region_checksum(rw) &&
(_md_base = mapinfo->map_region(md)) != NULL && (_md_base = mapinfo->map_region(md)) != NULL &&
mapinfo->verify_region_checksum(md) &&
(_mc_base = mapinfo->map_region(mc)) != NULL && (_mc_base = mapinfo->map_region(mc)) != NULL &&
mapinfo->verify_region_checksum(mc) &&
(image_alignment == (size_t)max_alignment())) { (image_alignment == (size_t)max_alignment())) {
// Success (no need to do anything) // Success (no need to do anything)
return true; return true;
......
...@@ -3581,6 +3581,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) { ...@@ -3581,6 +3581,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
return JNI_ENOMEM; return JNI_ENOMEM;
} }
// Set up VerifySharedSpaces
if (FLAG_IS_DEFAULT(VerifySharedSpaces) && SharedArchiveFile != NULL) {
VerifySharedSpaces = true;
}
// Delay warning until here so that we've had a chance to process // Delay warning until here so that we've had a chance to process
// the -XX:-PrintWarnings flag // the -XX:-PrintWarnings flag
if (needs_hotspotrc_warning) { if (needs_hotspotrc_warning) {
......
...@@ -3745,6 +3745,10 @@ class CommandLineFlags { ...@@ -3745,6 +3745,10 @@ class CommandLineFlags {
product(bool, UseSharedSpaces, true, \ product(bool, UseSharedSpaces, true, \
"Use shared spaces for metadata") \ "Use shared spaces for metadata") \
\ \
product(bool, VerifySharedSpaces, false, \
"Verify shared spaces (false for default archive, true for " \
"archive specified by -XX:SharedArchiveFile)") \
\
product(bool, RequireSharedSpaces, false, \ product(bool, RequireSharedSpaces, false, \
"Require shared spaces for metadata") \ "Require shared spaces for metadata") \
\ \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册