8069590: AIX port of "8050807: Better performing performance data handling"

Tue, 13 Jan 2015 16:09:52 +0100

author
goetz
date
Tue, 13 Jan 2015 16:09:52 +0100
changeset 7515
b9c06f87e476
parent 7513
0e67683b7001
child 7516
fa4e797f61e6

8069590: AIX port of "8050807: Better performing performance data handling"
Reviewed-by: simonis, goetz
Contributed-by: matthias.baesken@sap.com, martin.doerr@sap.com

make/aix/makefiles/xlc.make file | annotate | diff | comparison | revisions
src/os/aix/vm/perfMemory_aix.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/make/aix/makefiles/xlc.make	Wed Jan 21 12:19:39 2015 -0800
     1.2 +++ b/make/aix/makefiles/xlc.make	Tue Jan 13 16:09:52 2015 +0100
     1.3 @@ -74,6 +74,12 @@
     1.4  # no xlc counterpart for -fcheck-new
     1.5  # CFLAGS += -fcheck-new
     1.6  
     1.7 +# We need to define this on the command line if we want to use the the
     1.8 +# predefined format specifiers from "inttypes.h". Otherwise system headrs
     1.9 +# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS
    1.10 +# in globalDefinitions.hpp
    1.11 +CFLAGS += -D__STDC_FORMAT_MACROS
    1.12 +
    1.13  ARCHFLAG = -q64
    1.14  
    1.15  CFLAGS     += $(ARCHFLAG)
     2.1 --- a/src/os/aix/vm/perfMemory_aix.cpp	Wed Jan 21 12:19:39 2015 -0800
     2.2 +++ b/src/os/aix/vm/perfMemory_aix.cpp	Tue Jan 13 16:09:52 2015 +0100
     2.3 @@ -31,6 +31,7 @@
     2.4  #include "os_aix.inline.hpp"
     2.5  #include "runtime/handles.inline.hpp"
     2.6  #include "runtime/perfMemory.hpp"
     2.7 +#include "services/memTracker.hpp"
     2.8  #include "utilities/exceptions.hpp"
     2.9  
    2.10  // put OS-includes here
    2.11 @@ -196,12 +197,37 @@
    2.12    return pid;
    2.13  }
    2.14  
    2.15 +// Check if the given statbuf is considered a secure directory for
    2.16 +// the backing store files. Returns true if the directory is considered
    2.17 +// a secure location. Returns false if the statbuf is a symbolic link or
    2.18 +// if an error occurred.
    2.19 +static bool is_statbuf_secure(struct stat *statp) {
    2.20 +  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
    2.21 +    // The path represents a link or some non-directory file type,
    2.22 +    // which is not what we expected. Declare it insecure.
    2.23 +    //
    2.24 +    return false;
    2.25 +  }
    2.26 +  // We have an existing directory, check if the permissions are safe.
    2.27 +  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    2.28 +    // The directory is open for writing and could be subjected
    2.29 +    // to a symlink or a hard link attack. Declare it insecure.
    2.30 +    return false;
    2.31 +  }
    2.32 +  // See if the uid of the directory matches the effective uid of the process.
    2.33 +  //
    2.34 +  if (statp->st_uid != geteuid()) {
    2.35 +    // The directory was not created by this user, declare it insecure.
    2.36 +    return false;
    2.37 +  }
    2.38 +  return true;
    2.39 +}
    2.40  
    2.41 -// check if the given path is considered a secure directory for
    2.42 +
    2.43 +// Check if the given path is considered a secure directory for
    2.44  // the backing store files. Returns true if the directory exists
    2.45  // and is considered a secure location. Returns false if the path
    2.46  // is a symbolic link or if an error occurred.
    2.47 -//
    2.48  static bool is_directory_secure(const char* path) {
    2.49    struct stat statbuf;
    2.50    int result = 0;
    2.51 @@ -211,38 +237,276 @@
    2.52      return false;
    2.53    }
    2.54  
    2.55 -  // the path exists, now check it's mode
    2.56 -  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
    2.57 -    // the path represents a link or some non-directory file type,
    2.58 -    // which is not what we expected. declare it insecure.
    2.59 -    //
    2.60 +  // The path exists, see if it is secure.
    2.61 +  return is_statbuf_secure(&statbuf);
    2.62 +}
    2.63 +
    2.64 +// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
    2.65 +// Check if the given directory file descriptor is considered a secure
    2.66 +// directory for the backing store files. Returns true if the directory
    2.67 +// exists and is considered a secure location. Returns false if the path
    2.68 +// is a symbolic link or if an error occurred.
    2.69 +static bool is_dirfd_secure(int dir_fd) {
    2.70 +  struct stat statbuf;
    2.71 +  int result = 0;
    2.72 +
    2.73 +  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
    2.74 +  if (result == OS_ERR) {
    2.75      return false;
    2.76    }
    2.77 -  else {
    2.78 -    // we have an existing directory, check if the permissions are safe.
    2.79 -    //
    2.80 -    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    2.81 -      // the directory is open for writing and could be subjected
    2.82 -      // to a symlnk attack. declare it insecure.
    2.83 -      //
    2.84 -      return false;
    2.85 +
    2.86 +  // The path exists, now check its mode.
    2.87 +  return is_statbuf_secure(&statbuf);
    2.88 +}
    2.89 +
    2.90 +
    2.91 +// Check to make sure fd1 and fd2 are referencing the same file system object.
    2.92 +static bool is_same_fsobject(int fd1, int fd2) {
    2.93 +  struct stat statbuf1;
    2.94 +  struct stat statbuf2;
    2.95 +  int result = 0;
    2.96 +
    2.97 +  RESTARTABLE(::fstat(fd1, &statbuf1), result);
    2.98 +  if (result == OS_ERR) {
    2.99 +    return false;
   2.100 +  }
   2.101 +  RESTARTABLE(::fstat(fd2, &statbuf2), result);
   2.102 +  if (result == OS_ERR) {
   2.103 +    return false;
   2.104 +  }
   2.105 +
   2.106 +  if ((statbuf1.st_ino == statbuf2.st_ino) &&
   2.107 +      (statbuf1.st_dev == statbuf2.st_dev)) {
   2.108 +    return true;
   2.109 +  } else {
   2.110 +    return false;
   2.111 +  }
   2.112 +}
   2.113 +
   2.114 +// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
   2.115 +// We use the jdk6 implementation here.
   2.116 +#ifndef O_NOFOLLOW
   2.117 +// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
   2.118 +// was done in jdk 5/6 hotspot by Oracle this way
   2.119 +static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
   2.120 +  struct stat orig_st;
   2.121 +  struct stat new_st;
   2.122 +  bool create;
   2.123 +  int error;
   2.124 +  int fd;
   2.125 +
   2.126 +  create = false;
   2.127 +
   2.128 +  if (lstat(path, &orig_st) != 0) {
   2.129 +    if (errno == ENOENT && (oflag & O_CREAT) != 0) {
   2.130 +      // File doesn't exist, but_we want to create it, add O_EXCL flag
   2.131 +      // to make sure no-one creates it (or a symlink) before us
   2.132 +      // This works as we expect with symlinks, from posix man page:
   2.133 +      // 'If O_EXCL  and  O_CREAT  are set, and path names a symbolic
   2.134 +      // link, open() shall fail and set errno to [EEXIST]'.
   2.135 +      oflag |= O_EXCL;
   2.136 +      create = true;
   2.137 +    } else {
   2.138 +      // File doesn't exist, and we are not creating it.
   2.139 +      return OS_ERR;
   2.140      }
   2.141 +  } else {
   2.142 +    // Lstat success, check if existing file is a link.
   2.143 +    if ((orig_st.st_mode & S_IFMT) == S_IFLNK)  {
   2.144 +      // File is a symlink.
   2.145 +      errno = ELOOP;
   2.146 +      return OS_ERR;
   2.147 +    }
   2.148 +  }
   2.149 +
   2.150 +  if (use_mode == true) {
   2.151 +    fd = open(path, oflag, mode);
   2.152 +  } else {
   2.153 +    fd = open(path, oflag);
   2.154 +  }
   2.155 +
   2.156 +  if (fd == OS_ERR) {
   2.157 +    return fd;
   2.158 +  }
   2.159 +
   2.160 +  // Can't do inode checks on before/after if we created the file.
   2.161 +  if (create == false) {
   2.162 +    if (fstat(fd, &new_st) != 0) {
   2.163 +      // Keep errno from fstat, in case close also fails.
   2.164 +      error = errno;
   2.165 +      ::close(fd);
   2.166 +      errno = error;
   2.167 +      return OS_ERR;
   2.168 +    }
   2.169 +
   2.170 +    if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
   2.171 +      // File was tampered with during race window.
   2.172 +      ::close(fd);
   2.173 +      errno = EEXIST;
   2.174 +      if (PrintMiscellaneous && Verbose) {
   2.175 +        warning("possible file tampering attempt detected when opening %s", path);
   2.176 +      }
   2.177 +      return OS_ERR;
   2.178 +    }
   2.179 +  }
   2.180 +
   2.181 +  return fd;
   2.182 +}
   2.183 +
   2.184 +static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
   2.185 +  return open_o_nofollow_impl(path, oflag, mode, true);
   2.186 +}
   2.187 +
   2.188 +static int open_o_nofollow(const char* path, int oflag) {
   2.189 +  return open_o_nofollow_impl(path, oflag, 0, false);
   2.190 +}
   2.191 +#endif
   2.192 +
   2.193 +// Open the directory of the given path and validate it.
   2.194 +// Return a DIR * of the open directory.
   2.195 +static DIR *open_directory_secure(const char* dirname) {
   2.196 +  // Open the directory using open() so that it can be verified
   2.197 +  // to be secure by calling is_dirfd_secure(), opendir() and then check
   2.198 +  // to see if they are the same file system object.  This method does not
   2.199 +  // introduce a window of opportunity for the directory to be attacked that
   2.200 +  // calling opendir() and is_directory_secure() does.
   2.201 +  int result;
   2.202 +  DIR *dirp = NULL;
   2.203 +
   2.204 +  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
   2.205 +  // so provide a workaround in this case.
   2.206 +#ifdef O_NOFOLLOW
   2.207 +  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
   2.208 +#else
   2.209 +  // workaround (jdk6 coding)
   2.210 +  RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
   2.211 +#endif
   2.212 +
   2.213 +  if (result == OS_ERR) {
   2.214 +    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
   2.215 +    if (PrintMiscellaneous && Verbose) {
   2.216 +      if (errno == ELOOP) {
   2.217 +        warning("directory %s is a symlink and is not secure\n", dirname);
   2.218 +      } else {
   2.219 +        warning("could not open directory %s: %s\n", dirname, strerror(errno));
   2.220 +      }
   2.221 +    }
   2.222 +    return dirp;
   2.223 +  }
   2.224 +  int fd = result;
   2.225 +
   2.226 +  // Determine if the open directory is secure.
   2.227 +  if (!is_dirfd_secure(fd)) {
   2.228 +    // The directory is not a secure directory.
   2.229 +    os::close(fd);
   2.230 +    return dirp;
   2.231 +  }
   2.232 +
   2.233 +  // Open the directory.
   2.234 +  dirp = ::opendir(dirname);
   2.235 +  if (dirp == NULL) {
   2.236 +    // The directory doesn't exist, close fd and return.
   2.237 +    os::close(fd);
   2.238 +    return dirp;
   2.239 +  }
   2.240 +
   2.241 +  // Check to make sure fd and dirp are referencing the same file system object.
   2.242 +  if (!is_same_fsobject(fd, dirp->dd_fd)) {
   2.243 +    // The directory is not secure.
   2.244 +    os::close(fd);
   2.245 +    os::closedir(dirp);
   2.246 +    dirp = NULL;
   2.247 +    return dirp;
   2.248 +  }
   2.249 +
   2.250 +  // Close initial open now that we know directory is secure
   2.251 +  os::close(fd);
   2.252 +
   2.253 +  return dirp;
   2.254 +}
   2.255 +
   2.256 +// NOTE: The code below uses fchdir(), open() and unlink() because
   2.257 +// fdopendir(), openat() and unlinkat() are not supported on all
   2.258 +// versions.  Once the support for fdopendir(), openat() and unlinkat()
   2.259 +// is available on all supported versions the code can be changed
   2.260 +// to use these functions.
   2.261 +
   2.262 +// Open the directory of the given path, validate it and set the
   2.263 +// current working directory to it.
   2.264 +// Return a DIR * of the open directory and the saved cwd fd.
   2.265 +//
   2.266 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
   2.267 +
   2.268 +  // Open the directory.
   2.269 +  DIR* dirp = open_directory_secure(dirname);
   2.270 +  if (dirp == NULL) {
   2.271 +    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
   2.272 +    return dirp;
   2.273 +  }
   2.274 +  int fd = dirp->dd_fd;
   2.275 +
   2.276 +  // Open a fd to the cwd and save it off.
   2.277 +  int result;
   2.278 +  RESTARTABLE(::open(".", O_RDONLY), result);
   2.279 +  if (result == OS_ERR) {
   2.280 +    *saved_cwd_fd = -1;
   2.281 +  } else {
   2.282 +    *saved_cwd_fd = result;
   2.283 +  }
   2.284 +
   2.285 +  // Set the current directory to dirname by using the fd of the directory.
   2.286 +  result = fchdir(fd);
   2.287 +
   2.288 +  return dirp;
   2.289 +}
   2.290 +
   2.291 +// Close the directory and restore the current working directory.
   2.292 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
   2.293 +
   2.294 +  int result;
   2.295 +  // If we have a saved cwd change back to it and close the fd.
   2.296 +  if (saved_cwd_fd != -1) {
   2.297 +    result = fchdir(saved_cwd_fd);
   2.298 +    ::close(saved_cwd_fd);
   2.299 +  }
   2.300 +
   2.301 +  // Close the directory.
   2.302 +  os::closedir(dirp);
   2.303 +}
   2.304 +
   2.305 +// Check if the given file descriptor is considered a secure.
   2.306 +static bool is_file_secure(int fd, const char *filename) {
   2.307 +
   2.308 +  int result;
   2.309 +  struct stat statbuf;
   2.310 +
   2.311 +  // Determine if the file is secure.
   2.312 +  RESTARTABLE(::fstat(fd, &statbuf), result);
   2.313 +  if (result == OS_ERR) {
   2.314 +    if (PrintMiscellaneous && Verbose) {
   2.315 +      warning("fstat failed on %s: %s\n", filename, strerror(errno));
   2.316 +    }
   2.317 +    return false;
   2.318 +  }
   2.319 +  if (statbuf.st_nlink > 1) {
   2.320 +    // A file with multiple links is not expected.
   2.321 +    if (PrintMiscellaneous && Verbose) {
   2.322 +      warning("file %s has multiple links\n", filename);
   2.323 +    }
   2.324 +    return false;
   2.325    }
   2.326    return true;
   2.327  }
   2.328  
   2.329 -
   2.330 -// return the user name for the given user id
   2.331 +// Return the user name for the given user id.
   2.332  //
   2.333 -// the caller is expected to free the allocated memory.
   2.334 -//
   2.335 +// The caller is expected to free the allocated memory.
   2.336  static char* get_user_name(uid_t uid) {
   2.337  
   2.338    struct passwd pwent;
   2.339  
   2.340 -  // determine the max pwbuf size from sysconf, and hardcode
   2.341 +  // Determine the max pwbuf size from sysconf, and hardcode
   2.342    // a default if this not available through sysconf.
   2.343 -  //
   2.344    long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
   2.345    if (bufsize == -1)
   2.346      bufsize = 1024;
   2.347 @@ -344,7 +608,8 @@
   2.348      strcat(usrdir_name, "/");
   2.349      strcat(usrdir_name, dentry->d_name);
   2.350  
   2.351 -    DIR* subdirp = os::opendir(usrdir_name);
   2.352 +    // Open the user directory.
   2.353 +    DIR* subdirp = open_directory_secure(usrdir_name);
   2.354  
   2.355      if (subdirp == NULL) {
   2.356        FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   2.357 @@ -464,28 +729,7 @@
   2.358    }
   2.359  }
   2.360  
   2.361 -
   2.362 -// remove file
   2.363 -//
   2.364 -// this method removes the file with the given file name in the
   2.365 -// named directory.
   2.366 -//
   2.367 -static void remove_file(const char* dirname, const char* filename) {
   2.368 -
   2.369 -  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
   2.370 -  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
   2.371 -
   2.372 -  strcpy(path, dirname);
   2.373 -  strcat(path, "/");
   2.374 -  strcat(path, filename);
   2.375 -
   2.376 -  remove_file(path);
   2.377 -
   2.378 -  FREE_C_HEAP_ARRAY(char, path, mtInternal);
   2.379 -}
   2.380 -
   2.381 -
   2.382 -// cleanup stale shared memory resources
   2.383 +// Cleanup stale shared memory resources
   2.384  //
   2.385  // This method attempts to remove all stale shared memory files in
   2.386  // the named user temporary directory. It scans the named directory
   2.387 @@ -493,32 +737,26 @@
   2.388  // process id is extracted from the file name and a test is run to
   2.389  // determine if the process is alive. If the process is not alive,
   2.390  // any stale file resources are removed.
   2.391 -//
   2.392  static void cleanup_sharedmem_resources(const char* dirname) {
   2.393  
   2.394 -  // open the user temp directory
   2.395 -  DIR* dirp = os::opendir(dirname);
   2.396 -
   2.397 +  int saved_cwd_fd;
   2.398 +  // Open the directory.
   2.399 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   2.400    if (dirp == NULL) {
   2.401 -    // directory doesn't exist, so there is nothing to cleanup
   2.402 +     // Directory doesn't exist or is insecure, so there is nothing to cleanup.
   2.403      return;
   2.404    }
   2.405  
   2.406 -  if (!is_directory_secure(dirname)) {
   2.407 -    // the directory is not a secure directory
   2.408 -    return;
   2.409 -  }
   2.410 -
   2.411 -  // for each entry in the directory that matches the expected file
   2.412 +  // For each entry in the directory that matches the expected file
   2.413    // name pattern, determine if the file resources are stale and if
   2.414    // so, remove the file resources. Note, instrumented HotSpot processes
   2.415    // for this user may start and/or terminate during this search and
   2.416    // remove or create new files in this directory. The behavior of this
   2.417    // loop under these conditions is dependent upon the implementation of
   2.418    // opendir/readdir.
   2.419 -  //
   2.420    struct dirent* entry;
   2.421    char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
   2.422 +
   2.423    errno = 0;
   2.424    while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
   2.425  
   2.426 @@ -528,56 +766,55 @@
   2.427  
   2.428        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
   2.429  
   2.430 -        // attempt to remove all unexpected files, except "." and ".."
   2.431 -        remove_file(dirname, entry->d_name);
   2.432 +        // Attempt to remove all unexpected files, except "." and "..".
   2.433 +        unlink(entry->d_name);
   2.434        }
   2.435  
   2.436        errno = 0;
   2.437        continue;
   2.438      }
   2.439  
   2.440 -    // we now have a file name that converts to a valid integer
   2.441 +    // We now have a file name that converts to a valid integer
   2.442      // that could represent a process id . if this process id
   2.443      // matches the current process id or the process is not running,
   2.444      // then remove the stale file resources.
   2.445      //
   2.446 -    // process liveness is detected by sending signal number 0 to
   2.447 +    // Process liveness is detected by sending signal number 0 to
   2.448      // the process id (see kill(2)). if kill determines that the
   2.449      // process does not exist, then the file resources are removed.
   2.450      // if kill determines that that we don't have permission to
   2.451      // signal the process, then the file resources are assumed to
   2.452      // be stale and are removed because the resources for such a
   2.453      // process should be in a different user specific directory.
   2.454 -    //
   2.455      if ((pid == os::current_process_id()) ||
   2.456          (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
   2.457  
   2.458 -        remove_file(dirname, entry->d_name);
   2.459 +        unlink(entry->d_name);
   2.460      }
   2.461      errno = 0;
   2.462    }
   2.463 -  os::closedir(dirp);
   2.464 +
   2.465 +  // Close the directory and reset the current working directory.
   2.466 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.467 +
   2.468    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   2.469  }
   2.470  
   2.471 -// make the user specific temporary directory. Returns true if
   2.472 +// Make the user specific temporary directory. Returns true if
   2.473  // the directory exists and is secure upon return. Returns false
   2.474  // if the directory exists but is either a symlink, is otherwise
   2.475  // insecure, or if an error occurred.
   2.476 -//
   2.477  static bool make_user_tmp_dir(const char* dirname) {
   2.478  
   2.479 -  // create the directory with 0755 permissions. note that the directory
   2.480 +  // Create the directory with 0755 permissions. note that the directory
   2.481    // will be owned by euid::egid, which may not be the same as uid::gid.
   2.482 -  //
   2.483    if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
   2.484      if (errno == EEXIST) {
   2.485        // The directory already exists and was probably created by another
   2.486        // JVM instance. However, this could also be the result of a
   2.487        // deliberate symlink. Verify that the existing directory is safe.
   2.488 -      //
   2.489        if (!is_directory_secure(dirname)) {
   2.490 -        // directory is not secure
   2.491 +        // Directory is not secure.
   2.492          if (PrintMiscellaneous && Verbose) {
   2.493            warning("%s directory is insecure\n", dirname);
   2.494          }
   2.495 @@ -613,19 +850,63 @@
   2.496      return -1;
   2.497    }
   2.498  
   2.499 +  int saved_cwd_fd;
   2.500 +  // Open the directory and set the current working directory to it.
   2.501 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   2.502 +  if (dirp == NULL) {
   2.503 +    // Directory doesn't exist or is insecure, so cannot create shared
   2.504 +    // memory file.
   2.505 +    return -1;
   2.506 +  }
   2.507 +
   2.508 +  // Open the filename in the current directory.
   2.509 +  // Cannot use O_TRUNC here; truncation of an existing file has to happen
   2.510 +  // after the is_file_secure() check below.
   2.511    int result;
   2.512  
   2.513 -  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
   2.514 +  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
   2.515 +  // so provide a workaround in this case.
   2.516 +#ifdef O_NOFOLLOW
   2.517 +  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   2.518 +#else
   2.519 +  // workaround function (jdk6 code)
   2.520 +  RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
   2.521 +#endif
   2.522 +
   2.523    if (result == OS_ERR) {
   2.524      if (PrintMiscellaneous && Verbose) {
   2.525 -      warning("could not create file %s: %s\n", filename, strerror(errno));
   2.526 +      if (errno == ELOOP) {
   2.527 +        warning("file %s is a symlink and is not secure\n", filename);
   2.528 +      } else {
   2.529 +        warning("could not create file %s: %s\n", filename, strerror(errno));
   2.530 +      }
   2.531      }
   2.532 +    // Close the directory and reset the current working directory.
   2.533 +    close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.534 +
   2.535      return -1;
   2.536    }
   2.537 +  // Close the directory and reset the current working directory.
   2.538 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.539  
   2.540    // save the file descriptor
   2.541    int fd = result;
   2.542  
   2.543 +  // Check to see if the file is secure.
   2.544 +  if (!is_file_secure(fd, filename)) {
   2.545 +    ::close(fd);
   2.546 +    return -1;
   2.547 +  }
   2.548 +
   2.549 +  // Truncate the file to get rid of any existing data.
   2.550 +  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
   2.551 +  if (result == OS_ERR) {
   2.552 +    if (PrintMiscellaneous && Verbose) {
   2.553 +      warning("could not truncate shared memory file: %s\n", strerror(errno));
   2.554 +    }
   2.555 +    ::close(fd);
   2.556 +    return -1;
   2.557 +  }
   2.558    // set the file size
   2.559    RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   2.560    if (result == OS_ERR) {
   2.561 @@ -647,7 +928,14 @@
   2.562  
   2.563    // open the file
   2.564    int result;
   2.565 +  // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
   2.566 +  // so provide a workaround in this case
   2.567 +#ifdef O_NOFOLLOW
   2.568    RESTARTABLE(::open(filename, oflags), result);
   2.569 +#else
   2.570 +  RESTARTABLE(::open_o_nofollow(filename, oflags), result);
   2.571 +#endif
   2.572 +
   2.573    if (result == OS_ERR) {
   2.574      if (errno == ENOENT) {
   2.575        THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
   2.576 @@ -661,8 +949,15 @@
   2.577        THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
   2.578      }
   2.579    }
   2.580 +  int fd = result;
   2.581  
   2.582 -  return result;
   2.583 +  // Check to see if the file is secure.
   2.584 +  if (!is_file_secure(fd, filename)) {
   2.585 +    ::close(fd);
   2.586 +    return -1;
   2.587 +  }
   2.588 +
   2.589 +  return fd;
   2.590  }
   2.591  
   2.592  // create a named shared memory region. returns the address of the
   2.593 @@ -694,13 +989,21 @@
   2.594    char* dirname = get_user_tmp_dir(user_name);
   2.595    char* filename = get_sharedmem_filename(dirname, vmid);
   2.596  
   2.597 +  // Get the short filename.
   2.598 +  char* short_filename = strrchr(filename, '/');
   2.599 +  if (short_filename == NULL) {
   2.600 +    short_filename = filename;
   2.601 +  } else {
   2.602 +    short_filename++;
   2.603 +  }
   2.604 +
   2.605    // cleanup any stale shared memory files
   2.606    cleanup_sharedmem_resources(dirname);
   2.607  
   2.608    assert(((size > 0) && (size % os::vm_page_size() == 0)),
   2.609           "unexpected PerfMemory region size");
   2.610  
   2.611 -  fd = create_sharedmem_resources(dirname, filename, size);
   2.612 +  fd = create_sharedmem_resources(dirname, short_filename, size);
   2.613  
   2.614    FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   2.615    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
   2.616 @@ -732,6 +1035,9 @@
   2.617    // clear the shared memory region
   2.618    (void)::memset((void*) mapAddress, 0, size);
   2.619  
   2.620 +  // It does not go through os api, the operation has to record from here.
   2.621 +  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
   2.622 +
   2.623    return mapAddress;
   2.624  }
   2.625  
   2.626 @@ -806,7 +1112,7 @@
   2.627    char* mapAddress;
   2.628    int result;
   2.629    int fd;
   2.630 -  size_t size;
   2.631 +  size_t size = 0;
   2.632    const char* luser = NULL;
   2.633  
   2.634    int mmap_prot;
   2.635 @@ -818,12 +1124,18 @@
   2.636    // constructs for the file and the shared memory mapping.
   2.637    if (mode == PerfMemory::PERF_MODE_RO) {
   2.638      mmap_prot = PROT_READ;
   2.639 +
   2.640 +  // No O_NOFOLLOW defined at buildtime, and it is not documented for open.
   2.641 +#ifdef O_NOFOLLOW
   2.642 +    file_flags = O_RDONLY | O_NOFOLLOW;
   2.643 +#else
   2.644      file_flags = O_RDONLY;
   2.645 +#endif
   2.646    }
   2.647    else if (mode == PerfMemory::PERF_MODE_RW) {
   2.648  #ifdef LATER
   2.649      mmap_prot = PROT_READ | PROT_WRITE;
   2.650 -    file_flags = O_RDWR;
   2.651 +    file_flags = O_RDWR | O_NOFOLLOW;
   2.652  #else
   2.653      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
   2.654                "Unsupported access mode");
   2.655 @@ -853,6 +1165,9 @@
   2.656    //
   2.657    if (!is_directory_secure(dirname)) {
   2.658      FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
   2.659 +    if (luser != user) {
   2.660 +      FREE_C_HEAP_ARRAY(char, luser, mtInternal);
   2.661 +    }
   2.662      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
   2.663                "Process not found");
   2.664    }
   2.665 @@ -897,6 +1212,9 @@
   2.666                "Could not map PerfMemory");
   2.667    }
   2.668  
   2.669 +  // It does not go through os api, the operation has to record from here.
   2.670 +  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
   2.671 +
   2.672    *addr = mapAddress;
   2.673    *sizep = size;
   2.674  

mercurial