133 if (class_name == vmSymbols::java_lang_ClassLoader()) { 134 return true; 135 } 136 137 if (SystemDictionary::ClassLoader_klass_loaded()) { 138 const Klass* const super_klass = parser.super_klass(); 139 if (super_klass != NULL) { 140 if (super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass())) { 141 return true; 142 } 143 } 144 } 145 return false; 146 } 147 148 // called to verify that k is a member of this nest 149 bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { 150 if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) { 151 if (log_is_enabled(Trace, class, nestmates)) { 152 ResourceMark rm(THREAD); 153 log_trace(class, nestmates)("Checking nest membership of %s in non-nest-host class %s", 154 k->name()->as_C_string(), this->name()->as_C_string()); 155 } 156 return false; 157 } 158 159 if (log_is_enabled(Trace, class, nestmates)) { 160 ResourceMark rm(THREAD); 161 log_trace(class, nestmates)("Checking nest membership of %s in %s", 162 k->name()->as_C_string(), this->name()->as_C_string()); 163 } 164 165 // Check names first and if they match then check actual klass. This avoids 166 // resolving anything unnecessarily. 167 for (int i = 0; i < _nest_members->length(); i++) { 168 int cp_index = _nest_members->at(i); 169 Symbol* name = _constants->klass_name_at(cp_index); 170 if (name == k->name()) { 171 log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index); 172 173 // names match so check actual klass - this may trigger class loading if 174 // it doesn't match (but that should be impossible) 175 Klass* k2 = _constants->klass_at(cp_index, CHECK_false); 176 if (k2 == k) { 177 log_trace(class, nestmates)("- klass is nestmate member"); 178 return true; 179 } 180 else { 181 // same name but different klass! 182 log_trace(class, nestmates)(" - klass comparison failed!"); 183 } 184 } 185 } 186 log_trace(class, nestmates)("- klass is NOT nestmate member!"); 187 return false; 188 } 189 190 // Return nest-host class, resolving, validating and saving it if needed 191 InstanceKlass* InstanceKlass::nest_host(TRAPS) { 192 InstanceKlass* nest_host_k = _nest_host; 193 if (nest_host_k == NULL) { 194 // need to resolve and save our nest-host class. This could be attempted 195 // concurrently but as the result is idempotent and we don't use the class 196 // then we do not need any synchronization beyond what is implicitly used 197 // during class loading. 198 if (_nest_host_index != 0) { // we have a real nest_host 199 if (log_is_enabled(Trace, class, nestmates)) { 200 ResourceMark rm(THREAD); 201 log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s", 202 this->name()->as_C_string(), 203 _constants->klass_name_at(_nest_host_index)->as_C_string()); 204 } 205 206 Klass* k = _constants->klass_at(_nest_host_index, CHECK_NULL); 207 208 if (log_is_enabled(Trace, class, nestmates)) { 209 ResourceMark rm(THREAD); 210 log_trace(class, nestmates)("Resolved nest-host of %s to %s", 211 this->name()->as_C_string(), k->name()->as_C_string()); 212 } 213 214 if (!k->is_instance_klass()) { 215 ResourceMark rm(THREAD); 216 Exceptions::fthrow( 217 THREAD_AND_LOCATION, 218 vmSymbols::java_lang_IncompatibleClassChangeError(), 219 "class %s has non-instance class %s as nest-host", 220 this->external_name(), 221 k->external_name() 222 ); 223 return NULL; 224 } 225 226 nest_host_k = InstanceKlass::cast(k); 227 228 bool is_member = nest_host_k->has_nest_member(this, CHECK_NULL); 229 if (!is_member) { 230 // this_k and nest_host disagree about nest membership 231 ResourceMark rm(THREAD); 232 Exceptions::fthrow( 233 THREAD_AND_LOCATION, 234 vmSymbols::java_lang_IncompatibleClassChangeError(), 235 "Type %s is not a nest member of %s", 236 this->external_name(), 237 nest_host_k->external_name() 238 ); 239 return NULL; 240 } 241 242 if (!is_same_class_package(nest_host_k)) { 243 ResourceMark rm(THREAD); 244 Exceptions::fthrow( 245 THREAD_AND_LOCATION, 246 vmSymbols::java_lang_IncompatibleClassChangeError(), 247 "Class %s is in a different package to its nest-host class %s", 248 this->external_name(), 249 nest_host_k->external_name() 250 ); 251 return NULL; 252 } 253 } 254 else { 255 if (log_is_enabled(Trace, class, nestmates)) { 256 ResourceMark rm(THREAD); 257 log_trace(class, nestmates)("Class %s is not part of a nest: setting nest-host to self", 258 this->name()->as_C_string()); 259 } 260 nest_host_k = const_cast<InstanceKlass*>(this); 261 } 262 } 263 // save resolved nest-host value 264 _nest_host = nest_host_k; 265 266 return nest_host_k; 267 } 268 269 // check if 'this' and k are nestmates (same nest_host), or k is our nest_host, 270 // or we are k's nest_host - all of which is covered by comparing the two 271 // resolved_nest_hosts 272 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) { 273 274 // If not actually nestmates, then both nest-host classes may have to loaded 275 // and the nest membership of each class validated. 276 InstanceKlass* cur_top = nest_host(CHECK_false); 277 Klass* k_nest_host = k->nest_host(CHECK_false); 278 279 bool access = (cur_top == k_nest_host); 280 281 if (log_is_enabled(Trace, class, nestmates)) { 282 ResourceMark rm(THREAD); 283 log_trace(class, nestmates)("Class %s does %shave nestmate accesss to %s", 284 this->name()->as_C_string(), 285 access ? "" : "NOT ", 286 k->name()->as_C_string()); 287 } 288 289 return access; 290 } 291 292 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) { 293 const int size = InstanceKlass::size(parser.vtable_size(), 294 parser.itable_size(), 295 nonstatic_oop_map_size(parser.total_oop_map_count()), 296 parser.is_interface(), 297 parser.is_anonymous(), 298 should_store_fingerprint()); 299 300 const Symbol* const class_name = parser.class_name(); 301 assert(class_name != NULL, "invariant"); 302 ClassLoaderData* loader_data = parser.loader_data(); 303 assert(loader_data != NULL, "invariant"); 304 305 InstanceKlass* ik; 306 | 133 if (class_name == vmSymbols::java_lang_ClassLoader()) { 134 return true; 135 } 136 137 if (SystemDictionary::ClassLoader_klass_loaded()) { 138 const Klass* const super_klass = parser.super_klass(); 139 if (super_klass != NULL) { 140 if (super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass())) { 141 return true; 142 } 143 } 144 } 145 return false; 146 } 147 148 // called to verify that k is a member of this nest 149 bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const { 150 if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) { 151 if (log_is_enabled(Trace, class, nestmates)) { 152 ResourceMark rm(THREAD); 153 log_trace(class, nestmates)("Checked nest membership of %s in non-nest-host class %s", 154 k->external_name(), this->external_name()); 155 } 156 return false; 157 } 158 159 if (log_is_enabled(Trace, class, nestmates)) { 160 ResourceMark rm(THREAD); 161 log_trace(class, nestmates)("Checking nest membership of %s in %s", 162 k->external_name(), this->external_name()); 163 } 164 165 // Check names first and if they match then check actual klass. This avoids 166 // resolving anything unnecessarily. 167 for (int i = 0; i < _nest_members->length(); i++) { 168 int cp_index = _nest_members->at(i); 169 Symbol* name = _constants->klass_name_at(cp_index); 170 if (name == k->name()) { 171 log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index); 172 173 // names match so check actual klass - this may trigger class loading if 174 // it doesn't match (but that should be impossible) 175 Klass* k2 = _constants->klass_at(cp_index, CHECK_false); 176 if (k2 == k) { 177 log_trace(class, nestmates)("- class is listed as a nest member"); 178 return true; 179 } 180 else { 181 // same name but different klass! 182 log_trace(class, nestmates)(" - klass comparison failed!"); 183 } 184 } 185 } 186 log_trace(class, nestmates)("- class is NOT a nest member!"); 187 return false; 188 } 189 190 // Return nest-host class, resolving, validating and saving it if needed. 191 // In cases where this is called from a thread that can not do classloading 192 // (such as a native JIT thread) then we simply return NULL, which in turn 193 // causes the access check to return false. Such code will retry the access 194 // from a more suitable environment later. 195 InstanceKlass* InstanceKlass::nest_host(TRAPS) { 196 InstanceKlass* nest_host_k = _nest_host; 197 if (nest_host_k == NULL) { 198 // need to resolve and save our nest-host class. This could be attempted 199 // concurrently but as the result is idempotent and we don't use the class 200 // then we do not need any synchronization beyond what is implicitly used 201 // during class loading. 202 if (_nest_host_index != 0) { // we have a real nest_host 203 // Before trying to resolve check if we're in a suitable context 204 if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) { 205 if (log_is_enabled(Trace, class, nestmates)) { 206 ResourceMark rm(THREAD); 207 log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread", 208 this->external_name()); 209 } 210 return NULL; 211 } 212 213 if (log_is_enabled(Trace, class, nestmates)) { 214 ResourceMark rm(THREAD); 215 log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s", 216 this->external_name(), 217 _constants->klass_name_at(_nest_host_index)->as_C_string()); 218 } 219 220 Klass* k = _constants->klass_at(_nest_host_index, THREAD); 221 if (HAS_PENDING_EXCEPTION) { 222 Handle exc_h = Handle(THREAD, PENDING_EXCEPTION); 223 if (exc_h->is_a(SystemDictionary::NoClassDefFoundError_klass())) { 224 // throw a new CDNFE with the original as its cause, and a clear msg 225 ResourceMark rm(THREAD); 226 char buf[200]; 227 CLEAR_PENDING_EXCEPTION; 228 jio_snprintf(buf, sizeof(buf), 229 "Unable to load nest-host class of %s", 230 this->external_name()); 231 log_trace(class, nestmates)("%s - NoClassDefFoundError", buf); 232 THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), buf, exc_h); 233 } 234 // other exceptions pass through (OOME, StackOverflowError etc) 235 return NULL; 236 } 237 238 // A valid nest-host is an instance class in the current package that lists this 239 // class as a nest member. If any of these conditions are not met we simply throw 240 // IllegalAccessError, with a suitable message. 241 242 const char* error = NULL; 243 244 // Need to check we have an instance class first 245 if (k->is_instance_klass()) { 246 nest_host_k = InstanceKlass::cast(k); 247 248 // FIXME: an exception from this is perhaps impossible 249 bool is_member = nest_host_k->has_nest_member(this, CHECK_NULL); 250 if (is_member) { 251 // Finally check we're in the same package - as there could be collusion 252 // between untrusted types. 253 if (is_same_class_package(nest_host_k)) { 254 // save resolved nest-host value 255 _nest_host = nest_host_k; 256 257 if (log_is_enabled(Trace, class, nestmates)) { 258 ResourceMark rm(THREAD); 259 log_trace(class, nestmates)("Resolved nest-host of %s to %s", 260 this->external_name(), k->external_name()); 261 } 262 return nest_host_k; 263 } 264 else { 265 error = "types are in different packages"; 266 } 267 } 268 else { 269 error = "current type is not listed as a nest member"; 270 } 271 } 272 else { 273 error = "nest-host is not an instance class!"; 274 } 275 276 if (log_is_enabled(Trace, class, nestmates)) { 277 ResourceMark rm(THREAD); 278 log_trace(class, nestmates)("Type %s is not a nest member of resolved type %s: %s", 279 this->external_name(), 280 k->external_name(), 281 error); 282 } 283 284 ResourceMark rm(THREAD); 285 Exceptions::fthrow(THREAD_AND_LOCATION, 286 vmSymbols::java_lang_IllegalAccessError(), 287 "Type %s is not a nest member of %s: %s", 288 this->external_name(), 289 k->external_name(), 290 error 291 ); 292 return NULL; 293 } 294 else { 295 if (log_is_enabled(Trace, class, nestmates)) { 296 ResourceMark rm(THREAD); 297 log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self", 298 this->external_name()); 299 } 300 // save resolved nest-host value 301 return (_nest_host = this); 302 } 303 } 304 return nest_host_k; 305 } 306 307 // check if 'this' and k are nestmates (same nest_host), or k is our nest_host, 308 // or we are k's nest_host - all of which is covered by comparing the two 309 // resolved_nest_hosts 310 bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) { 311 312 assert(this != k, "this should be handled by higher-level code"); 313 314 // Per the JVMS we first resolve and validate the current class, then 315 // the target class k. Resolution exceptions will be passed on by upper 316 // layers. IllegalAccessErrors from membership validation failures will 317 // also be passed through. 318 319 InstanceKlass* cur_host = nest_host(THREAD); 320 if (cur_host == NULL || HAS_PENDING_EXCEPTION) { 321 return false; 322 } 323 324 Klass* k_nest_host = k->nest_host(THREAD); 325 if (k_nest_host == NULL || HAS_PENDING_EXCEPTION) { 326 return false; 327 } 328 329 bool access = (cur_host == k_nest_host); 330 331 if (log_is_enabled(Trace, class, nestmates)) { 332 ResourceMark rm(THREAD); 333 log_trace(class, nestmates)("Class %s does %shave nestmate accesss to %s", 334 this->external_name(), 335 access ? "" : "NOT ", 336 k->external_name()); 337 } 338 339 return access; 340 } 341 342 InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) { 343 const int size = InstanceKlass::size(parser.vtable_size(), 344 parser.itable_size(), 345 nonstatic_oop_map_size(parser.total_oop_map_count()), 346 parser.is_interface(), 347 parser.is_anonymous(), 348 should_store_fingerprint()); 349 350 const Symbol* const class_name = parser.class_name(); 351 assert(class_name != NULL, "invariant"); 352 ClassLoaderData* loader_data = parser.loader_data(); 353 assert(loader_data != NULL, "invariant"); 354 355 InstanceKlass* ik; 356 |