Mercurial > hg > graal-compiler
comparison src/os/solaris/vm/perfMemory_solaris.cpp @ 21820:fb677d6aebea
8062675: jmap is unable to display information about java processes and prints only pids
Summary: backout fix 8050808 which caused this regression and as requested.
Reviewed-by: hseigel
author | asaha |
---|---|
date | Mon, 10 Nov 2014 09:47:41 -0800 |
parents | 5ca2ea5eeff0 |
children | 9a227eaac2dc |
comparison
equal
deleted
inserted
replaced
21819:b1cf34d57e78 | 21820:fb677d6aebea |
---|---|
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 statbuf is considered a secure directory for | 202 // check if the given path 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 | |
234 // the backing store files. Returns true if the directory exists | 203 // the backing store files. Returns true if the directory exists |
235 // and is considered a secure location. Returns false if the path | 204 // and is considered a secure location. Returns false if the path |
236 // is a symbolic link or if an error occurred. | 205 // is a symbolic link or if an error occurred. |
237 // | 206 // |
238 static bool is_directory_secure(const char* path) { | 207 static bool is_directory_secure(const char* path) { |
242 RESTARTABLE(::lstat(path, &statbuf), result); | 211 RESTARTABLE(::lstat(path, &statbuf), result); |
243 if (result == OS_ERR) { | 212 if (result == OS_ERR) { |
244 return false; | 213 return false; |
245 } | 214 } |
246 | 215 |
247 // The path exists, see if it is secure. | 216 // the path exists, now check it's mode |
248 return is_statbuf_secure(&statbuf); | 217 if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { |
249 } | 218 // the path represents a link or some non-directory file type, |
250 | 219 // which is not what we expected. declare it insecure. |
251 | 220 // |
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) { | |
263 return false; | 221 return false; |
264 } | 222 } |
265 | 223 else { |
266 // The path exists, now check its mode. | 224 // we have an existing directory, check if the permissions are safe. |
267 return is_statbuf_secure(&statbuf); | 225 // |
268 } | 226 if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { |
269 | 227 // the directory is open for writing and could be subjected |
270 | 228 // to a symlnk attack. declare it insecure. |
271 // Check to make sure fd1 and fd2 are referencing the same file system object. | 229 // |
272 // | 230 return false; |
273 static bool is_same_fsobject(int fd1, int fd2) { | 231 } |
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; | |
422 } | 232 } |
423 return true; | 233 return true; |
424 } | 234 } |
235 | |
425 | 236 |
426 // return the user name for the given user id | 237 // return the user name for the given user id |
427 // | 238 // |
428 // the caller is expected to free the allocated memory. | 239 // the caller is expected to free the allocated memory. |
429 // | 240 // |
495 char* oldest_user = NULL; | 306 char* oldest_user = NULL; |
496 time_t oldest_ctime = 0; | 307 time_t oldest_ctime = 0; |
497 | 308 |
498 const char* tmpdirname = os::get_temp_directory(); | 309 const char* tmpdirname = os::get_temp_directory(); |
499 | 310 |
500 // open the temp directory | 311 DIR* tmpdirp = os::opendir(tmpdirname); |
501 DIR* tmpdirp = open_directory_secure(tmpdirname); | 312 |
502 if (tmpdirp == NULL) { | 313 if (tmpdirp == NULL) { |
503 // Cannot open the directory to get the user name, return. | |
504 return NULL; | 314 return NULL; |
505 } | 315 } |
506 | 316 |
507 // for each entry in the directory that matches the pattern hsperfdata_*, | 317 // for each entry in the directory that matches the pattern hsperfdata_*, |
508 // open the directory and check if the file for the given vmid exists. | 318 // open the directory and check if the file for the given vmid exists. |
523 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); | 333 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); |
524 strcpy(usrdir_name, tmpdirname); | 334 strcpy(usrdir_name, tmpdirname); |
525 strcat(usrdir_name, "/"); | 335 strcat(usrdir_name, "/"); |
526 strcat(usrdir_name, dentry->d_name); | 336 strcat(usrdir_name, dentry->d_name); |
527 | 337 |
528 // open the user directory | 338 DIR* subdirp = os::opendir(usrdir_name); |
529 DIR* subdirp = open_directory_secure(usrdir_name); | |
530 | 339 |
531 if (subdirp == NULL) { | 340 if (subdirp == NULL) { |
532 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | 341 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
533 continue; | 342 continue; |
534 } | 343 } |
693 } | 502 } |
694 } | 503 } |
695 } | 504 } |
696 | 505 |
697 | 506 |
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 | |
698 // cleanup stale shared memory resources | 527 // cleanup stale shared memory resources |
699 // | 528 // |
700 // This method attempts to remove all stale shared memory files in | 529 // This method attempts to remove all stale shared memory files in |
701 // the named user temporary directory. It scans the named directory | 530 // the named user temporary directory. It scans the named directory |
702 // for files matching the pattern ^$[0-9]*$. For each file found, the | 531 // for files matching the pattern ^$[0-9]*$. For each file found, the |
704 // determine if the process is alive. If the process is not alive, | 533 // determine if the process is alive. If the process is not alive, |
705 // any stale file resources are removed. | 534 // any stale file resources are removed. |
706 // | 535 // |
707 static void cleanup_sharedmem_resources(const char* dirname) { | 536 static void cleanup_sharedmem_resources(const char* dirname) { |
708 | 537 |
709 int saved_cwd_fd; | 538 // open the user temp directory |
710 // open the directory | 539 DIR* dirp = os::opendir(dirname); |
711 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); | 540 |
712 if (dirp == NULL) { | 541 if (dirp == NULL) { |
713 // directory doesn't exist or is insecure, so there is nothing to cleanup | 542 // directory doesn't exist, so there is nothing to cleanup |
543 return; | |
544 } | |
545 | |
546 if (!is_directory_secure(dirname)) { | |
547 // the directory is not a secure directory | |
714 return; | 548 return; |
715 } | 549 } |
716 | 550 |
717 // for each entry in the directory that matches the expected file | 551 // for each entry in the directory that matches the expected file |
718 // name pattern, determine if the file resources are stale and if | 552 // name pattern, determine if the file resources are stale and if |
722 // loop under these conditions is dependent upon the implementation of | 556 // loop under these conditions is dependent upon the implementation of |
723 // opendir/readdir. | 557 // opendir/readdir. |
724 // | 558 // |
725 struct dirent* entry; | 559 struct dirent* entry; |
726 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); | 560 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); |
727 | |
728 errno = 0; | 561 errno = 0; |
729 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { | 562 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { |
730 | 563 |
731 pid_t pid = filename_to_pid(entry->d_name); | 564 pid_t pid = filename_to_pid(entry->d_name); |
732 | 565 |
733 if (pid == 0) { | 566 if (pid == 0) { |
734 | 567 |
735 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { | 568 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { |
736 | 569 |
737 // attempt to remove all unexpected files, except "." and ".." | 570 // attempt to remove all unexpected files, except "." and ".." |
738 unlink(entry->d_name); | 571 remove_file(dirname, entry->d_name); |
739 } | 572 } |
740 | 573 |
741 errno = 0; | 574 errno = 0; |
742 continue; | 575 continue; |
743 } | 576 } |
756 // process should be in a different user specific directory. | 589 // process should be in a different user specific directory. |
757 // | 590 // |
758 if ((pid == os::current_process_id()) || | 591 if ((pid == os::current_process_id()) || |
759 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { | 592 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { |
760 | 593 |
761 unlink(entry->d_name); | 594 remove_file(dirname, entry->d_name); |
762 } | 595 } |
763 errno = 0; | 596 errno = 0; |
764 } | 597 } |
765 | 598 os::closedir(dirp); |
766 // close the directory and reset the current working directory | |
767 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
768 | |
769 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); | 599 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); |
770 } | 600 } |
771 | 601 |
772 // make the user specific temporary directory. Returns true if | 602 // make the user specific temporary directory. Returns true if |
773 // the directory exists and is secure upon return. Returns false | 603 // the directory exists and is secure upon return. Returns false |
820 // could not make/find the directory or the found directory | 650 // could not make/find the directory or the found directory |
821 // was not secure | 651 // was not secure |
822 return -1; | 652 return -1; |
823 } | 653 } |
824 | 654 |
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. | |
837 int result; | 655 int result; |
838 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); | 656 |
657 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); | |
839 if (result == OS_ERR) { | 658 if (result == OS_ERR) { |
840 if (PrintMiscellaneous && Verbose) { | 659 if (PrintMiscellaneous && Verbose) { |
841 if (errno == ELOOP) { | 660 warning("could not create file %s: %s\n", filename, strerror(errno)); |
842 warning("file %s is a symlink and is not secure\n", filename); | 661 } |
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 | |
850 return -1; | 662 return -1; |
851 } | 663 } |
852 // close the directory and reset the current working directory | |
853 close_directory_secure_cwd(dirp, saved_cwd_fd); | |
854 | 664 |
855 // save the file descriptor | 665 // save the file descriptor |
856 int fd = result; | 666 int fd = result; |
857 | 667 |
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 } | |
873 // set the file size | 668 // set the file size |
874 RESTARTABLE(::ftruncate(fd, (off_t)size), result); | 669 RESTARTABLE(::ftruncate(fd, (off_t)size), result); |
875 if (result == OS_ERR) { | 670 if (result == OS_ERR) { |
876 if (PrintMiscellaneous && Verbose) { | 671 if (PrintMiscellaneous && Verbose) { |
877 warning("could not set shared memory file size: %s\n", strerror(errno)); | 672 warning("could not set shared memory file size: %s\n", strerror(errno)); |
903 } | 698 } |
904 else { | 699 else { |
905 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); | 700 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); |
906 } | 701 } |
907 } | 702 } |
908 int fd = result; | 703 |
909 | 704 return result; |
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; | |
917 } | 705 } |
918 | 706 |
919 // create a named shared memory region. returns the address of the | 707 // create a named shared memory region. returns the address of the |
920 // memory region on success or NULL on failure. A return value of | 708 // memory region on success or NULL on failure. A return value of |
921 // NULL will ultimately disable the shared memory feature. | 709 // NULL will ultimately disable the shared memory feature. |
943 return NULL; | 731 return NULL; |
944 | 732 |
945 char* dirname = get_user_tmp_dir(user_name); | 733 char* dirname = get_user_tmp_dir(user_name); |
946 char* filename = get_sharedmem_filename(dirname, vmid); | 734 char* filename = get_sharedmem_filename(dirname, vmid); |
947 | 735 |
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 | |
956 // cleanup any stale shared memory files | 736 // cleanup any stale shared memory files |
957 cleanup_sharedmem_resources(dirname); | 737 cleanup_sharedmem_resources(dirname); |
958 | 738 |
959 assert(((size > 0) && (size % os::vm_page_size() == 0)), | 739 assert(((size > 0) && (size % os::vm_page_size() == 0)), |
960 "unexpected PerfMemory region size"); | 740 "unexpected PerfMemory region size"); |
961 | 741 |
962 fd = create_sharedmem_resources(dirname, short_filename, size); | 742 fd = create_sharedmem_resources(dirname, filename, size); |
963 | 743 |
964 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); | 744 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
965 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | 745 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
966 | 746 |
967 if (fd == -1) { | 747 if (fd == -1) { |
1073 | 853 |
1074 // map the high level access mode to the appropriate permission | 854 // map the high level access mode to the appropriate permission |
1075 // constructs for the file and the shared memory mapping. | 855 // constructs for the file and the shared memory mapping. |
1076 if (mode == PerfMemory::PERF_MODE_RO) { | 856 if (mode == PerfMemory::PERF_MODE_RO) { |
1077 mmap_prot = PROT_READ; | 857 mmap_prot = PROT_READ; |
1078 file_flags = O_RDONLY | O_NOFOLLOW; | 858 file_flags = O_RDONLY; |
1079 } | 859 } |
1080 else if (mode == PerfMemory::PERF_MODE_RW) { | 860 else if (mode == PerfMemory::PERF_MODE_RW) { |
1081 #ifdef LATER | 861 #ifdef LATER |
1082 mmap_prot = PROT_READ | PROT_WRITE; | 862 mmap_prot = PROT_READ | PROT_WRITE; |
1083 file_flags = O_RDWR | O_NOFOLLOW; | 863 file_flags = O_RDWR; |
1084 #else | 864 #else |
1085 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | 865 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
1086 "Unsupported access mode"); | 866 "Unsupported access mode"); |
1087 #endif | 867 #endif |
1088 } | 868 } |