Mercurial > hg > release > icedtea7-forest-2.3 > hotspot
changeset 3810:e565780c14d2
Merge
author | coffeys |
---|---|
date | Fri, 05 Apr 2013 21:33:44 +0100 |
parents | 1d448101a555 (diff) c5e4585a045f (current diff) |
children | e22194a44dc9 |
files | .hgtags |
diffstat | 13 files changed, 251 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Apr 05 12:48:45 2013 -0700 +++ b/.hgtags Fri Apr 05 21:33:44 2013 +0100 @@ -384,3 +384,7 @@ d4a4c2bd389abcd80c25d20e0ffb7d5cee356715 jdk7u21-b10 d07dafb51e1d75f110a3c506c250d995235acca6 jdk7u21-b11 a977dedec81c346247631ead6f3364c76949d67a jdk7u21-b30 +bf2d84c5103d98db1697b50071a649ea23c4e33d jdk7u25-b01 +07119340f80f77dfcb03fa568641e80b43d4be74 jdk7u25-b02 +655bea6843fb7beabd8d9eeda59572c0c7055b85 jdk7u25-b03 +96a4e612195c0d753be24cf38fea0ee8ce30edcf jdk7u25-b04
--- a/src/share/vm/classfile/javaClasses.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -2757,6 +2757,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"); @@ -2777,9 +2778,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 @@ -2790,6 +2802,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; } @@ -2870,6 +2884,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_Class::_klass_offset; int java_lang_Class::_array_klass_offset; @@ -2923,6 +2946,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; @@ -3064,6 +3088,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; @@ -3266,6 +3291,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
--- a/src/share/vm/classfile/javaClasses.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -1249,11 +1249,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; }; @@ -1296,18 +1299,22 @@ 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 static_in_offset; static int static_out_offset; static int static_err_offset; + static int static_security_offset; public: static int in_offset_in_bytes(); static int out_offset_in_bytes(); static int err_offset_in_bytes(); + static bool has_security_manager(); + // Debugging friend class JavaClasses; };
--- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -91,6 +91,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") \ @@ -324,6 +325,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") \
--- a/src/share/vm/memory/allocation.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/allocation.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -210,7 +210,7 @@ ChunkPool(size_t size) : _size(size) { _first = NULL; _num_chunks = _num_used = 0; } // Allocate a new chunk from the pool (might expand the pool) - void* allocate(size_t bytes) { + void* allocate(size_t bytes, AllocFailType alloc_failmode) { assert(bytes == _size, "bad size"); void* p = NULL; { ThreadCritical tc; @@ -218,9 +218,9 @@ p = get_first(); if (p == NULL) p = os::malloc(bytes); } - if (p == NULL) + if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { vm_exit_out_of_memory(bytes, "ChunkPool::allocate"); - + } return p; } @@ -311,7 +311,7 @@ //-------------------------------------------------------------------------------------- // Chunk implementation -void* Chunk::operator new(size_t requested_size, size_t length) { +void* Chunk::operator new(size_t requested_size, AllocFailType alloc_failmode, size_t length) { // requested_size is equal to sizeof(Chunk) but in order for the arena // allocations to come out aligned as expected the size must be aligned // to expected arean alignment. @@ -319,13 +319,14 @@ assert(ARENA_ALIGN(requested_size) == aligned_overhead_size(), "Bad alignment"); size_t bytes = ARENA_ALIGN(requested_size) + length; switch (length) { - case Chunk::size: return ChunkPool::large_pool()->allocate(bytes); - case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes); - case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes); + case Chunk::size: return ChunkPool::large_pool()->allocate(bytes, alloc_failmode); + case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes, alloc_failmode); + case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes, alloc_failmode); default: { - void *p = os::malloc(bytes); - if (p == NULL) + void* p = os::malloc(bytes); + if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { vm_exit_out_of_memory(bytes, "Chunk::new"); + } return p; } } @@ -378,14 +379,14 @@ Arena::Arena(size_t init_size) { size_t round_size = (sizeof (char *)) - 1; init_size = (init_size+round_size) & ~round_size; - _first = _chunk = new (init_size) Chunk(init_size); + _first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); set_size_in_bytes(init_size); } Arena::Arena() { - _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size); + _first = _chunk = new (AllocFailStrategy::EXIT_OOM, Chunk::init_size) Chunk(Chunk::init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); set_size_in_bytes(Chunk::init_size); @@ -438,15 +439,15 @@ } // Grow a new Chunk -void* Arena::grow( size_t x ) { +void* Arena::grow(size_t x, AllocFailType alloc_failmode) { // Get minimal required size. Either real big, or even bigger for giant objs size_t len = MAX2(x, (size_t) Chunk::size); Chunk *k = _chunk; // Get filled-up chunk address - _chunk = new (len) Chunk(len); + _chunk = new (alloc_failmode, len) Chunk(len); if (_chunk == NULL) { - signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); + return NULL; } if (k) k->set_next(_chunk); // Append new chunk to end of linked list @@ -462,13 +463,16 @@ // Reallocate storage in Arena. -void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size) { +void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFailType alloc_failmode) { assert(new_size >= 0, "bad size"); if (new_size == 0) return NULL; #ifdef ASSERT if (UseMallocOnly) { // always allocate a new object (otherwise we'll free this one twice) - char* copy = (char*)Amalloc(new_size); + char* copy = (char*)Amalloc(new_size, alloc_failmode); + if (copy == NULL) { + return NULL; + } size_t n = MIN2(old_size, new_size); if (n > 0) memcpy(copy, old_ptr, n); Afree(old_ptr,old_size); // Mostly done to keep stats accurate @@ -494,7 +498,10 @@ } // Oops, got to relocate guts - void *new_ptr = Amalloc(new_size); + void *new_ptr = Amalloc(new_size, alloc_failmode); + if (new_ptr == NULL) { + return NULL; + } memcpy( new_ptr, c_old, old_size ); Afree(c_old,old_size); // Mostly done to keep stats accurate return new_ptr;
--- a/src/share/vm/memory/allocation.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/allocation.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -40,6 +40,12 @@ #define ARENA_ALIGN_MASK (~((size_t)ARENA_ALIGN_M1)) #define ARENA_ALIGN(x) ((((size_t)(x)) + ARENA_ALIGN_M1) & ARENA_ALIGN_MASK) +class AllocFailStrategy { +public: + enum AllocFailEnum { EXIT_OOM, RETURN_NULL }; +}; +typedef AllocFailStrategy::AllocFailEnum AllocFailType; + // All classes in the virtual machine must be subclassed // by one of the following allocation classes: // @@ -157,7 +163,7 @@ Chunk* _next; // Next Chunk in list const size_t _len; // Size of this Chunk public: - void* operator new(size_t size, size_t length); + void* operator new(size_t size, AllocFailType alloc_failmode, size_t length); void operator delete(void* p); Chunk(size_t length); @@ -207,7 +213,8 @@ Chunk *_first; // First chunk Chunk *_chunk; // current chunk char *_hwm, *_max; // High water mark and max in current chunk - void* grow(size_t x); // Get a new Chunk of at least size x + // Get a new Chunk of at least size x + void* grow(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); NOT_PRODUCT(size_t _size_in_bytes;) // Size of arena (used for memory usage tracing) NOT_PRODUCT(static julong _bytes_allocated;) // total #bytes allocated since start friend class AllocStats; @@ -217,10 +224,15 @@ void signal_out_of_memory(size_t request, const char* whence) const; - void check_for_overflow(size_t request, const char* whence) const { + bool check_for_overflow(size_t request, const char* whence, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) const { if (UINTPTR_MAX - request < (uintptr_t)_hwm) { + if (alloc_failmode == AllocFailStrategy::RETURN_NULL) { + return false; + } signal_out_of_memory(request, whence); } + return true; } public: @@ -232,14 +244,15 @@ char* hwm() const { return _hwm; } // Fast allocate in the arena. Common case is: pointer test + increment. - void* Amalloc(size_t x) { + void* Amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2"); x = ARENA_ALIGN(x); debug_only(if (UseMallocOnly) return malloc(x);) - check_for_overflow(x, "Arena::Amalloc"); + if (!check_for_overflow(x, "Arena::Amalloc", alloc_failmode)) + return NULL; NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { - return grow(x); + return grow(x, alloc_failmode); } else { char *old = _hwm; _hwm += x; @@ -247,13 +260,14 @@ } } // Further assume size is padded out to words - void *Amalloc_4(size_t x) { + void *Amalloc_4(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); debug_only(if (UseMallocOnly) return malloc(x);) - check_for_overflow(x, "Arena::Amalloc_4"); + if (!check_for_overflow(x, "Arena::Amalloc_4", alloc_failmode)) + return NULL; NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { - return grow(x); + return grow(x, alloc_failmode); } else { char *old = _hwm; _hwm += x; @@ -263,7 +277,7 @@ // Allocate with 'double' alignment. It is 8 bytes on sparc. // In other cases Amalloc_D() should be the same as Amalloc_4(). - void* Amalloc_D(size_t x) { + void* Amalloc_D(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); debug_only(if (UseMallocOnly) return malloc(x);) #if defined(SPARC) && !defined(_LP64) @@ -271,10 +285,11 @@ size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm; x += delta; #endif - check_for_overflow(x, "Arena::Amalloc_D"); + if (!check_for_overflow(x, "Arena::Amalloc_D", alloc_failmode)) + return NULL; NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { - return grow(x); // grow() returns a result aligned >= 8 bytes. + return grow(x, alloc_failmode); // grow() returns a result aligned >= 8 bytes. } else { char *old = _hwm; _hwm += x; @@ -294,7 +309,8 @@ if (((char*)ptr) + size == _hwm) _hwm = (char*)ptr; } - void *Arealloc( void *old_ptr, size_t old_size, size_t new_size ); + void *Arealloc( void *old_ptr, size_t old_size, size_t new_size, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); // Move contents of this arena into an empty arena Arena *move_contents(Arena *empty_arena); @@ -336,9 +352,12 @@ //%note allocation_1 -extern char* resource_allocate_bytes(size_t size); -extern char* resource_allocate_bytes(Thread* thread, size_t size); -extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size); +extern char* resource_allocate_bytes(size_t size, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); +extern char* resource_allocate_bytes(Thread* thread, size_t size, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); +extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); extern void resource_free_bytes( char *old, size_t size ); //---------------------------------------------------------------------- @@ -384,6 +403,13 @@ DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) return res; } + + void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { + address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL); + DEBUG_ONLY(if (res != NULL) set_allocation_type(res, RESOURCE_AREA);) + return res; + } + void operator delete(void* p); }; @@ -394,6 +420,9 @@ #define NEW_RESOURCE_ARRAY(type, size)\ (type*) resource_allocate_bytes((size) * sizeof(type)) +#define NEW_RESOURCE_ARRAY_RETURN_NULL(type, size)\ + (type*) resource_allocate_bytes((size) * sizeof(type), AllocFailStrategy::RETURN_NULL) + #define NEW_RESOURCE_ARRAY_IN_THREAD(thread, type, size)\ (type*) resource_allocate_bytes(thread, (size) * sizeof(type))
--- a/src/share/vm/memory/allocation.inline.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/allocation.inline.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -48,25 +48,29 @@ #endif // allocate using malloc; will fail if no memory available -inline char* AllocateHeap(size_t size, const char* name = NULL) { +inline char* AllocateHeap(size_t size, const char* name = NULL, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { char* p = (char*) os::malloc(size); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, name, p); #else Unused_Variable(name); #endif - if (p == NULL) vm_exit_out_of_memory(size, name); + if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) + vm_exit_out_of_memory(size, "AllocateHeap"); return p; } -inline char* ReallocateHeap(char *old, size_t size, const char* name = NULL) { +inline char* ReallocateHeap(char *old, size_t size, const char* name = NULL, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { char* p = (char*) os::realloc(old,size); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, name, p); #else Unused_Variable(name); #endif - if (p == NULL) vm_exit_out_of_memory(size, name); + if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) + vm_exit_out_of_memory(size, "ReallocateHeap"); return p; }
--- a/src/share/vm/memory/resourceArea.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/resourceArea.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -45,15 +45,16 @@ // The following routines are declared in allocation.hpp and used everywhere: // Allocation in thread-local resource area -extern char* resource_allocate_bytes(size_t size) { - return Thread::current()->resource_area()->allocate_bytes(size); +extern char* resource_allocate_bytes(size_t size, AllocFailType alloc_failmode) { + return Thread::current()->resource_area()->allocate_bytes(size, alloc_failmode); } -extern char* resource_allocate_bytes(Thread* thread, size_t size) { - return thread->resource_area()->allocate_bytes(size); +extern char* resource_allocate_bytes(Thread* thread, size_t size, AllocFailType alloc_failmode) { + return thread->resource_area()->allocate_bytes(size, alloc_failmode); } -extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size){ - return (char*)Thread::current()->resource_area()->Arealloc(old, old_size, new_size); +extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size, + AllocFailType alloc_failmode){ + return (char*)Thread::current()->resource_area()->Arealloc(old, old_size, new_size, alloc_failmode); } extern void resource_free_bytes( char *old, size_t size ) {
--- a/src/share/vm/memory/resourceArea.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/resourceArea.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -68,7 +68,7 @@ debug_only(_nesting = 0;); } - char* allocate_bytes(size_t size) { + char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { #ifdef ASSERT if (_nesting < 1 && !_warned++) fatal("memory leak: allocating without ResourceMark"); @@ -78,7 +78,7 @@ return (*save = (char*)os::malloc(size)); } #endif - return (char*)Amalloc(size); + return (char*)Amalloc(size, alloc_failmode); } debug_only(int nesting() const { return _nesting; });
--- a/src/share/vm/memory/universe.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/universe.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -145,6 +145,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; @@ -264,6 +265,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); @@ -788,6 +790,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) { @@ -1141,6 +1144,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. @@ -1621,6 +1641,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");
--- a/src/share/vm/memory/universe.hpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/memory/universe.hpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -186,6 +186,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) @@ -325,6 +326,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; }
--- a/src/share/vm/oops/generateOopMap.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/oops/generateOopMap.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -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 @@ -643,11 +643,20 @@ // CellType handling methods // +// Allocate memory and throw LinkageError if failure. +#define ALLOC_RESOURCE_ARRAY(var, type, count) \ + var = NEW_RESOURCE_ARRAY_RETURN_NULL(type, count); \ + if (var == NULL) { \ + report_error("Cannot reserve enough memory to analyze this method"); \ + return; \ + } + void GenerateOopMap::init_state() { _state_len = _max_locals + _max_stack + _max_monitors; - _state = NEW_RESOURCE_ARRAY(CellTypeState, _state_len); + ALLOC_RESOURCE_ARRAY(_state, CellTypeState, _state_len); memset(_state, 0, _state_len * sizeof(CellTypeState)); - _state_vec_buf = NEW_RESOURCE_ARRAY(char, MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */); + int count = MAX3(_max_locals, _max_stack, _max_monitors) + 1/*for null terminator char */; + ALLOC_RESOURCE_ARRAY(_state_vec_buf, char, count) } void GenerateOopMap::make_context_uninitialized() { @@ -905,7 +914,7 @@ // But cumbersome since we don't know the stack heights yet. (Nor the // monitor stack heights...) - _basic_blocks = NEW_RESOURCE_ARRAY(BasicBlock, _bb_count); + ALLOC_RESOURCE_ARRAY(_basic_blocks, BasicBlock, _bb_count); // Make a pass through the bytecodes. Count the number of monitorenters. // This can be used an upper bound on the monitor stack depth in programs @@ -976,8 +985,8 @@ return; } - CellTypeState *basicBlockState = - NEW_RESOURCE_ARRAY(CellTypeState, bbNo * _state_len); + CellTypeState *basicBlockState; + ALLOC_RESOURCE_ARRAY(basicBlockState, CellTypeState, bbNo * _state_len); memset(basicBlockState, 0, bbNo * _state_len * sizeof(CellTypeState)); // Make a pass over the basicblocks and assign their state vectors.
--- a/src/share/vm/prims/jvm.cpp Fri Apr 05 12:48:45 2013 -0700 +++ b/src/share/vm/prims/jvm.cpp Fri Apr 05 21:33:44 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, 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 @@ -1107,6 +1107,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"); @@ -1115,8 +1165,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)); @@ -1130,12 +1201,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); }