view patches/security/20130618/8001330-checking_order_improvement.patch @ 3011:736ee5b3272b

Remove unused patches and those which need more testing in HEAD. 2013-07-10 Andrew John Hughes <gnu.andrew@redhat.com> * patches/security/20130618/7158805-nested_subroutine_rewriting-it6.patch: Readd parts of patch removed without note in an earlier backport and fix copyright headers to apply (2011 instead of 2010). 2013-07-09 Andrew John Hughes <gnu.andrew@redhat.com> * patches/ecj/ant.patch, * patches/openjdk/6990754-handle_renames.patch, * patches/openjdk/6990754-use_native_memory_for_symboltable.patch, * patches/openjdk/7008809-report_class_in_arraystoreexception.patch, * patches/openjdk/7014851-unused_parallel_compaction_code.patch, * patches/openjdk/7017732-move_static_fields_to_class.patch, * patches/openjdk/7036747-elfstringtable.patch, * patches/openjdk/7086585-flexible_field_injection.patch, * patches/openjdk/7188114-alternate_command_line_parser.patch, * patches/openjdk/7199143-OCSP_timeout.patch, * patches/openjdk/8002070-remove_logger_stack_search.patch, * patches/openjdk/8002070-remove_logger_stack_search_2.patch, * patches/openjdk/8006120-server_jre.patch, * patches/openjdk/8006536-remove_trailing_slashes.patch, * patches/openjdk/8009463-space_and_final_backslash.patch, * patches/openjdk/8010118-caller_sensitive.patch, * patches/openjdk/8010213-set_socketoptions_windows.patch, * patches/openjdk/8011139-revise_checking_getenclosingclass.patch, * patches/openjdk/8011313-OCSP_timeout_wrong_value.patch, * patches/openjdk/8011990-logger_test_urls.patch, * patches/openjdk/8012243-serial_regression.patch, * patches/openjdk/8013380-handle_renames.patch, * patches/openjdk/8013380-logger_stack_walk_glassfish.patch, * patches/openjdk/8014205-blank_swing_dialogs_windows.patch, * patches/openjdk/8014618-strip_leading_zeros_premastersecret.patch, * patches/openjdk/8014676-javadebugger_space_in_paths.patch, * patches/openjdk/8014745-logger_stack_walk_switch.patch, * patches/openjdk/8014968-OCSP_timeout_default.patch, * patches/security/20130618/7158805-nested_subroutine_rewriting-it6.patch, * patches/security/20130618/8001330-checking_order_improvement-it6.patch, * patches/security/20130618/hs_merge-01.patch, * patches/security/20130618/hs_merge-02.patch, * patches/security/20130618/hs_merge-03.patch, * patches/security/20130618/hs_merge-04.patch, * patches/sparc.patch: Remove unused patches. * Makefile.am: (ICEDTEA_PATCHES): Remove patches which need more testing before release. * patches/ecj/override.patch: Drop recent addition. In accordance with PR1397, we should avoid extending this patch in favour of either not including @Override additions or setting source/target correctly. * patches/security/20130618/7158805-nested_subroutine_rewriting.patch, * patches/security/20130618/8001330-checking_order_improvement.patch: Replace with Chris' patches, regenerated as unified diffs.
author Andrew John Hughes <gnu.andrew@redhat.com>
date Wed, 10 Jul 2013 14:09:21 +0100
parents 08ce3247b5b0
children
line wrap: on
line source

# HG changeset patch
# User chrisphi
# Date 1373378000 -3600
# Node ID d913c85a5297ea80a71b2f6a1174237cb2fbbbad
# Parent  2df643057b3d5f75d287a352cadf6fc0501a1682
8001330: Improve on checking order
8011896: Add check for invalid offset for new AccessControlContext isAuthorized field

diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
--- openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp
+++ openjdk/hotspot/src/share/vm/classfile/javaClasses.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2559,6 +2559,7 @@
 int java_security_AccessControlContext::_context_offset = 0;
 int java_security_AccessControlContext::_privilegedContext_offset = 0;
 int java_security_AccessControlContext::_isPrivileged_offset = 0;
