src/os/aix/vm/perfMemory_aix.cpp
Print this page
rev 7700 : 8069590: AIX port of "8050807: Better performing performance data handling"
Reviewed-by: simonis, goetz
Contributed-by: matthias.baesken@sap.com, martin.doerr@sap.com
*** 29,38 ****
--- 29,39 ----
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "os_aix.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/perfMemory.hpp"
+ #include "services/memTracker.hpp"
#include "utilities/exceptions.hpp"
// put OS-includes here
# include <sys/types.h>
# include <sys/mman.h>
*** 194,250 ****
// successful conversion, return the pid
return pid;
}
! // check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
- //
static bool is_directory_secure(const char* path) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::lstat(path, &statbuf), result);
if (result == OS_ERR) {
return false;
}
! // the path exists, now check it's mode
! if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
! // the path represents a link or some non-directory file type,
! // which is not what we expected. declare it insecure.
! //
return false;
}
! else {
! // we have an existing directory, check if the permissions are safe.
! //
! if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
! // the directory is open for writing and could be subjected
! // to a symlnk attack. declare it insecure.
! //
return false;
}
}
return true;
}
! // return the user name for the given user id
//
! // the caller is expected to free the allocated memory.
//
static char* get_user_name(uid_t uid) {
struct passwd pwent;
! // determine the max pwbuf size from sysconf, and hardcode
// a default if this not available through sysconf.
- //
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1)
bufsize = 1024;
char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
--- 195,514 ----
// successful conversion, return the pid
return pid;
}
+ // Check if the given statbuf is considered a secure directory for
+ // the backing store files. Returns true if the directory is considered
+ // a secure location. Returns false if the statbuf is a symbolic link or
+ // if an error occurred.
+ static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ return false;
+ }
+ return true;
+ }
+
! // Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
static bool is_directory_secure(const char* path) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::lstat(path, &statbuf), result);
if (result == OS_ERR) {
return false;
}
! // The path exists, see if it is secure.
! return is_statbuf_secure(&statbuf);
! }
!
! // (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
! // Check if the given directory file descriptor is considered a secure
! // directory for the backing store files. Returns true if the directory
! // exists and is considered a secure location. Returns false if the path
! // is a symbolic link or if an error occurred.
! static bool is_dirfd_secure(int dir_fd) {
! struct stat statbuf;
! int result = 0;
!
! RESTARTABLE(::fstat(dir_fd, &statbuf), result);
! if (result == OS_ERR) {
return false;
}
!
! // The path exists, now check its mode.
! return is_statbuf_secure(&statbuf);
! }
!
!
! // Check to make sure fd1 and fd2 are referencing the same file system object.
! static bool is_same_fsobject(int fd1, int fd2) {
! struct stat statbuf1;
! struct stat statbuf2;
! int result = 0;
!
! RESTARTABLE(::fstat(fd1, &statbuf1), result);
! if (result == OS_ERR) {
return false;
}
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
}
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
return true;
+ } else {
+ return false;
+ }
}
+ // Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
+ // We use the jdk6 implementation here.
+ #ifndef O_NOFOLLOW
+ // The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
+ // was done in jdk 5/6 hotspot by Oracle this way
+ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
+ struct stat orig_st;
+ struct stat new_st;
+ bool create;
+ int error;
+ int fd;
+
+ create = false;
+
+ if (lstat(path, &orig_st) != 0) {
+ if (errno == ENOENT && (oflag & O_CREAT) != 0) {
+ // File doesn't exist, but_we want to create it, add O_EXCL flag
+ // to make sure no-one creates it (or a symlink) before us
+ // This works as we expect with symlinks, from posix man page:
+ // 'If O_EXCL and O_CREAT are set, and path names a symbolic
+ // link, open() shall fail and set errno to [EEXIST]'.
+ oflag |= O_EXCL;
+ create = true;
+ } else {
+ // File doesn't exist, and we are not creating it.
+ return OS_ERR;
+ }
+ } else {
+ // Lstat success, check if existing file is a link.
+ if ((orig_st.st_mode & S_IFMT) == S_IFLNK) {
+ // File is a symlink.
+ errno = ELOOP;
+ return OS_ERR;
+ }
+ }
+
+ if (use_mode == true) {
+ fd = open(path, oflag, mode);
+ } else {
+ fd = open(path, oflag);
+ }
! if (fd == OS_ERR) {
! return fd;
! }
!
! // Can't do inode checks on before/after if we created the file.
! if (create == false) {
! if (fstat(fd, &new_st) != 0) {
! // Keep errno from fstat, in case close also fails.
! error = errno;
! ::close(fd);
! errno = error;
! return OS_ERR;
! }
!
! if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
! // File was tampered with during race window.
! ::close(fd);
! errno = EEXIST;
! if (PrintMiscellaneous && Verbose) {
! warning("possible file tampering attempt detected when opening %s", path);
! }
! return OS_ERR;
! }
! }
!
! return fd;
! }
!
! static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
! return open_o_nofollow_impl(path, oflag, mode, true);
! }
!
! static int open_o_nofollow(const char* path, int oflag) {
! return open_o_nofollow_impl(path, oflag, 0, false);
! }
! #endif
!
! // Open the directory of the given path and validate it.
! // Return a DIR * of the open directory.
! static DIR *open_directory_secure(const char* dirname) {
! // Open the directory using open() so that it can be verified
! // to be secure by calling is_dirfd_secure(), opendir() and then check
! // to see if they are the same file system object. This method does not
! // introduce a window of opportunity for the directory to be attacked that
! // calling opendir() and is_directory_secure() does.
! int result;
! DIR *dirp = NULL;
!
! // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
! // so provide a workaround in this case.
! #ifdef O_NOFOLLOW
! RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
! #else
! // workaround (jdk6 coding)
! RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
! #endif
!
! if (result == OS_ERR) {
! // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
! if (PrintMiscellaneous && Verbose) {
! if (errno == ELOOP) {
! warning("directory %s is a symlink and is not secure\n", dirname);
! } else {
! warning("could not open directory %s: %s\n", dirname, strerror(errno));
! }
! }
! return dirp;
! }
! int fd = result;
!
! // Determine if the open directory is secure.
! if (!is_dirfd_secure(fd)) {
! // The directory is not a secure directory.
! os::close(fd);
! return dirp;
! }
!
! // Open the directory.
! dirp = ::opendir(dirname);
! if (dirp == NULL) {
! // The directory doesn't exist, close fd and return.
! os::close(fd);
! return dirp;
! }
!
! // Check to make sure fd and dirp are referencing the same file system object.
! if (!is_same_fsobject(fd, dirp->dd_fd)) {
! // The directory is not secure.
! os::close(fd);
! os::closedir(dirp);
! dirp = NULL;
! return dirp;
! }
!
! // Close initial open now that we know directory is secure
! os::close(fd);
!
! return dirp;
! }
!
! // NOTE: The code below uses fchdir(), open() and unlink() because
! // fdopendir(), openat() and unlinkat() are not supported on all
! // versions. Once the support for fdopendir(), openat() and unlinkat()
! // is available on all supported versions the code can be changed
! // to use these functions.
!
! // Open the directory of the given path, validate it and set the
! // current working directory to it.
! // Return a DIR * of the open directory and the saved cwd fd.
//
! static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
!
! // Open the directory.
! DIR* dirp = open_directory_secure(dirname);
! if (dirp == NULL) {
! // Directory doesn't exist or is insecure, so there is nothing to cleanup.
! return dirp;
! }
! int fd = dirp->dd_fd;
!
! // Open a fd to the cwd and save it off.
! int result;
! RESTARTABLE(::open(".", O_RDONLY), result);
! if (result == OS_ERR) {
! *saved_cwd_fd = -1;
! } else {
! *saved_cwd_fd = result;
! }
!
! // Set the current directory to dirname by using the fd of the directory.
! result = fchdir(fd);
!
! return dirp;
! }
!
! // Close the directory and restore the current working directory.
! static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
!
! int result;
! // If we have a saved cwd change back to it and close the fd.
! if (saved_cwd_fd != -1) {
! result = fchdir(saved_cwd_fd);
! ::close(saved_cwd_fd);
! }
!
! // Close the directory.
! os::closedir(dirp);
! }
!
! // Check if the given file descriptor is considered a secure.
! static bool is_file_secure(int fd, const char *filename) {
!
! int result;
! struct stat statbuf;
!
! // Determine if the file is secure.
! RESTARTABLE(::fstat(fd, &statbuf), result);
! if (result == OS_ERR) {
! if (PrintMiscellaneous && Verbose) {
! warning("fstat failed on %s: %s\n", filename, strerror(errno));
! }
! return false;
! }
! if (statbuf.st_nlink > 1) {
! // A file with multiple links is not expected.
! if (PrintMiscellaneous && Verbose) {
! warning("file %s has multiple links\n", filename);
! }
! return false;
! }
! return true;
! }
!
! // Return the user name for the given user id.
//
+ // The caller is expected to free the allocated memory.
static char* get_user_name(uid_t uid) {
struct passwd pwent;
! // Determine the max pwbuf size from sysconf, and hardcode
// a default if this not available through sysconf.
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1)
bufsize = 1024;
char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
*** 342,352 ****
strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
! DIR* subdirp = os::opendir(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
continue;
}
--- 606,617 ----
strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
! // Open the user directory.
! DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
continue;
}
*** 462,586 ****
" store file %s : %s\n", path, strerror(errno));
}
}
}
!
! // remove file
! //
! // this method removes the file with the given file name in the
! // named directory.
! //
! static void remove_file(const char* dirname, const char* filename) {
!
! size_t nbytes = strlen(dirname) + strlen(filename) + 2;
! char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
!
! strcpy(path, dirname);
! strcat(path, "/");
! strcat(path, filename);
!
! remove_file(path);
!
! FREE_C_HEAP_ARRAY(char, path);
! }
!
!
! // cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
// the named user temporary directory. It scans the named directory
// for files matching the pattern ^$[0-9]*$. For each file found, the
// process id is extracted from the file name and a test is run to
// determine if the process is alive. If the process is not alive,
// any stale file resources are removed.
- //
static void cleanup_sharedmem_resources(const char* dirname) {
! // open the user temp directory
! DIR* dirp = os::opendir(dirname);
!
if (dirp == NULL) {
! // directory doesn't exist, so there is nothing to cleanup
return;
}
! if (!is_directory_secure(dirname)) {
! // the directory is not a secure directory
! os::closedir(dirp);
! return;
! }
!
! // for each entry in the directory that matches the expected file
// name pattern, determine if the file resources are stale and if
// so, remove the file resources. Note, instrumented HotSpot processes
// for this user may start and/or terminate during this search and
// remove or create new files in this directory. The behavior of this
// loop under these conditions is dependent upon the implementation of
// opendir/readdir.
- //
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
if (pid == 0) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
! // attempt to remove all unexpected files, except "." and ".."
! remove_file(dirname, entry->d_name);
}
errno = 0;
continue;
}
! // we now have a file name that converts to a valid integer
// that could represent a process id . if this process id
// matches the current process id or the process is not running,
// then remove the stale file resources.
//
! // process liveness is detected by sending signal number 0 to
// the process id (see kill(2)). if kill determines that the
// process does not exist, then the file resources are removed.
// if kill determines that that we don't have permission to
// signal the process, then the file resources are assumed to
// be stale and are removed because the resources for such a
// process should be in a different user specific directory.
- //
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
! remove_file(dirname, entry->d_name);
}
errno = 0;
}
! os::closedir(dirp);
! FREE_C_HEAP_ARRAY(char, dbuf);
}
! // make the user specific temporary directory. Returns true if
// the directory exists and is secure upon return. Returns false
// if the directory exists but is either a symlink, is otherwise
// insecure, or if an error occurred.
- //
static bool make_user_tmp_dir(const char* dirname) {
! // create the directory with 0755 permissions. note that the directory
// will be owned by euid::egid, which may not be the same as uid::gid.
- //
if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
if (errno == EEXIST) {
// The directory already exists and was probably created by another
// JVM instance. However, this could also be the result of a
// deliberate symlink. Verify that the existing directory is safe.
- //
if (!is_directory_secure(dirname)) {
! // directory is not secure
if (PrintMiscellaneous && Verbose) {
warning("%s directory is insecure\n", dirname);
}
return false;
}
--- 727,822 ----
" store file %s : %s\n", path, strerror(errno));
}
}
}
! // Cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
// the named user temporary directory. It scans the named directory
// for files matching the pattern ^$[0-9]*$. For each file found, the
// process id is extracted from the file name and a test is run to
// determine if the process is alive. If the process is not alive,
// any stale file resources are removed.
static void cleanup_sharedmem_resources(const char* dirname) {
! int saved_cwd_fd;
! // Open the directory.
! DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
! // Directory doesn't exist or is insecure, so there is nothing to cleanup.
return;
}
! // For each entry in the directory that matches the expected file
// name pattern, determine if the file resources are stale and if
// so, remove the file resources. Note, instrumented HotSpot processes
// for this user may start and/or terminate during this search and
// remove or create new files in this directory. The behavior of this
// loop under these conditions is dependent upon the implementation of
// opendir/readdir.
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
if (pid == 0) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
! // Attempt to remove all unexpected files, except "." and "..".
! unlink(entry->d_name);
}
errno = 0;
continue;
}
! // We now have a file name that converts to a valid integer
// that could represent a process id . if this process id
// matches the current process id or the process is not running,
// then remove the stale file resources.
//
! // Process liveness is detected by sending signal number 0 to
// the process id (see kill(2)). if kill determines that the
// process does not exist, then the file resources are removed.
// if kill determines that that we don't have permission to
// signal the process, then the file resources are assumed to
// be stale and are removed because the resources for such a
// process should be in a different user specific directory.
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
! unlink(entry->d_name);
}
errno = 0;
}
!
! // Close the directory and reset the current working directory.
! close_directory_secure_cwd(dirp, saved_cwd_fd);
!
! FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
! // Make the user specific temporary directory. Returns true if
// the directory exists and is secure upon return. Returns false
// if the directory exists but is either a symlink, is otherwise
// insecure, or if an error occurred.
static bool make_user_tmp_dir(const char* dirname) {
! // Create the directory with 0755 permissions. note that the directory
// will be owned by euid::egid, which may not be the same as uid::gid.
if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
if (errno == EEXIST) {
// The directory already exists and was probably created by another
// JVM instance. However, this could also be the result of a
// deliberate symlink. Verify that the existing directory is safe.
if (!is_directory_secure(dirname)) {
! // Directory is not secure.
if (PrintMiscellaneous && Verbose) {
warning("%s directory is insecure\n", dirname);
}
return false;
}
*** 612,634 ****
// could not make/find the directory or the found directory
// was not secure
return -1;
}
int result;
! RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
return -1;
}
// save the file descriptor
int fd = result;
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not set shared memory file size: %s\n", strerror(errno));
--- 848,914 ----
// could not make/find the directory or the found directory
// was not secure
return -1;
}
+ int saved_cwd_fd;
+ // Open the directory and set the current working directory to it.
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
+
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
int result;
! // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
! // so provide a workaround in this case.
! #ifdef O_NOFOLLOW
! RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
! #else
! // workaround function (jdk6 code)
! RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
! #endif
!
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
+ }
+ // Close the directory and reset the current working directory.
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // Close the directory and reset the current working directory.
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // Check to see if the file is secure.
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // Truncate the file to get rid of any existing data.
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not set shared memory file size: %s\n", strerror(errno));
*** 646,656 ****
--- 926,943 ----
//
static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
// open the file
int result;
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+ // so provide a workaround in this case
+ #ifdef O_NOFOLLOW
RESTARTABLE(::open(filename, oflags), result);
+ #else
+ RESTARTABLE(::open_o_nofollow(filename, oflags), result);
+ #endif
+
if (result == OS_ERR) {
if (errno == ENOENT) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
*** 660,671 ****
}
else {
THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
}
}
! return result;
}
// create a named shared memory region. returns the address of the
// memory region on success or NULL on failure. A return value of
// NULL will ultimately disable the shared memory feature.
--- 947,965 ----
}
else {
THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
}
}
+ int fd = result;
! // Check to see if the file is secure.
! if (!is_file_secure(fd, filename)) {
! ::close(fd);
! return -1;
! }
!
! return fd;
}
// create a named shared memory region. returns the address of the
// memory region on success or NULL on failure. A return value of
// NULL will ultimately disable the shared memory feature.
*** 693,709 ****
return NULL;
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
! fd = create_sharedmem_resources(dirname, filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
if (fd == -1) {
--- 987,1011 ----
return NULL;
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // Get the short filename.
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
! fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
if (fd == -1) {
*** 731,740 ****
--- 1033,1045 ----
backing_store_file_name = filename;
// clear the shared memory region
(void)::memset((void*) mapAddress, 0, size);
+ // It does not go through os api, the operation has to record from here.
+ MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
return mapAddress;
}
// release a named shared memory region
//
*** 805,815 ****
static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) {
char* mapAddress;
int result;
int fd;
! size_t size;
const char* luser = NULL;
int mmap_prot;
int file_flags;
--- 1110,1120 ----
static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPS) {
char* mapAddress;
int result;
int fd;
! size_t size = 0;
const char* luser = NULL;
int mmap_prot;
int file_flags;
*** 817,832 ****
// map the high level access mode to the appropriate permission
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
file_flags = O_RDONLY;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
! file_flags = O_RDWR;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
#endif
}
--- 1122,1143 ----
// map the high level access mode to the appropriate permission
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
+
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open.
+ #ifdef O_NOFOLLOW
+ file_flags = O_RDONLY | O_NOFOLLOW;
+ #else
file_flags = O_RDONLY;
+ #endif
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
! file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
#endif
}
*** 851,863 ****
// since we don't follow symbolic links when creating the backing
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
! FREE_C_HEAP_ARRAY(char, dirname);
if (luser != user) {
! FREE_C_HEAP_ARRAY(char, luser);
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
--- 1162,1174 ----
// since we don't follow symbolic links when creating the backing
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
! FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (luser != user) {
! FREE_C_HEAP_ARRAY(char, luser, mtInternal);
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
*** 899,908 ****
--- 1210,1222 ----
}
THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
"Could not map PerfMemory");
}
+ // It does not go through os api, the operation has to record from here.
+ MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
*addr = mapAddress;
*sizep = size;
if (PerfTraceMemOps) {
tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at "