提交 4eb202a8 编写于 作者: M mullan

8001330: Improve on checking order

Reviewed-by: acorn, hawtin
上级 ad497b3b
...@@ -2774,6 +2774,7 @@ void java_lang_invoke_CallSite::compute_offsets() { ...@@ -2774,6 +2774,7 @@ void java_lang_invoke_CallSite::compute_offsets() {
int java_security_AccessControlContext::_context_offset = 0; int java_security_AccessControlContext::_context_offset = 0;
int java_security_AccessControlContext::_privilegedContext_offset = 0; int java_security_AccessControlContext::_privilegedContext_offset = 0;
int java_security_AccessControlContext::_isPrivileged_offset = 0; int java_security_AccessControlContext::_isPrivileged_offset = 0;
int java_security_AccessControlContext::_isAuthorized_offset = -1;
void java_security_AccessControlContext::compute_offsets() { void java_security_AccessControlContext::compute_offsets() {
assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
...@@ -2794,9 +2795,20 @@ void java_security_AccessControlContext::compute_offsets() { ...@@ -2794,9 +2795,20 @@ void java_security_AccessControlContext::compute_offsets() {
fatal("Invalid layout of java.security.AccessControlContext"); fatal("Invalid layout of java.security.AccessControlContext");
} }
_isPrivileged_offset = fd.offset(); _isPrivileged_offset = fd.offset();
// The offset may not be present for bootstrapping with older JDK.
if (ik->find_local_field(vmSymbols::isAuthorized_name(), vmSymbols::bool_signature(), &fd)) {
_isAuthorized_offset = fd.offset();
}
} }
bool java_security_AccessControlContext::is_authorized(Handle context) {
assert(context.not_null() && context->klass() == SystemDictionary::AccessControlContext_klass(), "Invalid type");
assert(_isAuthorized_offset != -1, "should be set");
return context->bool_field(_isAuthorized_offset) != 0;
}
oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) { oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) {
assert(_isPrivileged_offset != 0, "offsets should have been initialized"); assert(_isPrivileged_offset != 0, "offsets should have been initialized");
// Ensure klass is initialized // Ensure klass is initialized
...@@ -2807,6 +2819,8 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr ...@@ -2807,6 +2819,8 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr
result->obj_field_put(_context_offset, context()); result->obj_field_put(_context_offset, context());
result->obj_field_put(_privilegedContext_offset, privileged_context()); result->obj_field_put(_privilegedContext_offset, privileged_context());
result->bool_field_put(_isPrivileged_offset, isPrivileged); result->bool_field_put(_isPrivileged_offset, isPrivileged);
// whitelist AccessControlContexts created by the JVM.
result->bool_field_put(_isAuthorized_offset, true);
return result; return result;
} }
...@@ -2916,6 +2930,15 @@ int java_lang_System::err_offset_in_bytes() { ...@@ -2916,6 +2930,15 @@ int java_lang_System::err_offset_in_bytes() {
} }
bool java_lang_System::has_security_manager() {
InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::System_klass());
address addr = ik->static_field_addr(static_security_offset);
if (UseCompressedOops) {
return oopDesc::load_decode_heap_oop((narrowOop *)addr) != NULL;
} else {
return oopDesc::load_decode_heap_oop((oop*)addr) != NULL;
}
}
int java_lang_Class::_klass_offset; int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset; int java_lang_Class::_array_klass_offset;
...@@ -2976,6 +2999,7 @@ int java_lang_ClassLoader::parent_offset; ...@@ -2976,6 +2999,7 @@ int java_lang_ClassLoader::parent_offset;
int java_lang_System::static_in_offset; int java_lang_System::static_in_offset;
int java_lang_System::static_out_offset; int java_lang_System::static_out_offset;
int java_lang_System::static_err_offset; int java_lang_System::static_err_offset;
int java_lang_System::static_security_offset;
int java_lang_StackTraceElement::declaringClass_offset; int java_lang_StackTraceElement::declaringClass_offset;
int java_lang_StackTraceElement::methodName_offset; int java_lang_StackTraceElement::methodName_offset;
int java_lang_StackTraceElement::fileName_offset; int java_lang_StackTraceElement::fileName_offset;
...@@ -3101,6 +3125,7 @@ void JavaClasses::compute_hard_coded_offsets() { ...@@ -3101,6 +3125,7 @@ void JavaClasses::compute_hard_coded_offsets() {
java_lang_System::static_in_offset = java_lang_System::hc_static_in_offset * x; java_lang_System::static_in_offset = java_lang_System::hc_static_in_offset * x;
java_lang_System::static_out_offset = java_lang_System::hc_static_out_offset * x; java_lang_System::static_out_offset = java_lang_System::hc_static_out_offset * x;
java_lang_System::static_err_offset = java_lang_System::hc_static_err_offset * x; java_lang_System::static_err_offset = java_lang_System::hc_static_err_offset * x;
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
// java_lang_StackTraceElement // java_lang_StackTraceElement
java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header; java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header;
...@@ -3300,6 +3325,7 @@ void JavaClasses::check_offsets() { ...@@ -3300,6 +3325,7 @@ void JavaClasses::check_offsets() {
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, in, "Ljava/io/InputStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, in, "Ljava/io/InputStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, out, "Ljava/io/PrintStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, out, "Ljava/io/PrintStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, err, "Ljava/io/PrintStream;"); CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, err, "Ljava/io/PrintStream;");
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, security, "Ljava/lang/SecurityManager;");
// java.lang.StackTraceElement // java.lang.StackTraceElement
......
...@@ -1149,11 +1149,14 @@ class java_security_AccessControlContext: AllStatic { ...@@ -1149,11 +1149,14 @@ class java_security_AccessControlContext: AllStatic {
static int _context_offset; static int _context_offset;
static int _privilegedContext_offset; static int _privilegedContext_offset;
static int _isPrivileged_offset; static int _isPrivileged_offset;
static int _isAuthorized_offset;
static void compute_offsets(); static void compute_offsets();
public: public:
static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS); static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS);
static bool is_authorized(Handle context);
// Debugging/initialization // Debugging/initialization
friend class JavaClasses; friend class JavaClasses;
}; };
...@@ -1213,18 +1216,22 @@ class java_lang_System : AllStatic { ...@@ -1213,18 +1216,22 @@ class java_lang_System : AllStatic {
enum { enum {
hc_static_in_offset = 0, hc_static_in_offset = 0,
hc_static_out_offset = 1, hc_static_out_offset = 1,
hc_static_err_offset = 2 hc_static_err_offset = 2,
hc_static_security_offset = 3
}; };
static int static_in_offset; static int static_in_offset;
static int static_out_offset; static int static_out_offset;
static int static_err_offset; static int static_err_offset;
static int static_security_offset;
public: public:
static int in_offset_in_bytes(); static int in_offset_in_bytes();
static int out_offset_in_bytes(); static int out_offset_in_bytes();
static int err_offset_in_bytes(); static int err_offset_in_bytes();
static bool has_security_manager();
// Debugging // Debugging
friend class JavaClasses; friend class JavaClasses;
}; };
......
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
template(java_lang_SecurityManager, "java/lang/SecurityManager") \ template(java_lang_SecurityManager, "java/lang/SecurityManager") \
template(java_security_AccessControlContext, "java/security/AccessControlContext") \ template(java_security_AccessControlContext, "java/security/AccessControlContext") \
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \ template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
template(java_io_OutputStream, "java/io/OutputStream") \ template(java_io_OutputStream, "java/io/OutputStream") \
template(java_io_Reader, "java/io/Reader") \ template(java_io_Reader, "java/io/Reader") \
template(java_io_BufferedReader, "java/io/BufferedReader") \ template(java_io_BufferedReader, "java/io/BufferedReader") \
...@@ -346,6 +347,7 @@ ...@@ -346,6 +347,7 @@
template(contextClassLoader_name, "contextClassLoader") \ template(contextClassLoader_name, "contextClassLoader") \
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \ template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
template(isPrivileged_name, "isPrivileged") \ template(isPrivileged_name, "isPrivileged") \
template(isAuthorized_name, "isAuthorized") \
template(getClassContext_name, "getClassContext") \ template(getClassContext_name, "getClassContext") \
template(wait_name, "wait") \ template(wait_name, "wait") \
template(checkPackageAccess_name, "checkPackageAccess") \ template(checkPackageAccess_name, "checkPackageAccess") \
......
...@@ -108,6 +108,7 @@ oop Universe::_the_null_string = NULL; ...@@ -108,6 +108,7 @@ oop Universe::_the_null_string = NULL;
oop Universe::_the_min_jint_string = NULL; oop Universe::_the_min_jint_string = NULL;
LatestMethodOopCache* Universe::_finalizer_register_cache = NULL; LatestMethodOopCache* Universe::_finalizer_register_cache = NULL;
LatestMethodOopCache* Universe::_loader_addClass_cache = NULL; LatestMethodOopCache* Universe::_loader_addClass_cache = NULL;
LatestMethodOopCache* Universe::_pd_implies_cache = NULL;
ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL; ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL;
oop Universe::_out_of_memory_error_java_heap = NULL; oop Universe::_out_of_memory_error_java_heap = NULL;
oop Universe::_out_of_memory_error_perm_gen = NULL; oop Universe::_out_of_memory_error_perm_gen = NULL;
...@@ -224,6 +225,7 @@ void Universe::serialize(SerializeClosure* f, bool do_all) { ...@@ -224,6 +225,7 @@ void Universe::serialize(SerializeClosure* f, bool do_all) {
_finalizer_register_cache->serialize(f); _finalizer_register_cache->serialize(f);
_loader_addClass_cache->serialize(f); _loader_addClass_cache->serialize(f);
_reflect_invoke_cache->serialize(f); _reflect_invoke_cache->serialize(f);
_pd_implies_cache->serialize(f);
} }
void Universe::check_alignment(uintx size, uintx alignment, const char* name) { void Universe::check_alignment(uintx size, uintx alignment, const char* name) {
...@@ -648,6 +650,7 @@ jint universe_init() { ...@@ -648,6 +650,7 @@ jint universe_init() {
// Metaspace::initialize_shared_spaces() tries to populate them. // Metaspace::initialize_shared_spaces() tries to populate them.
Universe::_finalizer_register_cache = new LatestMethodOopCache(); Universe::_finalizer_register_cache = new LatestMethodOopCache();
Universe::_loader_addClass_cache = new LatestMethodOopCache(); Universe::_loader_addClass_cache = new LatestMethodOopCache();
Universe::_pd_implies_cache = new LatestMethodOopCache();
Universe::_reflect_invoke_cache = new ActiveMethodOopsCache(); Universe::_reflect_invoke_cache = new ActiveMethodOopsCache();
if (UseSharedSpaces) { if (UseSharedSpaces) {
...@@ -1082,6 +1085,23 @@ bool universe_post_init() { ...@@ -1082,6 +1085,23 @@ bool universe_post_init() {
Universe::_loader_addClass_cache->init( Universe::_loader_addClass_cache->init(
SystemDictionary::ClassLoader_klass(), m, CHECK_false); SystemDictionary::ClassLoader_klass(), m, CHECK_false);
// Setup method for checking protection domain
InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->link_class(CHECK_false);
m = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->
find_method(vmSymbols::impliesCreateAccessControlContext_name(),
vmSymbols::void_boolean_signature());
// Allow NULL which should only happen with bootstrapping.
if (m != NULL) {
if (m->is_static()) {
// NoSuchMethodException doesn't actually work because it tries to run the
// <init> function before java_lang_Class is linked. Print error and exit.
tty->print_cr("ProtectionDomain.impliesCreateAccessControlContext() has the wrong linkage");
return false; // initialization failed
}
Universe::_pd_implies_cache->init(
SystemDictionary::ProtectionDomain_klass(), m, CHECK_false);;
}
// The folowing is initializing converter functions for serialization in // The folowing is initializing converter functions for serialization in
// JVM.cpp. If we clean up the StrictMath code above we may want to find // JVM.cpp. If we clean up the StrictMath code above we may want to find
// a better solution for this as well. // a better solution for this as well.
...@@ -1497,6 +1517,7 @@ bool ActiveMethodOopsCache::is_same_method(Method* const method) const { ...@@ -1497,6 +1517,7 @@ bool ActiveMethodOopsCache::is_same_method(Method* const method) const {
Method* LatestMethodOopCache::get_Method() { Method* LatestMethodOopCache::get_Method() {
if (klass() == NULL) return NULL;
InstanceKlass* ik = InstanceKlass::cast(klass()); InstanceKlass* ik = InstanceKlass::cast(klass());
Method* m = ik->method_with_idnum(method_idnum()); Method* m = ik->method_with_idnum(method_idnum());
assert(m != NULL, "sanity check"); assert(m != NULL, "sanity check");
......
...@@ -176,6 +176,7 @@ class Universe: AllStatic { ...@@ -176,6 +176,7 @@ class Universe: AllStatic {
static oop _the_min_jint_string; // A cache of "-2147483648" as a Java string static oop _the_min_jint_string; // A cache of "-2147483648" as a Java string
static LatestMethodOopCache* _finalizer_register_cache; // static method for registering finalizable objects static LatestMethodOopCache* _finalizer_register_cache; // static method for registering finalizable objects
static LatestMethodOopCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector static LatestMethodOopCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector
static LatestMethodOopCache* _pd_implies_cache; // method for checking protection domain attributes
static ActiveMethodOopsCache* _reflect_invoke_cache; // method for security checks static ActiveMethodOopsCache* _reflect_invoke_cache; // method for security checks
static oop _out_of_memory_error_java_heap; // preallocated error object (no backtrace) static oop _out_of_memory_error_java_heap; // preallocated error object (no backtrace)
static oop _out_of_memory_error_perm_gen; // preallocated error object (no backtrace) static oop _out_of_memory_error_perm_gen; // preallocated error object (no backtrace)
...@@ -346,7 +347,10 @@ class Universe: AllStatic { ...@@ -346,7 +347,10 @@ class Universe: AllStatic {
static oop the_min_jint_string() { return _the_min_jint_string; } static oop the_min_jint_string() { return _the_min_jint_string; }
static Method* finalizer_register_method() { return _finalizer_register_cache->get_Method(); } static Method* finalizer_register_method() { return _finalizer_register_cache->get_Method(); }
static Method* loader_addClass_method() { return _loader_addClass_cache->get_Method(); } static Method* loader_addClass_method() { return _loader_addClass_cache->get_Method(); }
static Method* protection_domain_implies_method() { return _pd_implies_cache->get_Method(); }
static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; } static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; }
static oop null_ptr_exception_instance() { return _null_ptr_exception_instance; } static oop null_ptr_exception_instance() { return _null_ptr_exception_instance; }
static oop arithmetic_exception_instance() { return _arithmetic_exception_instance; } static oop arithmetic_exception_instance() { return _arithmetic_exception_instance; }
static oop virtual_machine_error_instance() { return _virtual_machine_error_instance; } static oop virtual_machine_error_instance() { return _virtual_machine_error_instance; }
......
...@@ -1144,6 +1144,56 @@ JVM_ENTRY(void, JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protect ...@@ -1144,6 +1144,56 @@ JVM_ENTRY(void, JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protect
} }
JVM_END JVM_END
static bool is_authorized(Handle context, instanceKlassHandle klass, TRAPS) {
// If there is a security manager and protection domain, check the access
// in the protection domain, otherwise it is authorized.
if (java_lang_System::has_security_manager()) {
// For bootstrapping, if pd implies method isn't in the JDK, allow
// this context to revert to older behavior.
// In this case the isAuthorized field in AccessControlContext is also not
// present.
if (Universe::protection_domain_implies_method() == NULL) {
return true;
}
// Whitelist certain access control contexts
if (java_security_AccessControlContext::is_authorized(context)) {
return true;
}
oop prot = klass->protection_domain();
if (prot != NULL) {
// Call pd.implies(new SecurityPermission("createAccessControlContext"))
// in the new wrapper.
methodHandle m(THREAD, Universe::protection_domain_implies_method());
Handle h_prot(THREAD, prot);
JavaValue result(T_BOOLEAN);
JavaCallArguments args(h_prot);
JavaCalls::call(&result, m, &args, CHECK_false);
return (result.get_jboolean() != 0);
}
}
return true;
}
// Create an AccessControlContext with a protection domain with null codesource
// and null permissions - which gives no permissions.
oop create_dummy_access_control_context(TRAPS) {
InstanceKlass* pd_klass = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass());
// new ProtectionDomain(null,null);
oop null_protection_domain = pd_klass->allocate_instance(CHECK_NULL);
Handle null_pd(THREAD, null_protection_domain);
// new ProtectionDomain[] {pd};
objArrayOop context = oopFactory::new_objArray(pd_klass, 1, CHECK_NULL);
context->obj_at_put(0, null_pd());
// new AccessControlContext(new ProtectionDomain[] {pd})
objArrayHandle h_context(THREAD, context);
oop result = java_security_AccessControlContext::create(h_context, false, Handle(), CHECK_NULL);
return result;
}
JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)) JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException))
JVMWrapper("JVM_DoPrivileged"); JVMWrapper("JVM_DoPrivileged");
...@@ -1152,8 +1202,29 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job ...@@ -1152,8 +1202,29 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job
THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), "Null action"); THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), "Null action");
} }
// Stack allocated list of privileged stack elements // Compute the frame initiating the do privileged operation and setup the privileged stack
PrivilegedElement pi; vframeStream vfst(thread);
vfst.security_get_caller_frame(1);
if (vfst.at_end()) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "no caller?");
}
Method* method = vfst.method();
instanceKlassHandle klass (THREAD, method->method_holder());
// Check that action object understands "Object run()"
Handle h_context;
if (context != NULL) {
h_context = Handle(THREAD, JNIHandles::resolve(context));
bool authorized = is_authorized(h_context, klass, CHECK_NULL);
if (!authorized) {
// Create an unprivileged access control object and call it's run function
// instead.
oop noprivs = create_dummy_access_control_context(CHECK_NULL);
h_context = Handle(THREAD, noprivs);
}
}
// Check that action object understands "Object run()" // Check that action object understands "Object run()"
Handle object (THREAD, JNIHandles::resolve(action)); Handle object (THREAD, JNIHandles::resolve(action));
...@@ -1167,12 +1238,10 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job ...@@ -1167,12 +1238,10 @@ JVM_ENTRY(jobject, JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, job
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method"); THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method");
} }
// Compute the frame initiating the do privileged operation and setup the privileged stack // Stack allocated list of privileged stack elements
vframeStream vfst(thread); PrivilegedElement pi;
vfst.security_get_caller_frame(1);
if (!vfst.at_end()) { if (!vfst.at_end()) {
pi.initialize(&vfst, JNIHandles::resolve(context), thread->privileged_stack_top(), CHECK_NULL); pi.initialize(&vfst, h_context(), thread->privileged_stack_top(), CHECK_NULL);
thread->set_privileged_stack_top(&pi); thread->set_privileged_stack_top(&pi);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册