Mercurial > hg > graal-jvmci-8
comparison src/os/solaris/vm/perfMemory_solaris.cpp @ 21816:60a992c821f8
8050807: Better performing performance data handling
Reviewed-by: dcubed, dholmes, pnauman, ctornqvi, mschoene
Contributed-by: gerald.thornbrugh@oracle.com
author | hseigel |
---|---|
date | Fri, 24 Oct 2014 15:02:37 -0400 |
parents | 7d28f4e15b61 |
children | 5ca2ea5eeff0 |
comparison
equal
deleted
inserted
replaced
21815:37179dcf830a | 21816:60a992c821f8 |
---|---|
197 // successful conversion, return the pid | 197 // successful conversion, return the pid |
198 return pid; | 198 return pid; |
199 } | 199 } |
200 | 200 |
201 | 201 |
202 // check if the given path is considered a secure directory for | 202 // Check if the given statbuf is considered a secure directory for |
203 // the backing store files. Returns true if the directory is considered | |
204 // a secure location. Returns false if the statbuf is a symbolic link or | |
205 // if an error occurred. | |
206 // | |
207 static bool is_statbuf_secure(struct stat *statp) { | |
208 if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { | |
209 // The path represents a link or some non-directory file type, | |
210 // which is not what we expected. Declare it insecure. | |
211 // | |
212 return false; | |
213 } | |
214 // We have an existing directory, check if the permissions are safe. | |
215 // | |
216 if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { | |
217 // The directory is open for writing and could be subjected | |
218 // to a symlink or a hard link attack. Declare it insecure. | |
219 // | |
220 return false; | |
221 } | |
222 // See if the uid of the directory matches the effective uid of the process. | |
223 // | |
224 if (statp->st_uid != geteuid()) { | |
225 // The directory was not created by this user, declare it insecure. | |
226 // | |
227 return false; | |
228 } | |
229 return true; | |
230 } | |
231 | |
232 | |
233 // Check if the given path is considered a secure directory for | |
203 // the backing store files. Returns true if the directory exists | 234 // the backing store files. Returns true if the directory exists |
204 // and is considered a secure location. Returns false if the path | 235 // and is considered a secure location. Returns false if the path |
205 // is a symbolic link or if an error occurred. | 236 // is a symbolic link or if an error occurred. |
206 // | 237 // |
207 static bool is_directory_secure(const char* path) { | 238 static bool is_directory_secure(const char* path) { |
211 RESTARTABLE(::lstat(path, &statbuf), result); | 242 RESTARTABLE(::lstat(path, &statbuf), result); |
212 if (result == OS_ERR) { | 243 if (result == OS_ERR) { |
213 return false; | 244 return false; |
214 } | 245 } |
215 | 246 |
216 // the path exists, now check it's mode | 247 // The path exists, see if it is secure. |
217 if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { | 248 return is_statbuf_secure(&statbuf); |
218 // the path represents a link or some non-directory file type, | 249 } |
219 // which is not what we expected. declare it insecure. | 250 |
220 // | 251 |
252 // Check if the given directory file descriptor is considered a secure | |
253 // directory for the backing store files. Returns true if the directory | |
254 // exists and is considered a secure location. Returns false if the path | |
255 // is a symbolic link or if an error occurred. | |
256 // | |
257 static bool is_dirfd_secure(int dir_fd) { | |
258 struct stat statbuf; | |
259 int result = 0; | |
260 | |
261 RESTARTABLE(::fstat(dir_fd, &statbuf), result); | |
262 if (result == OS_ERR) { | |
221 return false; | 263 return false; |
222 } | 264 } |
223 else { | 265 |
224 // we have an existing directory, check if the permissions are safe. | 266 // The path exists, now check its mode. |
225 // | 267 return is_statbuf_secure(&statbuf); |
226 if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { | 268 } |
227 // the directory is open for writing and could be subjected | 269 |
228 // to a symlnk attack. declare it insecure. | 270 |
229 // | 271 // Check to make sure fd1 and fd2 are referencing the same file system object. |
230 return false; | 272 // |
231 } | 273 static bool is_same_fsobject(int fd1, int fd2) { |
274 struct stat statbuf1; | |
275 struct stat statbuf2; | |
276 int result = 0; | |
277 | |
278 RESTARTABLE(::fstat(fd1, &statbuf1), result); | |
279 if (result == OS_ERR) { | |
280 return false; | |
281 } | |
282 RESTARTABLE(::fstat(fd2, &statbuf2), result); | |
283 if (result == OS_ERR) { | |
284 return false; | |
285 } | |
286 | |
287 if ((statbuf1.st_ino == statbuf2.st_ino) && | |
288 (statbuf1.st_dev == statbuf2.st_dev)) { | |
289 return true; | |
290 } else { | |
291 return false; | |
292 } | |
293 } | |
294 | |
295 | |
296 // Open the directory of the given path and validate it. | |
297 // Return a DIR * of the open directory. | |
298 // | |
299 static DIR *open_directory_secure(const char* dirname) { | |
300 // Open the directory using open() so that it can be verified | |
301 // to be secure by calling is_dirfd_secure(), opendir() and then check | |
302 // to see if they are the same file system object. This method does not | |
303 // introduce a window of opportunity for the directory to be attacked that | |
304 // calling opendir() and is_directory_secure() does. | |
305 int result; | |
306 DIR *dirp = NULL; | |
307 RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); | |
308 if (result == OS_ERR) { | |
309 // Directory doesn't exist or is a symlink, so there is nothing to cleanup. | |
310 if (PrintMiscellaneous && Verbose) { | |
311 if (errno == ELOOP) { | |
312 warning("directory %s is a symlink and is not secure\n", dirname); | |
313 } else { | |
314 warning("could not open directory %s: %s\n", dirname, strerror(errno)); | |
315 } | |
316 } | |
317 return dirp; | |
318 } | |
319 int fd = result; | |
320 | |
321 // Determine if the open directory is secure. | |
322 if (!is_dirfd_secure(fd)) { | |
323 // The directory is not a secure directory. | |
324 os::close(fd); | |
325 return dirp; | |
326 } | |
327 | |
328 // Open the directory. | |
329 dirp = ::opendir(dirname); | |
330 if (dirp == NULL) { | |
331 // The directory doesn't exist, close fd and return. | |
332 os::close(fd); | |
333 return dirp; | |
334 } | |
335 | |
336 // Check to make sure fd and dirp are referencing the same file system object. | |
337 if (!is_same_fsobject(fd, dirp->dd_fd)) { | |
338 // The directory is not secure. | |
339 os::close(fd); | |
340 os::closedir(dirp); | |
341 dirp = NULL; | |
342 return dirp; | |
343 } | |
344 | |
345 // Close initial open now that we know directory is secure | |
346 os::close(fd); | |
347 | |
348 return dirp; | |
349 } | |
350 | |
351 // NOTE: The code below uses fchdir(), open() and unlink() because | |
352 // fdopendir(), openat() and unlinkat() are not supported on all | |
353 // versions. Once the support for fdopendir(), openat() and unlinkat() | |
354 // is available on all supported versions the code can be changed | |
355 // to use these functions. | |
356 | |
357 // Open the directory of the given path, validate it and set the | |
358 // current working directory to it. | |
359 // Return a DIR * of the open directory and the saved cwd fd. | |
360 // | |
361 static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { | |
362 | |
363 // Open the directory. | |
364 DIR* dirp = open_directory_secure(dirname); | |
365 if (dirp == NULL) { | |
366 // Directory doesn't exist or is insecure, so there is nothing to cleanup. | |
367 return dirp; | |
368 } | |
369 int fd = dirp->dd_fd; | |
370 | |
371 // Open a fd to the cwd and save it off. | |
372 int result; | |
373 RESTARTABLE(::open(".", O_RDONLY), result); | |
374 if (result == OS_ERR) { | |
375 *saved_cwd_fd = -1; | |
376 } else { | |
377 *saved_cwd_fd = result; | |
378 } | |
379 | |
380 // Set the current directory to dirname by using the fd of the directory. | |
381 result = fchdir(fd); | |
382 | |
383 return dirp; | |
384 } | |
385 | |
386 // Close the directory and restore the current working directory. | |
387 // | |
388 static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { | |
389 | |
390 int result; | |
391 // If we have a saved cwd change back to it and close the fd. | |
392 if (saved_cwd_fd != -1) { | |
393 result = fchdir(saved_cwd_fd); | |
394 ::close(saved_cwd_fd); | |
395 } | |
396 | |
397 // Close the directory. | |
398 os::closedir(dirp); | |
399 } | |
400 | |
401 // Check if the given file descriptor is considered a secure. | |
402 // | |
403 static bool is_file_secure(int fd, const char *filename) { | |
404 | |
405 int result; | |
406 struct stat statbuf; | |
407 | |
408 // Determine if the file is secure. | |
409 RESTARTABLE(::fstat(fd, &statbuf), result); | |
410 if (result == OS_ERR) { | |
411 if (PrintMiscellaneous && Verbose) { | |
412 warning("fstat failed on %s: %s\n", filename, strerror(errno)); | |
413 } | |
414 return false; | |
415 } | |
416 if (statbuf.st_nlink > 1) { | |
417 // A file with multiple links is not expected. | |
418 if (PrintMiscellaneous && Verbose) { | |
419 warning("file %s has multiple links\n", filename); | |
420 } | |
421 return false; | |
232 } | 422 } |
233 return true; | 423 return true; |
234 } | 424 } |
235 | |
236 | 425 |
237 // return the user name for the given user id | 426 // return the user name for the given user id |
238 // | 427 // |
239 // the caller is expected to free the allocated memory. | 428 // the caller is expected to free the allocated memory. |
240 // | 429 // |
306 char* oldest_user = NULL; | 495 char* oldest_user = NULL; |
307 time_t oldest_ctime = 0; | 496 time_t oldest_ctime = 0; |
308 | 497 |
309 const char* tmpdirname = os::get_temp_directory(); | 498 const char* tmpdirname = os::get_temp_directory(); |
310 | 499 |
311 DIR* tmpdirp = os::opendir(tmpdirname); | 500 // open the temp directory |
312 | 501 DIR* tmpdirp = open_directory_secure(tmpdirname); |
313 if (tmpdirp == NULL) { | 502 if (tmpdirp == NULL) { |
503 // Cannot open the directory to get the user name, return. | |
314 return NULL; | 504 return NULL; |
315 } | 505 } |
316 | 506 |
317 // for each entry in the directory that matches the pattern hsperfdata_*, | 507 // for each entry in the directory that matches the pattern hsperfdata_*, |
318 // open the directory and check if the file for the given vmid exists. | 508 // open the directory and check if the file for the given vmid exists. |
333 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); | 523 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); |
334 strcpy(usrdir_name, tmpdirname); | 524 strcpy(usrdir_name, tmpdirname); |
335 strcat(usrdir_name, "/"); | 525 strcat(usrdir_name, "/"); |
336 strcat(usrdir_name, dentry->d_name); | 526 strcat(usrdir_name, dentry->d_name); |
337 | 527 |
338 DIR* subdirp = os::opendir(usrdir_name); | 528 // open the user directory |
529 DIR* subdirp = open_directory_secure(usrdir_name); | |
339 | 530 |
340 if (subdirp == NULL) { | 531 if (subdirp == NULL) { |
341 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | 532 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
342 continue; | 533 continue; |
343 } | 534 } |
502 } | 693 } |
503 } | 694 } |
504 } | 695 } |
505 | 696 |
506 | 697 |
507 // remove file | |
508 // | |
509 // this method removes the file with the given file name in the | |
510 // named directory. | |
511 // | |
512 static void remove_file(const char* dirname, const char* filename) { | |
513 | |
514 size_t nbytes = strlen(dirname) + strlen(filename) + 2; | |
515 char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); | |
516 | |
517 strcpy(path, dirname); | |
518 strcat(path, "/"); | |
519 strcat(path, filename); | |
520 | |
521 remove_file(path); | |
522 | |
523 FREE_C_HEAP_ARRAY(char, path, mtInternal); | |
524 } | |
525 | |
526 | |
527 // cleanup stale shared memory resources | 698 // cleanup stale shared memory resources |
528 // | 699 // |
529 // This method attempts to remove all stale shared memory files in | 700 // This method attempts to remove all stale shared memory files in |
530 // the named user temporary directory. It scans the named directory | 701 // the named user temporary directory. It scans the named directory |
531 // for files matching the pattern ^$[0-9]*$. For each file found, the | 702 // for files matching the pattern ^$[0-9]*$. For each file found, the |
533 // determine if the process is alive. If the process is not alive, | 704 // determine if the process is alive. If the process is not alive, |
534 // any stale file resources are removed. | 705 // any stale file resources are removed. |
535 // | 706 // |
536 static void cleanup_sharedmem_resources(const char* dirname) { | 707 static void cleanup_sharedmem_resources(const char* dirname) { |
537 | 708 |
538 // open the user temp directory | 709 int saved_cwd_fd; |
539 DIR* dirp = os::opendir(dirname); | 710 // open the directory |
540 | 711 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); |
541 if (dirp == NULL) { | 712 if (dirp == NULL) { |
542 // directory doesn't exist, so there is nothing to cleanup | 713 // directory doesn't exist or is insecure, so there is nothing to cleanup |
543 return; | |
544 } | |
545 | |
546 if (!is_directory_secure(dirname)) { | |
547 // the directory is not a secure directory | |
548 return; | 714 return; |
549 } | 715 } |
550 | 716 |
551 // for each entry in the directory that matches the expected file | 717 // for each entry in the directory that matches the expected file |
552 // name pattern, determine if the file resources are stale and if | 718 // name pattern, determine if the file resources are stale and if |
556 // loop under these conditions is dependent upon the implementation of | 722 // loop under these conditions is dependent upon the implementation of |
557 // opendir/readdir. | 723 // opendir/readdir. |
558 // | 724 // |
559 struct dirent* entry; | 725 struct dirent* entry; |
560 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); | 726 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); |
727 | |
561 errno = 0; | 728 errno = 0; |
562 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { | 729 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { |
563 | 730 |
564 pid_t pid = filename_to_pid(entry->d_name); | 731 pid_t pid = filename_to_pid(entry->d_name); |
565 | 732 |
566 if (pid == 0) { | 733 if (pid == 0) { |
567 | 734 |
568 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { | 735 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { |
569 | 736 |
570 // attempt to remove all unexpected files, except "." and ".." | 737 // attempt to remove all unexpected files, except "." and ".." |
571 remove_file(dirname, entry->d_name); | 738 unlink(entry->d_name); |
572 } | 739 } |
573 | 740 |
574 errno = 0; | 741 errno = 0; |
575 continue; | 742 continue; |
576 } | 743 } |
589 // process should be in a different user specific directory. | 756 // process should be in a different user specific directory. |
590 // | 757 // |
591 if ((pid == os::current_process_id()) || | 758 if ((pid == os::current_process_id()) || |
592 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { | 759 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { |
593 | 760 |
594 remove_file(dirname, entry->d_name); | 761 unlink(entry->d_name); |
595 } | 762 } |
596 errno = 0; | 763 errno = 0; |
597 } | 764 } |
598 os::closedir(dirp); | 765 |
766 // close the directory and reset the current working directory | |
767 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
768 | |
599 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); | 769 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); |
600 } | 770 } |
601 | 771 |
602 // make the user specific temporary directory. Returns true if | 772 // make the user specific temporary directory. Returns true if |
603 // the directory exists and is secure upon return. Returns false | 773 // the directory exists and is secure upon return. Returns false |
650 // could not make/find the directory or the found directory | 820 // could not make/find the directory or the found directory |
651 // was not secure | 821 // was not secure |
652 return -1; | 822 return -1; |
653 } | 823 } |
654 | 824 |
825 int saved_cwd_fd; | |
826 // open the directory and set the current working directory to it | |
827 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); | |
828 if (dirp == NULL) { | |
829 // Directory doesn't exist or is insecure, so cannot create shared | |
830 // memory file. | |
831 return -1; | |
832 } | |
833 | |
834 // Open the filename in the current directory. | |
835 // Cannot use O_TRUNC here; truncation of an existing file has to happen | |
836 // after the is_file_secure() check below. | |
655 int result; | 837 int result; |
656 | 838 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); |
657 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); | |
658 if (result == OS_ERR) { | 839 if (result == OS_ERR) { |
659 if (PrintMiscellaneous && Verbose) { | 840 if (PrintMiscellaneous && Verbose) { |
660 warning("could not create file %s: %s\n", filename, strerror(errno)); | 841 if (errno == ELOOP) { |
661 } | 842 warning("file %s is a symlink and is not secure\n", filename); |
843 } else { | |
844 warning("could not create file %s: %s\n", filename, strerror(errno)); | |
845 } | |
846 } | |
847 // close the directory and reset the current working directory | |
848 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
849 | |
662 return -1; | 850 return -1; |
663 } | 851 } |
852 // close the directory and reset the current working directory | |
853 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
664 | 854 |
665 // save the file descriptor | 855 // save the file descriptor |
666 int fd = result; | 856 int fd = result; |
667 | 857 |
858 // check to see if the file is secure | |
859 if (!is_file_secure(fd, filename)) { | |
860 ::close(fd); | |
861 return -1; | |
862 } | |
863 | |
864 // truncate the file to get rid of any existing data | |
865 RESTARTABLE(::ftruncate(fd, (off_t)0), result); | |
866 if (result == OS_ERR) { | |
867 if (PrintMiscellaneous && Verbose) { | |
868 warning("could not truncate shared memory file: %s\n", strerror(errno)); | |
869 } | |
870 ::close(fd); | |
871 return -1; | |
872 } | |
668 // set the file size | 873 // set the file size |
669 RESTARTABLE(::ftruncate(fd, (off_t)size), result); | 874 RESTARTABLE(::ftruncate(fd, (off_t)size), result); |
670 if (result == OS_ERR) { | 875 if (result == OS_ERR) { |
671 if (PrintMiscellaneous && Verbose) { | 876 if (PrintMiscellaneous && Verbose) { |
672 warning("could not set shared memory file size: %s\n", strerror(errno)); | 877 warning("could not set shared memory file size: %s\n", strerror(errno)); |
698 } | 903 } |
699 else { | 904 else { |
700 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); | 905 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); |
701 } | 906 } |
702 } | 907 } |
703 | 908 int fd = result; |
704 return result; | 909 |
910 // check to see if the file is secure | |
911 if (!is_file_secure(fd, filename)) { | |
912 ::close(fd); | |
913 return -1; | |
914 } | |
915 | |
916 return fd; | |
705 } | 917 } |
706 | 918 |
707 // create a named shared memory region. returns the address of the | 919 // create a named shared memory region. returns the address of the |
708 // memory region on success or NULL on failure. A return value of | 920 // memory region on success or NULL on failure. A return value of |
709 // NULL will ultimately disable the shared memory feature. | 921 // NULL will ultimately disable the shared memory feature. |
731 return NULL; | 943 return NULL; |
732 | 944 |
733 char* dirname = get_user_tmp_dir(user_name); | 945 char* dirname = get_user_tmp_dir(user_name); |
734 char* filename = get_sharedmem_filename(dirname, vmid); | 946 char* filename = get_sharedmem_filename(dirname, vmid); |
735 | 947 |
948 // get the short filename | |
949 char* short_filename = strrchr(filename, '/'); | |
950 if (short_filename == NULL) { | |
951 short_filename = filename; | |
952 } else { | |
953 short_filename++; | |
954 } | |
955 | |
736 // cleanup any stale shared memory files | 956 // cleanup any stale shared memory files |
737 cleanup_sharedmem_resources(dirname); | 957 cleanup_sharedmem_resources(dirname); |
738 | 958 |
739 assert(((size > 0) && (size % os::vm_page_size() == 0)), | 959 assert(((size > 0) && (size % os::vm_page_size() == 0)), |
740 "unexpected PerfMemory region size"); | 960 "unexpected PerfMemory region size"); |
741 | 961 |
742 fd = create_sharedmem_resources(dirname, filename, size); | 962 fd = create_sharedmem_resources(dirname, short_filename, size); |
743 | 963 |
744 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); | 964 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
745 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | 965 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
746 | 966 |
747 if (fd == -1) { | 967 if (fd == -1) { |
852 | 1072 |
853 // map the high level access mode to the appropriate permission | 1073 // map the high level access mode to the appropriate permission |
854 // constructs for the file and the shared memory mapping. | 1074 // constructs for the file and the shared memory mapping. |
855 if (mode == PerfMemory::PERF_MODE_RO) { | 1075 if (mode == PerfMemory::PERF_MODE_RO) { |
856 mmap_prot = PROT_READ; | 1076 mmap_prot = PROT_READ; |
857 file_flags = O_RDONLY; | 1077 file_flags = O_RDONLY | O_NOFOLLOW; |
858 } | 1078 } |
859 else if (mode == PerfMemory::PERF_MODE_RW) { | 1079 else if (mode == PerfMemory::PERF_MODE_RW) { |
860 #ifdef LATER | 1080 #ifdef LATER |
861 mmap_prot = PROT_READ | PROT_WRITE; | 1081 mmap_prot = PROT_READ | PROT_WRITE; |
862 file_flags = O_RDWR; | 1082 file_flags = O_RDWR | O_NOFOLLOW; |
863 #else | 1083 #else |
864 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | 1084 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
865 "Unsupported access mode"); | 1085 "Unsupported access mode"); |
866 #endif | 1086 #endif |
867 } | 1087 } |