Merge

Fri, 31 Oct 2014 17:09:14 -0700

author
asaha
date
Fri, 31 Oct 2014 17:09:14 -0700
changeset 7709
5ca2ea5eeff0
parent 7708
12478c5eb000
parent 7707
60a992c821f8
child 7710
b1cf34d57e78

Merge

src/os/bsd/vm/perfMemory_bsd.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/perfMemory_linux.cpp file | annotate | diff | comparison | revisions
src/os/solaris/vm/perfMemory_solaris.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/vmError.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/os/bsd/vm/perfMemory_bsd.cpp	Fri Oct 24 17:09:30 2014 -0700
     1.2 +++ b/src/os/bsd/vm/perfMemory_bsd.cpp	Fri Oct 31 17:09:14 2014 -0700
     1.3 @@ -197,7 +197,38 @@
     1.4  }
     1.5  
     1.6  
     1.7 -// check if the given path is considered a secure directory for
     1.8 +// Check if the given statbuf is considered a secure directory for
     1.9 +// the backing store files. Returns true if the directory is considered
    1.10 +// a secure location. Returns false if the statbuf is a symbolic link or
    1.11 +// if an error occurred.
    1.12 +//
    1.13 +static bool is_statbuf_secure(struct stat *statp) {
    1.14 +  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
    1.15 +    // The path represents a link or some non-directory file type,
    1.16 +    // which is not what we expected. Declare it insecure.
    1.17 +    //
    1.18 +    return false;
    1.19 +  }
    1.20 +  // We have an existing directory, check if the permissions are safe.
    1.21 +  //
    1.22 +  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    1.23 +    // The directory is open for writing and could be subjected
    1.24 +    // to a symlink or a hard link attack. Declare it insecure.
    1.25 +    //
    1.26 +    return false;
    1.27 +  }
    1.28 +  // See if the uid of the directory matches the effective uid of the process.
    1.29 +  //
    1.30 +  if (statp->st_uid != geteuid()) {
    1.31 +    // The directory was not created by this user, declare it insecure.
    1.32 +    //
    1.33 +    return false;
    1.34 +  }
    1.35 +  return true;
    1.36 +}
    1.37 +
    1.38 +
    1.39 +// Check if the given path is considered a secure directory for
    1.40  // the backing store files. Returns true if the directory exists
    1.41  // and is considered a secure location. Returns false if the path
    1.42  // is a symbolic link or if an error occurred.
    1.43 @@ -211,27 +242,185 @@
    1.44      return false;
    1.45    }
    1.46  
    1.47 -  // the path exists, now check it's mode
    1.48 -  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
    1.49 -    // the path represents a link or some non-directory file type,
    1.50 -    // which is not what we expected. declare it insecure.
    1.51 -    //
    1.52 +  // The path exists, see if it is secure.
    1.53 +  return is_statbuf_secure(&statbuf);
    1.54 +}
    1.55 +
    1.56 +
    1.57 +// Check if the given directory file descriptor is considered a secure
    1.58 +// directory for the backing store files. Returns true if the directory
    1.59 +// exists and is considered a secure location. Returns false if the path
    1.60 +// is a symbolic link or if an error occurred.
    1.61 +//
    1.62 +static bool is_dirfd_secure(int dir_fd) {
    1.63 +  struct stat statbuf;
    1.64 +  int result = 0;
    1.65 +
    1.66 +  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
    1.67 +  if (result == OS_ERR) {
    1.68      return false;
    1.69    }
    1.70 -  else {
    1.71 -    // we have an existing directory, check if the permissions are safe.
    1.72 -    //
    1.73 -    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    1.74 -      // the directory is open for writing and could be subjected
    1.75 -      // to a symlnk attack. declare it insecure.
    1.76 -      //
    1.77 -      return false;
    1.78 +
    1.79 +  // The path exists, now check its mode.
    1.80 +  return is_statbuf_secure(&statbuf);
    1.81 +}
    1.82 +
    1.83 +
    1.84 +// Check to make sure fd1 and fd2 are referencing the same file system object.
    1.85 +//
    1.86 +static bool is_same_fsobject(int fd1, int fd2) {
    1.87 +  struct stat statbuf1;
    1.88 +  struct stat statbuf2;
    1.89 +  int result = 0;
    1.90 +
    1.91 +  RESTARTABLE(::fstat(fd1, &statbuf1), result);
    1.92 +  if (result == OS_ERR) {
    1.93 +    return false;
    1.94 +  }
    1.95 +  RESTARTABLE(::fstat(fd2, &statbuf2), result);
    1.96 +  if (result == OS_ERR) {
    1.97 +    return false;
    1.98 +  }
    1.99 +
   1.100 +  if ((statbuf1.st_ino == statbuf2.st_ino) &&
   1.101 +      (statbuf1.st_dev == statbuf2.st_dev)) {
   1.102 +    return true;
   1.103 +  } else {
   1.104 +    return false;
   1.105 +  }
   1.106 +}
   1.107 +
   1.108 +
   1.109 +// Open the directory of the given path and validate it.
   1.110 +// Return a DIR * of the open directory.
   1.111 +//
   1.112 +static DIR *open_directory_secure(const char* dirname) {
   1.113 +  // Open the directory using open() so that it can be verified
   1.114 +  // to be secure by calling is_dirfd_secure(), opendir() and then check
   1.115 +  // to see if they are the same file system object.  This method does not
   1.116 +  // introduce a window of opportunity for the directory to be attacked that
   1.117 +  // calling opendir() and is_directory_secure() does.
   1.118 +  int result;
   1.119 +  DIR *dirp = NULL;
   1.120 +  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
   1.121 +  if (result == OS_ERR) {
   1.122 +    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
   1.123 +    if (PrintMiscellaneous && Verbose) {
   1.124 +      if (errno == ELOOP) {
   1.125 +        warning("directory %s is a symlink and is not secure\n", dirname);
   1.126 +      } else {
   1.127 +        warning("could not open directory %s: %s\n", dirname, strerror(errno));
   1.128 +      }
   1.129      }
   1.130 +    return dirp;
   1.131 +  }
   1.132 +  int fd = result;
   1.133 +
   1.134 +  // Determine if the open directory is secure.
   1.135 +  if (!is_dirfd_secure(fd)) {
   1.136 +    // The directory is not a secure directory.
   1.137 +    os::close(fd);
   1.138 +    return dirp;
   1.139 +  }
   1.140 +
   1.141 +  // Open the directory.
   1.142 +  dirp = ::opendir(dirname);
   1.143 +  if (dirp == NULL) {
   1.144 +    // The directory doesn't exist, close fd and return.
   1.145 +    os::close(fd);
   1.146 +    return dirp;
   1.147 +  }
   1.148 +
   1.149 +  // Check to make sure fd and dirp are referencing the same file system object.
   1.150 +  if (!is_same_fsobject(fd, dirfd(dirp))) {
   1.151 +    // The directory is not secure.
   1.152 +    os::close(fd);
   1.153 +    os::closedir(dirp);
   1.154 +    dirp = NULL;
   1.155 +    return dirp;
   1.156 +  }
   1.157 +
   1.158 +  // Close initial open now that we know directory is secure
   1.159 +  os::close(fd);
   1.160 +
   1.161 +  return dirp;
   1.162 +}
   1.163 +
   1.164 +// NOTE: The code below uses fchdir(), open() and unlink() because
   1.165 +// fdopendir(), openat() and unlinkat() are not supported on all
   1.166 +// versions.  Once the support for fdopendir(), openat() and unlinkat()
   1.167 +// is available on all supported versions the code can be changed
   1.168 +// to use these functions.
   1.169 +
   1.170 +// Open the directory of the given path, validate it and set the
   1.171 +// current working directory to it.
   1.172 +// Return a DIR * of the open directory and the saved cwd fd.
   1.173 +//
   1.174 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
   1.175 +
   1.176 +  // Open the directory.
   1.177 +  DIR* dirp = open_directory_secure(dirname);
   1.178 +  if (dirp == NULL) {
   1.179 +    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
   1.180 +    return dirp;
   1.181 +  }
   1.182 +  int fd = dirfd(dirp);
   1.183 +
   1.184 +  // Open a fd to the cwd and save it off.
   1.185 +  int result;
   1.186 +  RESTARTABLE(::open(".", O_RDONLY), result);
   1.187 +  if (result == OS_ERR) {
   1.188 +    *saved_cwd_fd = -1;
   1.189 +  } else {
   1.190 +    *saved_cwd_fd = result;
   1.191 +  }
   1.192 +
   1.193 +  // Set the current directory to dirname by using the fd of the directory.
   1.194 +  result = fchdir(fd);
   1.195 +
   1.196 +  return dirp;
   1.197 +}
   1.198 +
   1.199 +// Close the directory and restore the current working directory.
   1.200 +//
   1.201 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
   1.202 +
   1.203 +  int result;
   1.204 +  // If we have a saved cwd change back to it and close the fd.
   1.205 +  if (saved_cwd_fd != -1) {
   1.206 +    result = fchdir(saved_cwd_fd);
   1.207 +    ::close(saved_cwd_fd);
   1.208 +  }
   1.209 +
   1.210 +  // Close the directory.
   1.211 +  os::closedir(dirp);
   1.212 +}
   1.213 +
   1.214 +// Check if the given file descriptor is considered a secure.
   1.215 +//
   1.216 +static bool is_file_secure(int fd, const char *filename) {
   1.217 +
   1.218 +  int result;
   1.219 +  struct stat statbuf;
   1.220 +
   1.221 +  // Determine if the file is secure.
   1.222 +  RESTARTABLE(::fstat(fd, &statbuf), result);
   1.223 +  if (result == OS_ERR) {
   1.224 +    if (PrintMiscellaneous && Verbose) {
   1.225 +      warning("fstat failed on %s: %s\n", filename, strerror(errno));
   1.226 +    }
   1.227 +    return false;
   1.228 +  }
   1.229 +  if (statbuf.st_nlink > 1) {
   1.230 +    // A file with multiple links is not expected.
   1.231 +    if (PrintMiscellaneous && Verbose) {
   1.232 +      warning("file %s has multiple links\n", filename);
   1.233 +    }
   1.234 +    return false;
   1.235    }
   1.236    return true;
   1.237  }
   1.238  
   1.239 -
   1.240  // return the user name for the given user id
   1.241  //
   1.242  // the caller is expected to free the allocated memory.
   1.243 @@ -317,9 +506,10 @@
   1.244  
   1.245    const char* tmpdirname = os::get_temp_directory();
   1.246  
   1.247 -  DIR* tmpdirp = os::opendir(tmpdirname);
   1.248 -
   1.249 +  // open the temp directory
   1.250 +  DIR* tmpdirp = open_directory_secure(tmpdirname);
   1.251    if (tmpdirp == NULL) {
   1.252 +    // Cannot open the directory to get the user name, return.
   1.253      return NULL;
   1.254    }
   1.255  
   1.256 @@ -344,25 +534,14 @@
   1.257      strcat(usrdir_name, "/");
   1.258      strcat(usrdir_name, dentry->d_name);
   1.259  
   1.260 -    DIR* subdirp = os::opendir(usrdir_name);
   1.261 +    // open the user directory
   1.262 +    DIR* subdirp = open_directory_secure(usrdir_name);
   1.263  
   1.264      if (subdirp == NULL) {
   1.265        FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   1.266        continue;
   1.267      }
   1.268  
   1.269 -    // Since we don't create the backing store files in directories
   1.270 -    // pointed to by symbolic links, we also don't follow them when
   1.271 -    // looking for the files. We check for a symbolic link after the
   1.272 -    // call to opendir in order to eliminate a small window where the
   1.273 -    // symlink can be exploited.
   1.274 -    //
   1.275 -    if (!is_directory_secure(usrdir_name)) {
   1.276 -      FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   1.277 -      os::closedir(subdirp);
   1.278 -      continue;
   1.279 -    }
   1.280 -
   1.281      struct dirent* udentry;
   1.282      char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
   1.283      errno = 0;
   1.284 @@ -465,26 +644,6 @@
   1.285  }
   1.286  
   1.287  
   1.288 -// remove file
   1.289 -//
   1.290 -// this method removes the file with the given file name in the
   1.291 -// named directory.
   1.292 -//
   1.293 -static void remove_file(const char* dirname, const char* filename) {
   1.294 -
   1.295 -  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
   1.296 -  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
   1.297 -
   1.298 -  strcpy(path, dirname);
   1.299 -  strcat(path, "/");
   1.300 -  strcat(path, filename);
   1.301 -
   1.302 -  remove_file(path);
   1.303 -
   1.304 -  FREE_C_HEAP_ARRAY(char, path, mtInternal);
   1.305 -}
   1.306 -
   1.307 -
   1.308  // cleanup stale shared memory resources
   1.309  //
   1.310  // This method attempts to remove all stale shared memory files in
   1.311 @@ -496,16 +655,11 @@
   1.312  //
   1.313  static void cleanup_sharedmem_resources(const char* dirname) {
   1.314  
   1.315 -  // open the user temp directory
   1.316 -  DIR* dirp = os::opendir(dirname);
   1.317 -
   1.318 +  int saved_cwd_fd;
   1.319 +  // open the directory and set the current working directory to it
   1.320 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   1.321    if (dirp == NULL) {
   1.322 -    // directory doesn't exist, so there is nothing to cleanup
   1.323 -    return;
   1.324 -  }
   1.325 -
   1.326 -  if (!is_directory_secure(dirname)) {
   1.327 -    // the directory is not a secure directory
   1.328 +    // directory doesn't exist or is insecure, so there is nothing to cleanup
   1.329      return;
   1.330    }
   1.331  
   1.332 @@ -519,6 +673,7 @@
   1.333    //
   1.334    struct dirent* entry;
   1.335    char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
   1.336 +
   1.337    errno = 0;
   1.338    while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
   1.339  
   1.340 @@ -529,7 +684,7 @@
   1.341        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
   1.342  
   1.343          // attempt to remove all unexpected files, except "." and ".."
   1.344 -        remove_file(dirname, entry->d_name);
   1.345 +        unlink(entry->d_name);
   1.346        }
   1.347  
   1.348        errno = 0;
   1.349 @@ -552,11 +707,14 @@
   1.350      if ((pid == os::current_process_id()) ||
   1.351          (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
   1.352  
   1.353 -        remove_file(dirname, entry->d_name);
   1.354 +        unlink(entry->d_name);
   1.355      }
   1.356      errno = 0;
   1.357    }
   1.358 -  os::closedir(dirp);
   1.359 +
   1.360 +  // close the directory and reset the current working directory
   1.361 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   1.362 +
   1.363    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   1.364  }
   1.365  
   1.366 @@ -613,19 +771,54 @@
   1.367      return -1;
   1.368    }
   1.369  
   1.370 +  int saved_cwd_fd;
   1.371 +  // open the directory and set the current working directory to it
   1.372 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   1.373 +  if (dirp == NULL) {
   1.374 +    // Directory doesn't exist or is insecure, so cannot create shared
   1.375 +    // memory file.
   1.376 +    return -1;
   1.377 +  }
   1.378 +
   1.379 +  // Open the filename in the current directory.
   1.380 +  // Cannot use O_TRUNC here; truncation of an existing file has to happen
   1.381 +  // after the is_file_secure() check below.
   1.382    int result;
   1.383 -
   1.384 -  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
   1.385 +  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   1.386    if (result == OS_ERR) {
   1.387      if (PrintMiscellaneous && Verbose) {
   1.388 -      warning("could not create file %s: %s\n", filename, strerror(errno));
   1.389 +      if (errno == ELOOP) {
   1.390 +        warning("file %s is a symlink and is not secure\n", filename);
   1.391 +      } else {
   1.392 +        warning("could not create file %s: %s\n", filename, strerror(errno));
   1.393 +      }
   1.394      }
   1.395 +    // close the directory and reset the current working directory
   1.396 +    close_directory_secure_cwd(dirp, saved_cwd_fd);
   1.397 +
   1.398      return -1;
   1.399    }
   1.400 +  // close the directory and reset the current working directory
   1.401 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   1.402  
   1.403    // save the file descriptor
   1.404    int fd = result;
   1.405  
   1.406 +  // check to see if the file is secure
   1.407 +  if (!is_file_secure(fd, filename)) {
   1.408 +    ::close(fd);
   1.409 +    return -1;
   1.410 +  }
   1.411 +
   1.412 +  // truncate the file to get rid of any existing data
   1.413 +  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
   1.414 +  if (result == OS_ERR) {
   1.415 +    if (PrintMiscellaneous && Verbose) {
   1.416 +      warning("could not truncate shared memory file: %s\n", strerror(errno));
   1.417 +    }
   1.418 +    ::close(fd);
   1.419 +    return -1;
   1.420 +  }
   1.421    // set the file size
   1.422    RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   1.423    if (result == OS_ERR) {
   1.424 @@ -683,8 +876,15 @@
   1.425        THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
   1.426      }
   1.427    }
   1.428 +  int fd = result;
   1.429  
   1.430 -  return result;
   1.431 +  // check to see if the file is secure
   1.432 +  if (!is_file_secure(fd, filename)) {
   1.433 +    ::close(fd);
   1.434 +    return -1;
   1.435 +  }
   1.436 +
   1.437 +  return fd;
   1.438  }
   1.439  
   1.440  // create a named shared memory region. returns the address of the
   1.441 @@ -716,13 +916,21 @@
   1.442    char* dirname = get_user_tmp_dir(user_name);
   1.443    char* filename = get_sharedmem_filename(dirname, vmid);
   1.444  
   1.445 +  // get the short filename
   1.446 +  char* short_filename = strrchr(filename, '/');
   1.447 +  if (short_filename == NULL) {
   1.448 +    short_filename = filename;
   1.449 +  } else {
   1.450 +    short_filename++;
   1.451 +  }
   1.452 +
   1.453    // cleanup any stale shared memory files
   1.454    cleanup_sharedmem_resources(dirname);
   1.455  
   1.456    assert(((size > 0) && (size % os::vm_page_size() == 0)),
   1.457           "unexpected PerfMemory region size");
   1.458  
   1.459 -  fd = create_sharedmem_resources(dirname, filename, size);
   1.460 +  fd = create_sharedmem_resources(dirname, short_filename, size);
   1.461  
   1.462    FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   1.463    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
   1.464 @@ -837,12 +1045,12 @@
   1.465    // constructs for the file and the shared memory mapping.
   1.466    if (mode == PerfMemory::PERF_MODE_RO) {
   1.467      mmap_prot = PROT_READ;
   1.468 -    file_flags = O_RDONLY;
   1.469 +    file_flags = O_RDONLY | O_NOFOLLOW;
   1.470    }
   1.471    else if (mode == PerfMemory::PERF_MODE_RW) {
   1.472  #ifdef LATER
   1.473      mmap_prot = PROT_READ | PROT_WRITE;
   1.474 -    file_flags = O_RDWR;
   1.475 +    file_flags = O_RDWR | O_NOFOLLOW;
   1.476  #else
   1.477      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
   1.478                "Unsupported access mode");
     2.1 --- a/src/os/linux/vm/perfMemory_linux.cpp	Fri Oct 24 17:09:30 2014 -0700
     2.2 +++ b/src/os/linux/vm/perfMemory_linux.cpp	Fri Oct 31 17:09:14 2014 -0700
     2.3 @@ -197,7 +197,38 @@
     2.4  }
     2.5  
     2.6  
     2.7 -// check if the given path is considered a secure directory for
     2.8 +// Check if the given statbuf is considered a secure directory for
     2.9 +// the backing store files. Returns true if the directory is considered
    2.10 +// a secure location. Returns false if the statbuf is a symbolic link or
    2.11 +// if an error occurred.
    2.12 +//
    2.13 +static bool is_statbuf_secure(struct stat *statp) {
    2.14 +  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
    2.15 +    // The path represents a link or some non-directory file type,
    2.16 +    // which is not what we expected. Declare it insecure.
    2.17 +    //
    2.18 +    return false;
    2.19 +  }
    2.20 +  // We have an existing directory, check if the permissions are safe.
    2.21 +  //
    2.22 +  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    2.23 +    // The directory is open for writing and could be subjected
    2.24 +    // to a symlink or a hard link attack. Declare it insecure.
    2.25 +    //
    2.26 +    return false;
    2.27 +  }
    2.28 +  // See if the uid of the directory matches the effective uid of the process.
    2.29 +  //
    2.30 +  if (statp->st_uid != geteuid()) {
    2.31 +    // The directory was not created by this user, declare it insecure.
    2.32 +    //
    2.33 +    return false;
    2.34 +  }
    2.35 +  return true;
    2.36 +}
    2.37 +
    2.38 +
    2.39 +// Check if the given path is considered a secure directory for
    2.40  // the backing store files. Returns true if the directory exists
    2.41  // and is considered a secure location. Returns false if the path
    2.42  // is a symbolic link or if an error occurred.
    2.43 @@ -211,22 +242,181 @@
    2.44      return false;
    2.45    }
    2.46  
    2.47 -  // the path exists, now check it's mode
    2.48 -  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
    2.49 -    // the path represents a link or some non-directory file type,
    2.50 -    // which is not what we expected. declare it insecure.
    2.51 -    //
    2.52 +  // The path exists, see if it is secure.
    2.53 +  return is_statbuf_secure(&statbuf);
    2.54 +}
    2.55 +
    2.56 +
    2.57 +// Check if the given directory file descriptor is considered a secure
    2.58 +// directory for the backing store files. Returns true if the directory
    2.59 +// exists and is considered a secure location. Returns false if the path
    2.60 +// is a symbolic link or if an error occurred.
    2.61 +//
    2.62 +static bool is_dirfd_secure(int dir_fd) {
    2.63 +  struct stat statbuf;
    2.64 +  int result = 0;
    2.65 +
    2.66 +  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
    2.67 +  if (result == OS_ERR) {
    2.68      return false;
    2.69    }
    2.70 -  else {
    2.71 -    // we have an existing directory, check if the permissions are safe.
    2.72 -    //
    2.73 -    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    2.74 -      // the directory is open for writing and could be subjected
    2.75 -      // to a symlnk attack. declare it insecure.
    2.76 -      //
    2.77 -      return false;
    2.78 +
    2.79 +  // The path exists, now check its mode.
    2.80 +  return is_statbuf_secure(&statbuf);
    2.81 +}
    2.82 +
    2.83 +
    2.84 +// Check to make sure fd1 and fd2 are referencing the same file system object.
    2.85 +//
    2.86 +static bool is_same_fsobject(int fd1, int fd2) {
    2.87 +  struct stat statbuf1;
    2.88 +  struct stat statbuf2;
    2.89 +  int result = 0;
    2.90 +
    2.91 +  RESTARTABLE(::fstat(fd1, &statbuf1), result);
    2.92 +  if (result == OS_ERR) {
    2.93 +    return false;
    2.94 +  }
    2.95 +  RESTARTABLE(::fstat(fd2, &statbuf2), result);
    2.96 +  if (result == OS_ERR) {
    2.97 +    return false;
    2.98 +  }
    2.99 +
   2.100 +  if ((statbuf1.st_ino == statbuf2.st_ino) &&
   2.101 +      (statbuf1.st_dev == statbuf2.st_dev)) {
   2.102 +    return true;
   2.103 +  } else {
   2.104 +    return false;
   2.105 +  }
   2.106 +}
   2.107 +
   2.108 +
   2.109 +// Open the directory of the given path and validate it.
   2.110 +// Return a DIR * of the open directory.
   2.111 +//
   2.112 +static DIR *open_directory_secure(const char* dirname) {
   2.113 +  // Open the directory using open() so that it can be verified
   2.114 +  // to be secure by calling is_dirfd_secure(), opendir() and then check
   2.115 +  // to see if they are the same file system object.  This method does not
   2.116 +  // introduce a window of opportunity for the directory to be attacked that
   2.117 +  // calling opendir() and is_directory_secure() does.
   2.118 +  int result;
   2.119 +  DIR *dirp = NULL;
   2.120 +  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
   2.121 +  if (result == OS_ERR) {
   2.122 +    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
   2.123 +    if (PrintMiscellaneous && Verbose) {
   2.124 +      if (errno == ELOOP) {
   2.125 +        warning("directory %s is a symlink and is not secure\n", dirname);
   2.126 +      } else {
   2.127 +        warning("could not open directory %s: %s\n", dirname, strerror(errno));
   2.128 +      }
   2.129      }
   2.130 +    return dirp;
   2.131 +  }
   2.132 +  int fd = result;
   2.133 +
   2.134 +  // Determine if the open directory is secure.
   2.135 +  if (!is_dirfd_secure(fd)) {
   2.136 +    // The directory is not a secure directory.
   2.137 +    os::close(fd);
   2.138 +    return dirp;
   2.139 +  }
   2.140 +
   2.141 +  // Open the directory.
   2.142 +  dirp = ::opendir(dirname);
   2.143 +  if (dirp == NULL) {
   2.144 +    // The directory doesn't exist, close fd and return.
   2.145 +    os::close(fd);
   2.146 +    return dirp;
   2.147 +  }
   2.148 +
   2.149 +  // Check to make sure fd and dirp are referencing the same file system object.
   2.150 +  if (!is_same_fsobject(fd, dirfd(dirp))) {
   2.151 +    // The directory is not secure.
   2.152 +    os::close(fd);
   2.153 +    os::closedir(dirp);
   2.154 +    dirp = NULL;
   2.155 +    return dirp;
   2.156 +  }
   2.157 +
   2.158 +  // Close initial open now that we know directory is secure
   2.159 +  os::close(fd);
   2.160 +
   2.161 +  return dirp;
   2.162 +}
   2.163 +
   2.164 +// NOTE: The code below uses fchdir(), open() and unlink() because
   2.165 +// fdopendir(), openat() and unlinkat() are not supported on all
   2.166 +// versions.  Once the support for fdopendir(), openat() and unlinkat()
   2.167 +// is available on all supported versions the code can be changed
   2.168 +// to use these functions.
   2.169 +
   2.170 +// Open the directory of the given path, validate it and set the
   2.171 +// current working directory to it.
   2.172 +// Return a DIR * of the open directory and the saved cwd fd.
   2.173 +//
   2.174 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
   2.175 +
   2.176 +  // Open the directory.
   2.177 +  DIR* dirp = open_directory_secure(dirname);
   2.178 +  if (dirp == NULL) {
   2.179 +    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
   2.180 +    return dirp;
   2.181 +  }
   2.182 +  int fd = dirfd(dirp);
   2.183 +
   2.184 +  // Open a fd to the cwd and save it off.
   2.185 +  int result;
   2.186 +  RESTARTABLE(::open(".", O_RDONLY), result);
   2.187 +  if (result == OS_ERR) {
   2.188 +    *saved_cwd_fd = -1;
   2.189 +  } else {
   2.190 +    *saved_cwd_fd = result;
   2.191 +  }
   2.192 +
   2.193 +  // Set the current directory to dirname by using the fd of the directory.
   2.194 +  result = fchdir(fd);
   2.195 +
   2.196 +  return dirp;
   2.197 +}
   2.198 +
   2.199 +// Close the directory and restore the current working directory.
   2.200 +//
   2.201 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
   2.202 +
   2.203 +  int result;
   2.204 +  // If we have a saved cwd change back to it and close the fd.
   2.205 +  if (saved_cwd_fd != -1) {
   2.206 +    result = fchdir(saved_cwd_fd);
   2.207 +    ::close(saved_cwd_fd);
   2.208 +  }
   2.209 +
   2.210 +  // Close the directory.
   2.211 +  os::closedir(dirp);
   2.212 +}
   2.213 +
   2.214 +// Check if the given file descriptor is considered a secure.
   2.215 +//
   2.216 +static bool is_file_secure(int fd, const char *filename) {
   2.217 +
   2.218 +  int result;
   2.219 +  struct stat statbuf;
   2.220 +
   2.221 +  // Determine if the file is secure.
   2.222 +  RESTARTABLE(::fstat(fd, &statbuf), result);
   2.223 +  if (result == OS_ERR) {
   2.224 +    if (PrintMiscellaneous && Verbose) {
   2.225 +      warning("fstat failed on %s: %s\n", filename, strerror(errno));
   2.226 +    }
   2.227 +    return false;
   2.228 +  }
   2.229 +  if (statbuf.st_nlink > 1) {
   2.230 +    // A file with multiple links is not expected.
   2.231 +    if (PrintMiscellaneous && Verbose) {
   2.232 +      warning("file %s has multiple links\n", filename);
   2.233 +    }
   2.234 +    return false;
   2.235    }
   2.236    return true;
   2.237  }
   2.238 @@ -317,9 +507,10 @@
   2.239  
   2.240    const char* tmpdirname = os::get_temp_directory();
   2.241  
   2.242 -  DIR* tmpdirp = os::opendir(tmpdirname);
   2.243 -
   2.244 +  // open the temp directory
   2.245 +  DIR* tmpdirp = open_directory_secure(tmpdirname);
   2.246    if (tmpdirp == NULL) {
   2.247 +    // Cannot open the directory to get the user name, return.
   2.248      return NULL;
   2.249    }
   2.250  
   2.251 @@ -344,7 +535,8 @@
   2.252      strcat(usrdir_name, "/");
   2.253      strcat(usrdir_name, dentry->d_name);
   2.254  
   2.255 -    DIR* subdirp = os::opendir(usrdir_name);
   2.256 +    // open the user directory
   2.257 +    DIR* subdirp = open_directory_secure(usrdir_name);
   2.258  
   2.259      if (subdirp == NULL) {
   2.260        FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   2.261 @@ -465,26 +657,6 @@
   2.262  }
   2.263  
   2.264  
   2.265 -// remove file
   2.266 -//
   2.267 -// this method removes the file with the given file name in the
   2.268 -// named directory.
   2.269 -//
   2.270 -static void remove_file(const char* dirname, const char* filename) {
   2.271 -
   2.272 -  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
   2.273 -  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
   2.274 -
   2.275 -  strcpy(path, dirname);
   2.276 -  strcat(path, "/");
   2.277 -  strcat(path, filename);
   2.278 -
   2.279 -  remove_file(path);
   2.280 -
   2.281 -  FREE_C_HEAP_ARRAY(char, path, mtInternal);
   2.282 -}
   2.283 -
   2.284 -
   2.285  // cleanup stale shared memory resources
   2.286  //
   2.287  // This method attempts to remove all stale shared memory files in
   2.288 @@ -496,16 +668,11 @@
   2.289  //
   2.290  static void cleanup_sharedmem_resources(const char* dirname) {
   2.291  
   2.292 -  // open the user temp directory
   2.293 -  DIR* dirp = os::opendir(dirname);
   2.294 -
   2.295 +  int saved_cwd_fd;
   2.296 +  // open the directory
   2.297 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   2.298    if (dirp == NULL) {
   2.299 -    // directory doesn't exist, so there is nothing to cleanup
   2.300 -    return;
   2.301 -  }
   2.302 -
   2.303 -  if (!is_directory_secure(dirname)) {
   2.304 -    // the directory is not a secure directory
   2.305 +    // directory doesn't exist or is insecure, so there is nothing to cleanup
   2.306      return;
   2.307    }
   2.308  
   2.309 @@ -519,6 +686,7 @@
   2.310    //
   2.311    struct dirent* entry;
   2.312    char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
   2.313 +
   2.314    errno = 0;
   2.315    while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
   2.316  
   2.317 @@ -527,9 +695,8 @@
   2.318      if (pid == 0) {
   2.319  
   2.320        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
   2.321 -
   2.322          // attempt to remove all unexpected files, except "." and ".."
   2.323 -        remove_file(dirname, entry->d_name);
   2.324 +        unlink(entry->d_name);
   2.325        }
   2.326  
   2.327        errno = 0;
   2.328 @@ -551,12 +718,14 @@
   2.329      //
   2.330      if ((pid == os::current_process_id()) ||
   2.331          (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
   2.332 -
   2.333 -        remove_file(dirname, entry->d_name);
   2.334 +        unlink(entry->d_name);
   2.335      }
   2.336      errno = 0;
   2.337    }
   2.338 -  os::closedir(dirp);
   2.339 +
   2.340 +  // close the directory and reset the current working directory
   2.341 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.342 +
   2.343    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   2.344  }
   2.345  
   2.346 @@ -613,19 +782,54 @@
   2.347      return -1;
   2.348    }
   2.349  
   2.350 +  int saved_cwd_fd;
   2.351 +  // open the directory and set the current working directory to it
   2.352 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   2.353 +  if (dirp == NULL) {
   2.354 +    // Directory doesn't exist or is insecure, so cannot create shared
   2.355 +    // memory file.
   2.356 +    return -1;
   2.357 +  }
   2.358 +
   2.359 +  // Open the filename in the current directory.
   2.360 +  // Cannot use O_TRUNC here; truncation of an existing file has to happen
   2.361 +  // after the is_file_secure() check below.
   2.362    int result;
   2.363 -
   2.364 -  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
   2.365 +  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   2.366    if (result == OS_ERR) {
   2.367      if (PrintMiscellaneous && Verbose) {
   2.368 -      warning("could not create file %s: %s\n", filename, strerror(errno));
   2.369 +      if (errno == ELOOP) {
   2.370 +        warning("file %s is a symlink and is not secure\n", filename);
   2.371 +      } else {
   2.372 +        warning("could not create file %s: %s\n", filename, strerror(errno));
   2.373 +      }
   2.374      }
   2.375 +    // close the directory and reset the current working directory
   2.376 +    close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.377 +
   2.378      return -1;
   2.379    }
   2.380 +  // close the directory and reset the current working directory
   2.381 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   2.382  
   2.383    // save the file descriptor
   2.384    int fd = result;
   2.385  
   2.386 +  // check to see if the file is secure
   2.387 +  if (!is_file_secure(fd, filename)) {
   2.388 +    ::close(fd);
   2.389 +    return -1;
   2.390 +  }
   2.391 +
   2.392 +  // truncate the file to get rid of any existing data
   2.393 +  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
   2.394 +  if (result == OS_ERR) {
   2.395 +    if (PrintMiscellaneous && Verbose) {
   2.396 +      warning("could not truncate shared memory file: %s\n", strerror(errno));
   2.397 +    }
   2.398 +    ::close(fd);
   2.399 +    return -1;
   2.400 +  }
   2.401    // set the file size
   2.402    RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   2.403    if (result == OS_ERR) {
   2.404 @@ -683,8 +887,15 @@
   2.405        THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
   2.406      }
   2.407    }
   2.408 +  int fd = result;
   2.409  
   2.410 -  return result;
   2.411 +  // check to see if the file is secure
   2.412 +  if (!is_file_secure(fd, filename)) {
   2.413 +    ::close(fd);
   2.414 +    return -1;
   2.415 +  }
   2.416 +
   2.417 +  return fd;
   2.418  }
   2.419  
   2.420  // create a named shared memory region. returns the address of the
   2.421 @@ -715,6 +926,13 @@
   2.422  
   2.423    char* dirname = get_user_tmp_dir(user_name);
   2.424    char* filename = get_sharedmem_filename(dirname, vmid);
   2.425 +  // get the short filename
   2.426 +  char* short_filename = strrchr(filename, '/');
   2.427 +  if (short_filename == NULL) {
   2.428 +    short_filename = filename;
   2.429 +  } else {
   2.430 +    short_filename++;
   2.431 +  }
   2.432  
   2.433    // cleanup any stale shared memory files
   2.434    cleanup_sharedmem_resources(dirname);
   2.435 @@ -722,7 +940,7 @@
   2.436    assert(((size > 0) && (size % os::vm_page_size() == 0)),
   2.437           "unexpected PerfMemory region size");
   2.438  
   2.439 -  fd = create_sharedmem_resources(dirname, filename, size);
   2.440 +  fd = create_sharedmem_resources(dirname, short_filename, size);
   2.441  
   2.442    FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   2.443    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
   2.444 @@ -837,12 +1055,12 @@
   2.445    // constructs for the file and the shared memory mapping.
   2.446    if (mode == PerfMemory::PERF_MODE_RO) {
   2.447      mmap_prot = PROT_READ;
   2.448 -    file_flags = O_RDONLY;
   2.449 +    file_flags = O_RDONLY | O_NOFOLLOW;
   2.450    }
   2.451    else if (mode == PerfMemory::PERF_MODE_RW) {
   2.452  #ifdef LATER
   2.453      mmap_prot = PROT_READ | PROT_WRITE;
   2.454 -    file_flags = O_RDWR;
   2.455 +    file_flags = O_RDWR | O_NOFOLLOW;
   2.456  #else
   2.457      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
   2.458                "Unsupported access mode");
     3.1 --- a/src/os/solaris/vm/perfMemory_solaris.cpp	Fri Oct 24 17:09:30 2014 -0700
     3.2 +++ b/src/os/solaris/vm/perfMemory_solaris.cpp	Fri Oct 31 17:09:14 2014 -0700
     3.3 @@ -199,7 +199,38 @@
     3.4  }
     3.5  
     3.6  
     3.7 -// check if the given path is considered a secure directory for
     3.8 +// Check if the given statbuf is considered a secure directory for
     3.9 +// the backing store files. Returns true if the directory is considered
    3.10 +// a secure location. Returns false if the statbuf is a symbolic link or
    3.11 +// if an error occurred.
    3.12 +//
    3.13 +static bool is_statbuf_secure(struct stat *statp) {
    3.14 +  if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
    3.15 +    // The path represents a link or some non-directory file type,
    3.16 +    // which is not what we expected. Declare it insecure.
    3.17 +    //
    3.18 +    return false;
    3.19 +  }
    3.20 +  // We have an existing directory, check if the permissions are safe.
    3.21 +  //
    3.22 +  if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    3.23 +    // The directory is open for writing and could be subjected
    3.24 +    // to a symlink or a hard link attack. Declare it insecure.
    3.25 +    //
    3.26 +    return false;
    3.27 +  }
    3.28 +  // See if the uid of the directory matches the effective uid of the process.
    3.29 +  //
    3.30 +  if (statp->st_uid != geteuid()) {
    3.31 +    // The directory was not created by this user, declare it insecure.
    3.32 +    //
    3.33 +    return false;
    3.34 +  }
    3.35 +  return true;
    3.36 +}
    3.37 +
    3.38 +
    3.39 +// Check if the given path is considered a secure directory for
    3.40  // the backing store files. Returns true if the directory exists
    3.41  // and is considered a secure location. Returns false if the path
    3.42  // is a symbolic link or if an error occurred.
    3.43 @@ -213,27 +244,185 @@
    3.44      return false;
    3.45    }
    3.46  
    3.47 -  // the path exists, now check it's mode
    3.48 -  if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
    3.49 -    // the path represents a link or some non-directory file type,
    3.50 -    // which is not what we expected. declare it insecure.
    3.51 -    //
    3.52 +  // The path exists, see if it is secure.
    3.53 +  return is_statbuf_secure(&statbuf);
    3.54 +}
    3.55 +
    3.56 +
    3.57 +// Check if the given directory file descriptor is considered a secure
    3.58 +// directory for the backing store files. Returns true if the directory
    3.59 +// exists and is considered a secure location. Returns false if the path
    3.60 +// is a symbolic link or if an error occurred.
    3.61 +//
    3.62 +static bool is_dirfd_secure(int dir_fd) {
    3.63 +  struct stat statbuf;
    3.64 +  int result = 0;
    3.65 +
    3.66 +  RESTARTABLE(::fstat(dir_fd, &statbuf), result);
    3.67 +  if (result == OS_ERR) {
    3.68      return false;
    3.69    }
    3.70 -  else {
    3.71 -    // we have an existing directory, check if the permissions are safe.
    3.72 -    //
    3.73 -    if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
    3.74 -      // the directory is open for writing and could be subjected
    3.75 -      // to a symlnk attack. declare it insecure.
    3.76 -      //
    3.77 -      return false;
    3.78 +
    3.79 +  // The path exists, now check its mode.
    3.80 +  return is_statbuf_secure(&statbuf);
    3.81 +}
    3.82 +
    3.83 +
    3.84 +// Check to make sure fd1 and fd2 are referencing the same file system object.
    3.85 +//
    3.86 +static bool is_same_fsobject(int fd1, int fd2) {
    3.87 +  struct stat statbuf1;
    3.88 +  struct stat statbuf2;
    3.89 +  int result = 0;
    3.90 +
    3.91 +  RESTARTABLE(::fstat(fd1, &statbuf1), result);
    3.92 +  if (result == OS_ERR) {
    3.93 +    return false;
    3.94 +  }
    3.95 +  RESTARTABLE(::fstat(fd2, &statbuf2), result);
    3.96 +  if (result == OS_ERR) {
    3.97 +    return false;
    3.98 +  }
    3.99 +
   3.100 +  if ((statbuf1.st_ino == statbuf2.st_ino) &&
   3.101 +      (statbuf1.st_dev == statbuf2.st_dev)) {
   3.102 +    return true;
   3.103 +  } else {
   3.104 +    return false;
   3.105 +  }
   3.106 +}
   3.107 +
   3.108 +
   3.109 +// Open the directory of the given path and validate it.
   3.110 +// Return a DIR * of the open directory.
   3.111 +//
   3.112 +static DIR *open_directory_secure(const char* dirname) {
   3.113 +  // Open the directory using open() so that it can be verified
   3.114 +  // to be secure by calling is_dirfd_secure(), opendir() and then check
   3.115 +  // to see if they are the same file system object.  This method does not
   3.116 +  // introduce a window of opportunity for the directory to be attacked that
   3.117 +  // calling opendir() and is_directory_secure() does.
   3.118 +  int result;
   3.119 +  DIR *dirp = NULL;
   3.120 +  RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
   3.121 +  if (result == OS_ERR) {
   3.122 +    // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
   3.123 +    if (PrintMiscellaneous && Verbose) {
   3.124 +      if (errno == ELOOP) {
   3.125 +        warning("directory %s is a symlink and is not secure\n", dirname);
   3.126 +      } else {
   3.127 +        warning("could not open directory %s: %s\n", dirname, strerror(errno));
   3.128 +      }
   3.129      }
   3.130 +    return dirp;
   3.131 +  }
   3.132 +  int fd = result;
   3.133 +
   3.134 +  // Determine if the open directory is secure.
   3.135 +  if (!is_dirfd_secure(fd)) {
   3.136 +    // The directory is not a secure directory.
   3.137 +    os::close(fd);
   3.138 +    return dirp;
   3.139 +  }
   3.140 +
   3.141 +  // Open the directory.
   3.142 +  dirp = ::opendir(dirname);
   3.143 +  if (dirp == NULL) {
   3.144 +    // The directory doesn't exist, close fd and return.
   3.145 +    os::close(fd);
   3.146 +    return dirp;
   3.147 +  }
   3.148 +
   3.149 +  // Check to make sure fd and dirp are referencing the same file system object.
   3.150 +  if (!is_same_fsobject(fd, dirp->dd_fd)) {
   3.151 +    // The directory is not secure.
   3.152 +    os::close(fd);
   3.153 +    os::closedir(dirp);
   3.154 +    dirp = NULL;
   3.155 +    return dirp;
   3.156 +  }
   3.157 +
   3.158 +  // Close initial open now that we know directory is secure
   3.159 +  os::close(fd);
   3.160 +
   3.161 +  return dirp;
   3.162 +}
   3.163 +
   3.164 +// NOTE: The code below uses fchdir(), open() and unlink() because
   3.165 +// fdopendir(), openat() and unlinkat() are not supported on all
   3.166 +// versions.  Once the support for fdopendir(), openat() and unlinkat()
   3.167 +// is available on all supported versions the code can be changed
   3.168 +// to use these functions.
   3.169 +
   3.170 +// Open the directory of the given path, validate it and set the
   3.171 +// current working directory to it.
   3.172 +// Return a DIR * of the open directory and the saved cwd fd.
   3.173 +//
   3.174 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
   3.175 +
   3.176 +  // Open the directory.
   3.177 +  DIR* dirp = open_directory_secure(dirname);
   3.178 +  if (dirp == NULL) {
   3.179 +    // Directory doesn't exist or is insecure, so there is nothing to cleanup.
   3.180 +    return dirp;
   3.181 +  }
   3.182 +  int fd = dirp->dd_fd;
   3.183 +
   3.184 +  // Open a fd to the cwd and save it off.
   3.185 +  int result;
   3.186 +  RESTARTABLE(::open(".", O_RDONLY), result);
   3.187 +  if (result == OS_ERR) {
   3.188 +    *saved_cwd_fd = -1;
   3.189 +  } else {
   3.190 +    *saved_cwd_fd = result;
   3.191 +  }
   3.192 +
   3.193 +  // Set the current directory to dirname by using the fd of the directory.
   3.194 +  result = fchdir(fd);
   3.195 +
   3.196 +  return dirp;
   3.197 +}
   3.198 +
   3.199 +// Close the directory and restore the current working directory.
   3.200 +//
   3.201 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
   3.202 +
   3.203 +  int result;
   3.204 +  // If we have a saved cwd change back to it and close the fd.
   3.205 +  if (saved_cwd_fd != -1) {
   3.206 +    result = fchdir(saved_cwd_fd);
   3.207 +    ::close(saved_cwd_fd);
   3.208 +  }
   3.209 +
   3.210 +  // Close the directory.
   3.211 +  os::closedir(dirp);
   3.212 +}
   3.213 +
   3.214 +// Check if the given file descriptor is considered a secure.
   3.215 +//
   3.216 +static bool is_file_secure(int fd, const char *filename) {
   3.217 +
   3.218 +  int result;
   3.219 +  struct stat statbuf;
   3.220 +
   3.221 +  // Determine if the file is secure.
   3.222 +  RESTARTABLE(::fstat(fd, &statbuf), result);
   3.223 +  if (result == OS_ERR) {
   3.224 +    if (PrintMiscellaneous && Verbose) {
   3.225 +      warning("fstat failed on %s: %s\n", filename, strerror(errno));
   3.226 +    }
   3.227 +    return false;
   3.228 +  }
   3.229 +  if (statbuf.st_nlink > 1) {
   3.230 +    // A file with multiple links is not expected.
   3.231 +    if (PrintMiscellaneous && Verbose) {
   3.232 +      warning("file %s has multiple links\n", filename);
   3.233 +    }
   3.234 +    return false;
   3.235    }
   3.236    return true;
   3.237  }
   3.238  
   3.239 -
   3.240  // return the user name for the given user id
   3.241  //
   3.242  // the caller is expected to free the allocated memory.
   3.243 @@ -308,9 +497,10 @@
   3.244  
   3.245    const char* tmpdirname = os::get_temp_directory();
   3.246  
   3.247 -  DIR* tmpdirp = os::opendir(tmpdirname);
   3.248 -
   3.249 +  // open the temp directory
   3.250 +  DIR* tmpdirp = open_directory_secure(tmpdirname);
   3.251    if (tmpdirp == NULL) {
   3.252 +    // Cannot open the directory to get the user name, return.
   3.253      return NULL;
   3.254    }
   3.255  
   3.256 @@ -335,7 +525,8 @@
   3.257      strcat(usrdir_name, "/");
   3.258      strcat(usrdir_name, dentry->d_name);
   3.259  
   3.260 -    DIR* subdirp = os::opendir(usrdir_name);
   3.261 +    // open the user directory
   3.262 +    DIR* subdirp = open_directory_secure(usrdir_name);
   3.263  
   3.264      if (subdirp == NULL) {
   3.265        FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
   3.266 @@ -504,26 +695,6 @@
   3.267  }
   3.268  
   3.269  
   3.270 -// remove file
   3.271 -//
   3.272 -// this method removes the file with the given file name in the
   3.273 -// named directory.
   3.274 -//
   3.275 -static void remove_file(const char* dirname, const char* filename) {
   3.276 -
   3.277 -  size_t nbytes = strlen(dirname) + strlen(filename) + 2;
   3.278 -  char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
   3.279 -
   3.280 -  strcpy(path, dirname);
   3.281 -  strcat(path, "/");
   3.282 -  strcat(path, filename);
   3.283 -
   3.284 -  remove_file(path);
   3.285 -
   3.286 -  FREE_C_HEAP_ARRAY(char, path, mtInternal);
   3.287 -}
   3.288 -
   3.289 -
   3.290  // cleanup stale shared memory resources
   3.291  //
   3.292  // This method attempts to remove all stale shared memory files in
   3.293 @@ -535,16 +706,11 @@
   3.294  //
   3.295  static void cleanup_sharedmem_resources(const char* dirname) {
   3.296  
   3.297 -  // open the user temp directory
   3.298 -  DIR* dirp = os::opendir(dirname);
   3.299 -
   3.300 +  int saved_cwd_fd;
   3.301 +  // open the directory
   3.302 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   3.303    if (dirp == NULL) {
   3.304 -    // directory doesn't exist, so there is nothing to cleanup
   3.305 -    return;
   3.306 -  }
   3.307 -
   3.308 -  if (!is_directory_secure(dirname)) {
   3.309 -    // the directory is not a secure directory
   3.310 +     // directory doesn't exist or is insecure, so there is nothing to cleanup
   3.311      return;
   3.312    }
   3.313  
   3.314 @@ -558,6 +724,7 @@
   3.315    //
   3.316    struct dirent* entry;
   3.317    char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
   3.318 +
   3.319    errno = 0;
   3.320    while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
   3.321  
   3.322 @@ -568,7 +735,7 @@
   3.323        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
   3.324  
   3.325          // attempt to remove all unexpected files, except "." and ".."
   3.326 -        remove_file(dirname, entry->d_name);
   3.327 +        unlink(entry->d_name);
   3.328        }
   3.329  
   3.330        errno = 0;
   3.331 @@ -591,11 +758,14 @@
   3.332      if ((pid == os::current_process_id()) ||
   3.333          (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
   3.334  
   3.335 -        remove_file(dirname, entry->d_name);
   3.336 +        unlink(entry->d_name);
   3.337      }
   3.338      errno = 0;
   3.339    }
   3.340 -  os::closedir(dirp);
   3.341 +
   3.342 +  // close the directory and reset the current working directory
   3.343 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   3.344 +
   3.345    FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
   3.346  }
   3.347  
   3.348 @@ -652,19 +822,54 @@
   3.349      return -1;
   3.350    }
   3.351  
   3.352 +  int saved_cwd_fd;
   3.353 +  // open the directory and set the current working directory to it
   3.354 +  DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
   3.355 +  if (dirp == NULL) {
   3.356 +    // Directory doesn't exist or is insecure, so cannot create shared
   3.357 +    // memory file.
   3.358 +    return -1;
   3.359 +  }
   3.360 +
   3.361 +  // Open the filename in the current directory.
   3.362 +  // Cannot use O_TRUNC here; truncation of an existing file has to happen
   3.363 +  // after the is_file_secure() check below.
   3.364    int result;
   3.365 -
   3.366 -  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
   3.367 +  RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
   3.368    if (result == OS_ERR) {
   3.369      if (PrintMiscellaneous && Verbose) {
   3.370 -      warning("could not create file %s: %s\n", filename, strerror(errno));
   3.371 +      if (errno == ELOOP) {
   3.372 +        warning("file %s is a symlink and is not secure\n", filename);
   3.373 +      } else {
   3.374 +        warning("could not create file %s: %s\n", filename, strerror(errno));
   3.375 +      }
   3.376      }
   3.377 +    // close the directory and reset the current working directory
   3.378 +    close_directory_secure_cwd(dirp, saved_cwd_fd);
   3.379 +
   3.380      return -1;
   3.381    }
   3.382 +  // close the directory and reset the current working directory
   3.383 +  close_directory_secure_cwd(dirp, saved_cwd_fd);
   3.384  
   3.385    // save the file descriptor
   3.386    int fd = result;
   3.387  
   3.388 +  // check to see if the file is secure
   3.389 +  if (!is_file_secure(fd, filename)) {
   3.390 +    ::close(fd);
   3.391 +    return -1;
   3.392 +  }
   3.393 +
   3.394 +  // truncate the file to get rid of any existing data
   3.395 +  RESTARTABLE(::ftruncate(fd, (off_t)0), result);
   3.396 +  if (result == OS_ERR) {
   3.397 +    if (PrintMiscellaneous && Verbose) {
   3.398 +      warning("could not truncate shared memory file: %s\n", strerror(errno));
   3.399 +    }
   3.400 +    ::close(fd);
   3.401 +    return -1;
   3.402 +  }
   3.403    // set the file size
   3.404    RESTARTABLE(::ftruncate(fd, (off_t)size), result);
   3.405    if (result == OS_ERR) {
   3.406 @@ -700,8 +905,15 @@
   3.407        THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
   3.408      }
   3.409    }
   3.410 +  int fd = result;
   3.411  
   3.412 -  return result;
   3.413 +  // check to see if the file is secure
   3.414 +  if (!is_file_secure(fd, filename)) {
   3.415 +    ::close(fd);
   3.416 +    return -1;
   3.417 +  }
   3.418 +
   3.419 +  return fd;
   3.420  }
   3.421  
   3.422  // create a named shared memory region. returns the address of the
   3.423 @@ -733,13 +945,21 @@
   3.424    char* dirname = get_user_tmp_dir(user_name);
   3.425    char* filename = get_sharedmem_filename(dirname, vmid);
   3.426  
   3.427 +  // get the short filename
   3.428 +  char* short_filename = strrchr(filename, '/');
   3.429 +  if (short_filename == NULL) {
   3.430 +    short_filename = filename;
   3.431 +  } else {
   3.432 +    short_filename++;
   3.433 +  }
   3.434 +
   3.435    // cleanup any stale shared memory files
   3.436    cleanup_sharedmem_resources(dirname);
   3.437  
   3.438    assert(((size > 0) && (size % os::vm_page_size() == 0)),
   3.439           "unexpected PerfMemory region size");
   3.440  
   3.441 -  fd = create_sharedmem_resources(dirname, filename, size);
   3.442 +  fd = create_sharedmem_resources(dirname, short_filename, size);
   3.443  
   3.444    FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
   3.445    FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
   3.446 @@ -855,12 +1075,12 @@
   3.447    // constructs for the file and the shared memory mapping.
   3.448    if (mode == PerfMemory::PERF_MODE_RO) {
   3.449      mmap_prot = PROT_READ;
   3.450 -    file_flags = O_RDONLY;
   3.451 +    file_flags = O_RDONLY | O_NOFOLLOW;
   3.452    }
   3.453    else if (mode == PerfMemory::PERF_MODE_RW) {
   3.454  #ifdef LATER
   3.455      mmap_prot = PROT_READ | PROT_WRITE;
   3.456 -    file_flags = O_RDWR;
   3.457 +    file_flags = O_RDWR | O_NOFOLLOW;
   3.458  #else
   3.459      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
   3.460                "Unsupported access mode");
     4.1 --- a/src/share/vm/utilities/vmError.cpp	Fri Oct 24 17:09:30 2014 -0700
     4.2 +++ b/src/share/vm/utilities/vmError.cpp	Fri Oct 31 17:09:14 2014 -0700
     4.3 @@ -22,6 +22,7 @@
     4.4   *
     4.5   */
     4.6  
     4.7 +#include <fcntl.h>
     4.8  #include "precompiled.hpp"
     4.9  #include "compiler/compileBroker.hpp"
    4.10  #include "gc_interface/collectedHeap.hpp"
    4.11 @@ -841,7 +842,8 @@
    4.12  static int expand_and_open(const char* pattern, char* buf, size_t buflen, size_t pos) {
    4.13    int fd = -1;
    4.14    if (Arguments::copy_expand_pid(pattern, strlen(pattern), &buf[pos], buflen - pos)) {
    4.15 -    fd = open(buf, O_RDWR | O_CREAT | O_TRUNC, 0666);
    4.16 +    // the O_EXCL flag will cause the open to fail if the file exists
    4.17 +    fd = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
    4.18    }
    4.19    return fd;
    4.20  }

mercurial