+int java_security_AccessControlContext::_isAuthorized_offset = -1;
 
 void java_security_AccessControlContext::compute_offsets() {
   assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
@@ -2579,9 +2580,20 @@
     fatal("Invalid layout of java.security.AccessControlContext");
   }
   _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) {
   assert(_isPrivileged_offset != 0, "offsets should have been initialized");
   // Ensure klass is initialized
@@ -2592,6 +2604,8 @@
   result->obj_field_put(_context_offset, context());
   result->obj_field_put(_privilegedContext_offset, privileged_context());
   result->bool_field_put(_isPrivileged_offset, isPrivileged);
+  // whitelist AccessControlContexts created by the JVM.
+  result->bool_field_put(_isAuthorized_offset, true);
   return result;
 }
 
@@ -2656,6 +2670,15 @@
 }
 
 
+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_String::value_offset;
 int java_lang_String::offset_offset;
@@ -2712,6 +2735,7 @@
 int java_lang_System::static_in_offset;
 int java_lang_System::static_out_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::methodName_offset;
 int java_lang_StackTraceElement::fileName_offset;
@@ -2866,6 +2890,7 @@
   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_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::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset  * x + header;
@@ -3067,6 +3092,7 @@
   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, err, "Ljava/io/PrintStream;");
+  CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, security, "Ljava/lang/SecurityManager;");
 
   // java.lang.StackTraceElement
 
diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
--- openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp
+++ openjdk/hotspot/src/share/vm/classfile/javaClasses.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1146,11 +1146,14 @@
   static int _context_offset;
   static int _privilegedContext_offset;
   static int _isPrivileged_offset;
+  static int _isAuthorized_offset;
 
   static void compute_offsets();
  public:
   static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS);
 
+  static bool is_authorized(Handle context);
+
   // Debugging/initialization
   friend class JavaClasses;
 };
@@ -1186,13 +1189,15 @@
   enum {
    hc_static_in_offset  = 0,
    hc_static_out_offset = 1,
-   hc_static_err_offset = 2
+   hc_static_err_offset = 2,
+   hc_static_security_offset = 3
   };
 
   static int offset_of_static_fields;
   static int  static_in_offset;
   static int static_out_offset;
   static int static_err_offset;
+  static int static_security_offset;
 
   static void compute_offsets();
 
@@ -1201,6 +1206,8 @@
   static int out_offset_in_bytes();
   static int err_offset_in_bytes();
 
+  static bool has_security_manager();
+
   // Debugging
   friend class JavaClasses;
 };
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
--- openjdk/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ openjdk/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,6 +93,7 @@
   template(java_lang_CharSequence,                    "java/lang/CharSequence")                   \
   template(java_security_AccessControlContext,        "java/security/AccessControlContext")       \
   template(java_security_ProtectionDomain,            "java/security/ProtectionDomain")           \
+  template(impliesCreateAccessControlContext_name,    "impliesCreateAccessControlContext")        \
   template(java_io_OutputStream,                      "java/io/OutputStream")                     \
   template(java_io_Reader,                            "java/io/Reader")                           \
   template(java_io_BufferedReader,                    "java/io/BufferedReader")                   \
@@ -315,6 +316,7 @@
   template(contextClassLoader_name,                   "contextClassLoader")                       \
   template(inheritedAccessControlContext_name,        "inheritedAccessControlContext")            \
   template(isPrivileged_name,                         "isPrivileged")                             \
+  template(isAuthorized_name,                         "isAuthorized")                             \
   template(wait_name,                                 "wait")                                     \
   template(checkPackageAccess_name,                   "checkPackageAccess")                       \
   template(stackSize_name,                            "stackSize")                                \
diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp
--- openjdk/hotspot/src/share/vm/memory/universe.cpp
+++ openjdk/hotspot/src/share/vm/memory/universe.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -143,6 +143,7 @@
 oop Universe::_the_min_jint_string                   = NULL;
 LatestMethodOopCache* Universe::_finalizer_register_cache = NULL;
 LatestMethodOopCache* Universe::_loader_addClass_cache    = NULL;
+LatestMethodOopCache* Universe::_pd_implies_cache         = NULL;
 ActiveMethodOopsCache* Universe::_reflect_invoke_cache    = NULL;
 oop Universe::_out_of_memory_error_java_heap          = NULL;
 oop Universe::_out_of_memory_error_perm_gen           = NULL;
@@ -265,6 +266,7 @@
   f->do_oop((oop*)&_the_min_jint_string);
   _finalizer_register_cache->oops_do(f);
   _loader_addClass_cache->oops_do(f);
