Mercurial > hg > truffle
comparison src/os/bsd/vm/perfMemory_bsd.cpp @ 21818:5ca2ea5eeff0
Merge
author | asaha |
---|---|
date | Fri, 31 Oct 2014 17:09:14 -0700 |
parents | 833b0f92429a 60a992c821f8 |
children | fb677d6aebea |
comparison
equal
deleted
inserted
replaced
21817:12478c5eb000 | 21818:5ca2ea5eeff0 |
---|---|
195 // successful conversion, return the pid | 195 // successful conversion, return the pid |
196 return pid; | 196 return pid; |
197 } | 197 } |
198 | 198 |
199 | 199 |
200 // check if the given path is considered a secure directory for | 200 // Check if the given statbuf is considered a secure directory for |
201 // the backing store files. Returns true if the directory is considered | |
202 // a secure location. Returns false if the statbuf is a symbolic link or | |
203 // if an error occurred. | |
204 // | |
205 static bool is_statbuf_secure(struct stat *statp) { | |
206 if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { | |
207 // The path represents a link or some non-directory file type, | |
208 // which is not what we expected. Declare it insecure. | |
209 // | |
210 return false; | |
211 } | |
212 // We have an existing directory, check if the permissions are safe. | |
213 // | |
214 if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { | |
215 // The directory is open for writing and could be subjected | |
216 // to a symlink or a hard link attack. Declare it insecure. | |
217 // | |
218 return false; | |
219 } | |
220 // See if the uid of the directory matches the effective uid of the process. | |
221 // | |
222 if (statp->st_uid != geteuid()) { | |
223 // The directory was not created by this user, declare it insecure. | |
224 // | |
225 return false; | |
226 } | |
227 return true; | |
228 } | |
229 | |
230 | |
231 // Check if the given path is considered a secure directory for | |
201 // the backing store files. Returns true if the directory exists | 232 // the backing store files. Returns true if the directory exists |
202 // and is considered a secure location. Returns false if the path | 233 // and is considered a secure location. Returns false if the path |
203 // is a symbolic link or if an error occurred. | 234 // is a symbolic link or if an error occurred. |
204 // | 235 // |
205 static bool is_directory_secure(const char* path) { | 236 static bool is_directory_secure(const char* path) { |
209 RESTARTABLE(::lstat(path, &statbuf), result); | 240 RESTARTABLE(::lstat(path, &statbuf), result); |
210 if (result == OS_ERR) { | 241 if (result == OS_ERR) { |
211 return false; | 242 return false; |
212 } | 243 } |
213 | 244 |
214 // the path exists, now check it's mode | 245 // The path exists, see if it is secure. |
215 if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { | 246 return is_statbuf_secure(&statbuf); |
216 // the path represents a link or some non-directory file type, | 247 } |
217 // which is not what we expected. declare it insecure. | 248 |
218 // | 249 |
250 // Check if the given directory file descriptor is considered a secure | |
251 // directory for the backing store files. Returns true if the directory | |
252 // exists and is considered a secure location. Returns false if the path | |
253 // is a symbolic link or if an error occurred. | |
254 // | |
255 static bool is_dirfd_secure(int dir_fd) { | |
256 struct stat statbuf; | |
257 int result = 0; | |
258 | |
259 RESTARTABLE(::fstat(dir_fd, &statbuf), result); | |
260 if (result == OS_ERR) { | |
219 return false; | 261 return false; |
220 } | 262 } |
221 else { | 263 |
222 // we have an existing directory, check if the permissions are safe. | 264 // The path exists, now check its mode. |
223 // | 265 return is_statbuf_secure(&statbuf); |
224 if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { | 266 } |
225 // the directory is open for writing and could be subjected | 267 |
226 // to a symlnk attack. declare it insecure. | 268 |
227 // | 269 // Check to make sure fd1 and fd2 are referencing the same file system object. |
228 return false; | 270 // |
229 } | 271 static bool is_same_fsobject(int fd1, int fd2) { |
272 struct stat statbuf1; | |
273 struct stat statbuf2; | |
274 int result = 0; | |
275 | |
276 RESTARTABLE(::fstat(fd1, &statbuf1), result); | |
277 if (result == OS_ERR) { | |
278 return false; | |
279 } | |
280 RESTARTABLE(::fstat(fd2, &statbuf2), result); | |
281 if (result == OS_ERR) { | |
282 return false; | |
283 } | |
284 | |
285 if ((statbuf1.st_ino == statbuf2.st_ino) && | |
286 (statbuf1.st_dev == statbuf2.st_dev)) { | |
287 return true; | |
288 } else { | |
289 return false; | |
290 } | |
291 } | |
292 | |
293 | |
294 // Open the directory of the given path and validate it. | |
295 // Return a DIR * of the open directory. | |
296 // | |
297 static DIR *open_directory_secure(const char* dirname) { | |
298 // Open the directory using open() so that it can be verified | |
299 // to be secure by calling is_dirfd_secure(), opendir() and then check | |
300 // to see if they are the same file system object. This method does not | |
301 // introduce a window of opportunity for the directory to be attacked that | |
302 // calling opendir() and is_directory_secure() does. | |
303 int result; | |
304 DIR *dirp = NULL; | |
305 RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); | |
306 if (result == OS_ERR) { | |
307 // Directory doesn't exist or is a symlink, so there is nothing to cleanup. | |
308 if (PrintMiscellaneous && Verbose) { | |
309 if (errno == ELOOP) { | |
310 warning("directory %s is a symlink and is not secure\n", dirname); | |
311 } else { | |
312 warning("could not open directory %s: %s\n", dirname, strerror(errno)); | |
313 } | |
314 } | |
315 return dirp; | |
316 } | |
317 int fd = result; | |
318 | |
319 // Determine if the open directory is secure. | |
320 if (!is_dirfd_secure(fd)) { | |
321 // The directory is not a secure directory. | |
322 os::close(fd); | |
323 return dirp; | |
324 } | |
325 | |
326 // Open the directory. | |
327 dirp = ::opendir(dirname); | |
328 if (dirp == NULL) { | |
329 // The directory doesn't exist, close fd and return. | |
330 os::close(fd); | |
331 return dirp; | |
332 } | |
333 | |
334 // Check to make sure fd and dirp are referencing the same file system object. | |
335 if (!is_same_fsobject(fd, dirfd(dirp))) { | |
336 // The directory is not secure. | |
337 os::close(fd); | |
338 os::closedir(dirp); | |
339 dirp = NULL; | |
340 return dirp; | |
341 } | |
342 | |
343 // Close initial open now that we know directory is secure | |
344 os::close(fd); | |
345 | |
346 return dirp; | |
347 } | |
348 | |
349 // NOTE: The code below uses fchdir(), open() and unlink() because | |
350 // fdopendir(), openat() and unlinkat() are not supported on all | |
351 // versions. Once the support for fdopendir(), openat() and unlinkat() | |
352 // is available on all supported versions the code can be changed | |
353 // to use these functions. | |
354 | |
355 // Open the directory of the given path, validate it and set the | |
356 // current working directory to it. | |
357 // Return a DIR * of the open directory and the saved cwd fd. | |
358 // | |
359 static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { | |
360 | |
361 // Open the directory. | |
362 DIR* dirp = open_directory_secure(dirname); | |
363 if (dirp == NULL) { | |
364 // Directory doesn't exist or is insecure, so there is nothing to cleanup. | |
365 return dirp; | |
366 } | |
367 int fd = dirfd(dirp); | |
368 | |
369 // Open a fd to the cwd and save it off. | |
370 int result; | |
371 RESTARTABLE(::open(".", O_RDONLY), result); | |
372 if (result == OS_ERR) { | |
373 *saved_cwd_fd = -1; | |
374 } else { | |
375 *saved_cwd_fd = result; | |
376 } | |
377 | |
378 // Set the current directory to dirname by using the fd of the directory. | |
379 result = fchdir(fd); | |
380 | |
381 return dirp; | |
382 } | |
383 | |
384 // Close the directory and restore the current working directory. | |
385 // | |
386 static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { | |
387 | |
388 int result; | |
389 // If we have a saved cwd change back to it and close the fd. | |
390 if (saved_cwd_fd != -1) { | |
391 result = fchdir(saved_cwd_fd); | |
392 ::close(saved_cwd_fd); | |
393 } | |
394 | |
395 // Close the directory. | |
396 os::closedir(dirp); | |
397 } | |
398 | |
399 // Check if the given file descriptor is considered a secure. | |
400 // | |
401 static bool is_file_secure(int fd, const char *filename) { | |
402 | |
403 int result; | |
404 struct stat statbuf; | |
405 | |
406 // Determine if the file is secure. | |
407 RESTARTABLE(::fstat(fd, &statbuf), result); | |
408 if (result == OS_ERR) { | |
409 if (PrintMiscellaneous && Verbose) { | |
410 warning("fstat failed on %s: %s\n", filename, strerror(errno)); | |
411 } | |
412 return false; | |
413 } | |
414 if (statbuf.st_nlink > 1) { | |
415 // A file with multiple links is not expected. | |
416 if (PrintMiscellaneous && Verbose) { | |
417 warning("file %s has multiple links\n", filename); | |
418 } | |
419 return false; | |
230 } | 420 } |
231 return true; | 421 return true; |
232 } | 422 } |
233 | |
234 | 423 |
235 // return the user name for the given user id | 424 // return the user name for the given user id |
236 // | 425 // |
237 // the caller is expected to free the allocated memory. | 426 // the caller is expected to free the allocated memory. |
238 // | 427 // |
315 char* oldest_user = NULL; | 504 char* oldest_user = NULL; |
316 time_t oldest_ctime = 0; | 505 time_t oldest_ctime = 0; |
317 | 506 |
318 const char* tmpdirname = os::get_temp_directory(); | 507 const char* tmpdirname = os::get_temp_directory(); |
319 | 508 |
320 DIR* tmpdirp = os::opendir(tmpdirname); | 509 // open the temp directory |
321 | 510 DIR* tmpdirp = open_directory_secure(tmpdirname); |
322 if (tmpdirp == NULL) { | 511 if (tmpdirp == NULL) { |
512 // Cannot open the directory to get the user name, return. | |
323 return NULL; | 513 return NULL; |
324 } | 514 } |
325 | 515 |
326 // for each entry in the directory that matches the pattern hsperfdata_*, | 516 // for each entry in the directory that matches the pattern hsperfdata_*, |
327 // open the directory and check if the file for the given vmid exists. | 517 // open the directory and check if the file for the given vmid exists. |
342 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); | 532 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); |
343 strcpy(usrdir_name, tmpdirname); | 533 strcpy(usrdir_name, tmpdirname); |
344 strcat(usrdir_name, "/"); | 534 strcat(usrdir_name, "/"); |
345 strcat(usrdir_name, dentry->d_name); | 535 strcat(usrdir_name, dentry->d_name); |
346 | 536 |
347 DIR* subdirp = os::opendir(usrdir_name); | 537 // open the user directory |
538 DIR* subdirp = open_directory_secure(usrdir_name); | |
348 | 539 |
349 if (subdirp == NULL) { | 540 if (subdirp == NULL) { |
350 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | 541 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
351 continue; | |
352 } | |
353 | |
354 // Since we don't create the backing store files in directories | |
355 // pointed to by symbolic links, we also don't follow them when | |
356 // looking for the files. We check for a symbolic link after the | |
357 // call to opendir in order to eliminate a small window where the | |
358 // symlink can be exploited. | |
359 // | |
360 if (!is_directory_secure(usrdir_name)) { | |
361 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | |
362 os::closedir(subdirp); | |
363 continue; | 542 continue; |
364 } | 543 } |
365 | 544 |
366 struct dirent* udentry; | 545 struct dirent* udentry; |
367 char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); | 546 char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); |
463 } | 642 } |
464 } | 643 } |
465 } | 644 } |
466 | 645 |
467 | 646 |
468 // remove file | |
469 // | |
470 // this method removes the file with the given file name in the | |
471 // named directory. | |
472 // | |
473 static void remove_file(const char* dirname, const char* filename) { | |
474 | |
475 size_t nbytes = strlen(dirname) + strlen(filename) + 2; | |
476 char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); | |
477 | |
478 strcpy(path, dirname); | |
479 strcat(path, "/"); | |
480 strcat(path, filename); | |
481 | |
482 remove_file(path); | |
483 | |
484 FREE_C_HEAP_ARRAY(char, path, mtInternal); | |
485 } | |
486 | |
487 | |
488 // cleanup stale shared memory resources | 647 // cleanup stale shared memory resources |
489 // | 648 // |
490 // This method attempts to remove all stale shared memory files in | 649 // This method attempts to remove all stale shared memory files in |
491 // the named user temporary directory. It scans the named directory | 650 // the named user temporary directory. It scans the named directory |
492 // for files matching the pattern ^$[0-9]*$. For each file found, the | 651 // for files matching the pattern ^$[0-9]*$. For each file found, the |
494 // determine if the process is alive. If the process is not alive, | 653 // determine if the process is alive. If the process is not alive, |
495 // any stale file resources are removed. | 654 // any stale file resources are removed. |
496 // | 655 // |
497 static void cleanup_sharedmem_resources(const char* dirname) { | 656 static void cleanup_sharedmem_resources(const char* dirname) { |
498 | 657 |
499 // open the user temp directory | 658 int saved_cwd_fd; |
500 DIR* dirp = os::opendir(dirname); | 659 // open the directory and set the current working directory to it |
501 | 660 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); |
502 if (dirp == NULL) { | 661 if (dirp == NULL) { |
503 // directory doesn't exist, so there is nothing to cleanup | 662 // directory doesn't exist or is insecure, so there is nothing to cleanup |
504 return; | |
505 } | |
506 | |
507 if (!is_directory_secure(dirname)) { | |
508 // the directory is not a secure directory | |
509 return; | 663 return; |
510 } | 664 } |
511 | 665 |
512 // for each entry in the directory that matches the expected file | 666 // for each entry in the directory that matches the expected file |
513 // name pattern, determine if the file resources are stale and if | 667 // name pattern, determine if the file resources are stale and if |
517 // loop under these conditions is dependent upon the implementation of | 671 // loop under these conditions is dependent upon the implementation of |
518 // opendir/readdir. | 672 // opendir/readdir. |
519 // | 673 // |
520 struct dirent* entry; | 674 struct dirent* entry; |
521 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); | 675 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); |
676 | |
522 errno = 0; | 677 errno = 0; |
523 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { | 678 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { |
524 | 679 |
525 pid_t pid = filename_to_pid(entry->d_name); | 680 pid_t pid = filename_to_pid(entry->d_name); |
526 | 681 |
527 if (pid == 0) { | 682 if (pid == 0) { |
528 | 683 |
529 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { | 684 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { |
530 | 685 |
531 // attempt to remove all unexpected files, except "." and ".." | 686 // attempt to remove all unexpected files, except "." and ".." |
532 remove_file(dirname, entry->d_name); | 687 unlink(entry->d_name); |
533 } | 688 } |
534 | 689 |
535 errno = 0; | 690 errno = 0; |
536 continue; | 691 continue; |
537 } | 692 } |
550 // process should be in a different user specific directory. | 705 // process should be in a different user specific directory. |
551 // | 706 // |
552 if ((pid == os::current_process_id()) || | 707 if ((pid == os::current_process_id()) || |
553 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { | 708 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { |
554 | 709 |
555 remove_file(dirname, entry->d_name); | 710 unlink(entry->d_name); |
556 } | 711 } |
557 errno = 0; | 712 errno = 0; |
558 } | 713 } |
559 os::closedir(dirp); | 714 |
715 // close the directory and reset the current working directory | |
716 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
717 | |
560 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); | 718 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); |
561 } | 719 } |
562 | 720 |
563 // make the user specific temporary directory. Returns true if | 721 // make the user specific temporary directory. Returns true if |
564 // the directory exists and is secure upon return. Returns false | 722 // the directory exists and is secure upon return. Returns false |
611 // could not make/find the directory or the found directory | 769 // could not make/find the directory or the found directory |
612 // was not secure | 770 // was not secure |
613 return -1; | 771 return -1; |
614 } | 772 } |
615 | 773 |
774 int saved_cwd_fd; | |
775 // open the directory and set the current working directory to it | |
776 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); | |
777 if (dirp == NULL) { | |
778 // Directory doesn't exist or is insecure, so cannot create shared | |
779 // memory file. | |
780 return -1; | |
781 } | |
782 | |
783 // Open the filename in the current directory. | |
784 // Cannot use O_TRUNC here; truncation of an existing file has to happen | |
785 // after the is_file_secure() check below. | |
616 int result; | 786 int result; |
617 | 787 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); |
618 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); | |
619 if (result == OS_ERR) { | 788 if (result == OS_ERR) { |
620 if (PrintMiscellaneous && Verbose) { | 789 if (PrintMiscellaneous && Verbose) { |
621 warning("could not create file %s: %s\n", filename, strerror(errno)); | 790 if (errno == ELOOP) { |
622 } | 791 warning("file %s is a symlink and is not secure\n", filename); |
792 } else { | |
793 warning("could not create file %s: %s\n", filename, strerror(errno)); | |
794 } | |
795 } | |
796 // close the directory and reset the current working directory | |
797 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
798 | |
623 return -1; | 799 return -1; |
624 } | 800 } |
801 // close the directory and reset the current working directory | |
802 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
625 | 803 |
626 // save the file descriptor | 804 // save the file descriptor |
627 int fd = result; | 805 int fd = result; |
628 | 806 |
807 // check to see if the file is secure | |
808 if (!is_file_secure(fd, filename)) { | |
809 ::close(fd); | |
810 return -1; | |
811 } | |
812 | |
813 // truncate the file to get rid of any existing data | |
814 RESTARTABLE(::ftruncate(fd, (off_t)0), result); | |
815 if (result == OS_ERR) { | |
816 if (PrintMiscellaneous && Verbose) { | |
817 warning("could not truncate shared memory file: %s\n", strerror(errno)); | |
818 } | |
819 ::close(fd); | |
820 return -1; | |
821 } | |
629 // set the file size | 822 // set the file size |
630 RESTARTABLE(::ftruncate(fd, (off_t)size), result); | 823 RESTARTABLE(::ftruncate(fd, (off_t)size), result); |
631 if (result == OS_ERR) { | 824 if (result == OS_ERR) { |
632 if (PrintMiscellaneous && Verbose) { | 825 if (PrintMiscellaneous && Verbose) { |
633 warning("could not set shared memory file size: %s\n", strerror(errno)); | 826 warning("could not set shared memory file size: %s\n", strerror(errno)); |
681 } | 874 } |
682 else { | 875 else { |
683 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); | 876 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); |
684 } | 877 } |
685 } | 878 } |
686 | 879 int fd = result; |
687 return result; | 880 |
881 // check to see if the file is secure | |
882 if (!is_file_secure(fd, filename)) { | |
883 ::close(fd); | |
884 return -1; | |
885 } | |
886 | |
887 return fd; | |
688 } | 888 } |
689 | 889 |
690 // create a named shared memory region. returns the address of the | 890 // create a named shared memory region. returns the address of the |
691 // memory region on success or NULL on failure. A return value of | 891 // memory region on success or NULL on failure. A return value of |
692 // NULL will ultimately disable the shared memory feature. | 892 // NULL will ultimately disable the shared memory feature. |
714 return NULL; | 914 return NULL; |
715 | 915 |
716 char* dirname = get_user_tmp_dir(user_name); | 916 char* dirname = get_user_tmp_dir(user_name); |
717 char* filename = get_sharedmem_filename(dirname, vmid); | 917 char* filename = get_sharedmem_filename(dirname, vmid); |
718 | 918 |
919 // get the short filename | |
920 char* short_filename = strrchr(filename, '/'); | |
921 if (short_filename == NULL) { | |
922 short_filename = filename; | |
923 } else { | |
924 short_filename++; | |
925 } | |
926 | |
719 // cleanup any stale shared memory files | 927 // cleanup any stale shared memory files |
720 cleanup_sharedmem_resources(dirname); | 928 cleanup_sharedmem_resources(dirname); |
721 | 929 |
722 assert(((size > 0) && (size % os::vm_page_size() == 0)), | 930 assert(((size > 0) && (size % os::vm_page_size() == 0)), |
723 "unexpected PerfMemory region size"); | 931 "unexpected PerfMemory region size"); |
724 | 932 |
725 fd = create_sharedmem_resources(dirname, filename, size); | 933 fd = create_sharedmem_resources(dirname, short_filename, size); |
726 | 934 |
727 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); | 935 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
728 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | 936 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
729 | 937 |
730 if (fd == -1) { | 938 if (fd == -1) { |
835 | 1043 |
836 // map the high level access mode to the appropriate permission | 1044 // map the high level access mode to the appropriate permission |
837 // constructs for the file and the shared memory mapping. | 1045 // constructs for the file and the shared memory mapping. |
838 if (mode == PerfMemory::PERF_MODE_RO) { | 1046 if (mode == PerfMemory::PERF_MODE_RO) { |
839 mmap_prot = PROT_READ; | 1047 mmap_prot = PROT_READ; |
840 file_flags = O_RDONLY; | 1048 file_flags = O_RDONLY | O_NOFOLLOW; |
841 } | 1049 } |
842 else if (mode == PerfMemory::PERF_MODE_RW) { | 1050 else if (mode == PerfMemory::PERF_MODE_RW) { |
843 #ifdef LATER | 1051 #ifdef LATER |
844 mmap_prot = PROT_READ | PROT_WRITE; | 1052 mmap_prot = PROT_READ | PROT_WRITE; |
845 file_flags = O_RDWR; | 1053 file_flags = O_RDWR | O_NOFOLLOW; |
846 #else | 1054 #else |
847 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | 1055 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
848 "Unsupported access mode"); | 1056 "Unsupported access mode"); |
849 #endif | 1057 #endif |
850 } | 1058 } |