Skip to content
Permalink
Browse files
8263974: Move SystemDictionary::verify_protection_domain
Reviewed-by: hseigel, lfoltan, dholmes
  • Loading branch information
coleenp committed Mar 23, 2021
1 parent 9dad857 commit de2ff25687b2f19e5d4ea4efb6c973ad879f32f7
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 95 deletions.
@@ -30,7 +30,6 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoadInfo.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/fieldLayoutBuilder.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "memory/resourceArea.hpp"

@@ -25,18 +25,23 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/protectionDomainCache.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/iterator.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "utilities/hashtable.inline.hpp"
@@ -285,7 +290,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
for (DictionaryEntry* entry = bucket(index);
entry != NULL;
entry = entry->next()) {
if (entry->hash() == hash && entry->equals(class_name)) {
if (entry->hash() == hash && entry->instance_klass()->name() == class_name) {
return entry;
}
}
@@ -320,8 +325,7 @@ InstanceKlass* Dictionary::find_class(unsigned int hash,

void Dictionary::add_protection_domain(int index, unsigned int hash,
InstanceKlass* klass,
Handle protection_domain,
TRAPS) {
Handle protection_domain) {
assert(java_lang_System::allow_security_manager(), "only needed if security manager allowed");
Symbol* klass_name = klass->name();
DictionaryEntry* entry = get_entry(index, hash, klass_name);
@@ -341,14 +345,82 @@ void Dictionary::add_protection_domain(int index, unsigned int hash,
}


bool Dictionary::is_valid_protection_domain(unsigned int hash,
inline bool Dictionary::is_valid_protection_domain(unsigned int hash,
Symbol* name,
Handle protection_domain) {
int index = hash_to_index(hash);
DictionaryEntry* entry = get_entry(index, hash, name);
return entry->is_valid_protection_domain(protection_domain);
}

void Dictionary::validate_protection_domain(unsigned int name_hash,
InstanceKlass* klass,
Handle class_loader,
Handle protection_domain,
TRAPS) {

assert(class_loader() != NULL, "Should not call this");
assert(protection_domain() != NULL, "Should not call this");

if (!java_lang_System::allow_security_manager() ||
is_valid_protection_domain(name_hash, klass->name(), protection_domain)) {
return;
}

// We only have to call checkPackageAccess if there's a security manager installed.
if (java_lang_System::has_security_manager()) {

// This handle and the class_loader handle passed in keeps this class from
// being unloaded through several GC points.
// The class_loader handle passed in is the initiating loader.
Handle mirror(THREAD, klass->java_mirror());

// Now we have to call back to java to check if the initating class has access
InstanceKlass* system_loader = vmClasses::ClassLoader_klass();
JavaValue result(T_VOID);
JavaCalls::call_special(&result,
class_loader,
system_loader,
vmSymbols::checkPackageAccess_name(),
vmSymbols::class_protectiondomain_signature(),
mirror,
protection_domain,
THREAD);

LogTarget(Debug, protectiondomain) lt;
if (lt.is_enabled()) {
ResourceMark rm(THREAD);
// Print out trace information
LogStream ls(lt);
ls.print_cr("Checking package access");
ls.print("class loader: ");
class_loader()->print_value_on(&ls);
ls.print(" protection domain: ");
protection_domain()->print_value_on(&ls);
ls.print(" loading: "); klass->print_value_on(&ls);
if (HAS_PENDING_EXCEPTION) {
ls.print_cr(" DENIED !!!!!!!!!!!!!!!!!!!!!");
} else {
ls.print_cr(" granted");
}
}

if (HAS_PENDING_EXCEPTION) return;
}

// If no exception has been thrown, we have validated the protection domain
// Insert the protection domain of the initiating class into the set.
// We still have to add the protection_domain to the dictionary in case a new
// security manager is installed later. Calls to load the same class with class loader
// and protection domain are expected to succeed.
{
MutexLocker mu(THREAD, SystemDictionary_lock);
int d_index = hash_to_index(name_hash);
add_protection_domain(d_index, name_hash, klass,
protection_domain);
}
}

// During class loading we may have cached a protection domain that has
// since been unreferenced, so this entry should be cleared.
void Dictionary::clean_cached_protection_domains() {
@@ -71,12 +71,11 @@ class Dictionary : public Hashtable<InstanceKlass*, mtClass> {

// Protection domains
InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain);
bool is_valid_protection_domain(unsigned int hash,
Symbol* name,
Handle protection_domain);
void add_protection_domain(int index, unsigned int hash,
InstanceKlass* klass,
Handle protection_domain, TRAPS);
void validate_protection_domain(unsigned int name_hash,
InstanceKlass* klass,
Handle class_loader,
Handle protection_domain,
TRAPS);

void print_on(outputStream* st) const;
void verify();
@@ -102,6 +101,13 @@ class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
}

void free_entry(DictionaryEntry* entry);

bool is_valid_protection_domain(unsigned int hash,
Symbol* name,
Handle protection_domain);
void add_protection_domain(int index, unsigned int hash,
InstanceKlass* klass,
Handle protection_domain);
};

// An entry in the class loader data dictionaries, this describes a class as
@@ -156,11 +162,6 @@ class DictionaryEntry : public HashtableEntry<InstanceKlass*, mtClass> {
inline bool is_valid_protection_domain(Handle protection_domain);
void verify_protection_domain_set();

bool equals(const Symbol* class_name) const {
InstanceKlass* klass = (InstanceKlass*)literal();
return (klass->name() == class_name);
}

void print_count(outputStream *st);
void verify();
};
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/classLoadInfo.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/lambdaFormInvokers.hpp"
@@ -455,73 +455,6 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
return superk;
}

void SystemDictionary::validate_protection_domain(InstanceKlass* klass,
Handle class_loader,
Handle protection_domain,
TRAPS) {
// Now we have to call back to java to check if the initating class has access
assert(class_loader() != NULL, "Should not call this");
assert(protection_domain() != NULL, "Should not call this");

// We only have to call checkPackageAccess if there's a security manager installed.
if (java_lang_System::has_security_manager()) {

// This handle and the class_loader handle passed in keeps this class from
// being unloaded through several GC points.
// The class_loader handle passed in is the initiating loader.
Handle mirror(THREAD, klass->java_mirror());

InstanceKlass* system_loader = vmClasses::ClassLoader_klass();
JavaValue result(T_VOID);
JavaCalls::call_special(&result,
class_loader,
system_loader,
vmSymbols::checkPackageAccess_name(),
vmSymbols::class_protectiondomain_signature(),
mirror,
protection_domain,
THREAD);

LogTarget(Debug, protectiondomain) lt;
if (lt.is_enabled()) {
ResourceMark rm(THREAD);
// Print out trace information
LogStream ls(lt);
ls.print_cr("Checking package access");
ls.print("class loader: ");
class_loader()->print_value_on(&ls);
ls.print(" protection domain: ");
protection_domain()->print_value_on(&ls);
ls.print(" loading: "); klass->print_value_on(&ls);
if (HAS_PENDING_EXCEPTION) {
ls.print_cr(" DENIED !!!!!!!!!!!!!!!!!!!!!");
} else {
ls.print_cr(" granted");
}
}

if (HAS_PENDING_EXCEPTION) return;
}

// If no exception has been thrown, we have validated the protection domain
// Insert the protection domain of the initiating class into the set.
// We still have to add the protection_domain to the dictionary in case a new
// security manager is installed later. Calls to load the same class with class loader
// and protection domain are expected to succeed.
{
ClassLoaderData* loader_data = class_loader_data(class_loader);
Dictionary* dictionary = loader_data->dictionary();

Symbol* kn = klass->name();
unsigned int name_hash = dictionary->compute_hash(kn);

MutexLocker mu(THREAD, SystemDictionary_lock);
int d_index = dictionary->hash_to_index(name_hash);
dictionary->add_protection_domain(d_index, name_hash, klass,
protection_domain, THREAD);
}
}

// We only get here if this thread finds that another thread
// has already claimed the placeholder token for the current operation,
// but that other thread either never owned or gave up the
@@ -876,12 +809,9 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
DEBUG_ONLY(verify_dictionary_entry(name, loaded_class));

// Check if the protection domain is present it has the right access
if (protection_domain() != NULL &&
java_lang_System::allow_security_manager() &&
!dictionary->is_valid_protection_domain(name_hash, name,
protection_domain)) {
if (protection_domain() != NULL) {
// Verify protection domain. If it fails an exception is thrown
validate_protection_domain(loaded_class, class_loader, protection_domain, CHECK_NULL);
dictionary->validate_protection_domain(name_hash, loaded_class, class_loader, protection_domain, CHECK_NULL);
}

return loaded_class;
@@ -315,10 +315,6 @@ class SystemDictionary : AllStatic {
static OopHandle _java_system_loader;
static OopHandle _java_platform_loader;

static void validate_protection_domain(InstanceKlass* klass,
Handle class_loader,
Handle protection_domain, TRAPS);

friend class VM_PopulateDumpSharedSpace;
static LoaderConstraintTable* constraints() { return _loader_constraints; }
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
@@ -26,7 +26,6 @@
#include "jvm_io.h"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderDataGraph.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"

0 comments on commit de2ff25

Please sign in to comment.