+  _pd_implies_cache->oops_do(f);
   _reflect_invoke_cache->oops_do(f);
   f->do_oop((oop*)&_out_of_memory_error_java_heap);
   f->do_oop((oop*)&_out_of_memory_error_perm_gen);
@@ -787,6 +789,7 @@
   // CompactingPermGenGen::initialize_oops() tries to populate them.
   Universe::_finalizer_register_cache = new LatestMethodOopCache();
   Universe::_loader_addClass_cache    = new LatestMethodOopCache();
+  Universe::_pd_implies_cache         = new LatestMethodOopCache();
   Universe::_reflect_invoke_cache     = new ActiveMethodOopsCache();
 
   if (UseSharedSpaces) {
@@ -1137,6 +1140,23 @@
   Universe::_loader_addClass_cache->init(
     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
   // JVM.cpp. If we clean up the StrictMath code above we may want to find
   // a better solution for this as well.
@@ -1570,6 +1590,7 @@
 
 
 methodOop LatestMethodOopCache::get_methodOop() {
+  if (klass() == NULL) return NULL;
   instanceKlass* ik = instanceKlass::cast(klass());
   methodOop m = ik->method_with_idnum(method_idnum());
   assert(m != NULL, "sanity check");
diff --git a/src/share/vm/memory/universe.hpp b/src/share/vm/memory/universe.hpp
--- openjdk/hotspot/src/share/vm/memory/universe.hpp
+++ openjdk/hotspot/src/share/vm/memory/universe.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -179,6 +179,7 @@
   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* _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 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)
@@ -322,6 +323,7 @@
   static oop          the_min_jint_string()          { return _the_min_jint_string;          }
   static methodOop    finalizer_register_method()     { return _finalizer_register_cache->get_methodOop(); }
   static methodOop    loader_addClass_method()        { return _loader_addClass_cache->get_methodOop(); }
+  static methodOop protection_domain_implies_method() { return _pd_implies_cache->get_methodOop(); }
   static ActiveMethodOopsCache* reflect_invoke_cache() { return _reflect_invoke_cache; }
   static oop          null_ptr_exception_instance()   { return _null_ptr_exception_instance;   }
   static oop          arithmetic_exception_instance() { return _arithmetic_exception_instance; }
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
--- openjdk/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ openjdk/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -1992,6 +1992,11 @@
   }
 }
 
+address instanceKlass::static_field_addr(int offset) {
+  return (address)(offset + instanceKlass::offset_of_static_fields() + (intptr_t)java_mirror());
+}
+
+
 const char* instanceKlass::signature_name() const {
   const char* src = (const char*) (name()->as_C_string());
   const int src_length = (int)strlen(src);
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
--- openjdk/hotspot/src/share/vm/oops/instanceKlass.hpp
+++ openjdk/hotspot/src/share/vm/oops/instanceKlass.hpp
@@ -675,6 +675,8 @@
 
   intptr_t* end_of_itable() const          { return start_of_itable() + itable_length(); }
 
+  address static_field_addr(int offset);
+
   int offset_of_static_fields() const {
     return (intptr_t)start_of_static_fields() - (intptr_t)as_klassOop();
   }
diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp
--- openjdk/hotspot/src/share/vm/prims/jvm.cpp
+++ openjdk/hotspot/src/share/vm/prims/jvm.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1101,6 +1101,56 @@
   }
 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) {
+  instanceKlassHandle pd_klass (THREAD, 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))
   JVMWrapper("JVM_DoPrivileged");
@@ -1109,8 +1159,29 @@
     THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), "Null action");
   }
 
-  // Stack allocated list of privileged stack elements
-  PrivilegedElement pi;
+  // Compute the frame initiating the do privileged operation and setup the privileged stack
+  vframeStream vfst(thread);
+  vfst.security_get_caller_frame(1);
+
+  if (vfst.at_end()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), "no caller?");
+  }
+
+  methodOop 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()"
   Handle object (THREAD, JNIHandles::resolve(action));
@@ -1124,12 +1195,10 @@
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method");
   }
 
-  // Compute the frame initiating the do privileged operation and setup the privileged stack
-  vframeStream vfst(thread);
-  vfst.security_get_caller_frame(1);
-
+  // Stack allocated list of privileged stack elements
+  PrivilegedElement pi;
   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);
   }