Mon, 17 Nov 2014 15:51:46 -0500
8050807: Better performing performance data handling
Reviewed-by: dcubed, pnauman, ctornqvi, dholmes, mschoene
Contributed-by: gerald.thornbrugh@oracle.com
1.1 --- a/src/os/bsd/vm/perfMemory_bsd.cpp Mon Nov 10 09:47:41 2014 -0800 1.2 +++ b/src/os/bsd/vm/perfMemory_bsd.cpp Mon Nov 17 15:51:46 2014 -0500 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,11 @@ 1.244 1.245 const char* tmpdirname = os::get_temp_directory(); 1.246 1.247 + // open the temp directory 1.248 DIR* tmpdirp = os::opendir(tmpdirname); 1.249 1.250 if (tmpdirp == NULL) { 1.251 + // Cannot open the directory to get the user name, return. 1.252 return NULL; 1.253 } 1.254 1.255 @@ -344,25 +535,14 @@ 1.256 strcat(usrdir_name, "/"); 1.257 strcat(usrdir_name, dentry->d_name); 1.258 1.259 - DIR* subdirp = os::opendir(usrdir_name); 1.260 + // open the user directory 1.261 + DIR* subdirp = open_directory_secure(usrdir_name); 1.262 1.263 if (subdirp == NULL) { 1.264 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); 1.265 continue; 1.266 } 1.267 1.268 - // Since we don't create the backing store files in directories 1.269 - // pointed to by symbolic links, we also don't follow them when 1.270 - // looking for the files. We check for a symbolic link after the 1.271 - // call to opendir in order to eliminate a small window where the 1.272 - // symlink can be exploited. 1.273 - // 1.274 - if (!is_directory_secure(usrdir_name)) { 1.275 - FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); 1.276 - os::closedir(subdirp); 1.277 - continue; 1.278 - } 1.279 - 1.280 struct dirent* udentry; 1.281 char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); 1.282 errno = 0; 1.283 @@ -465,26 +645,6 @@ 1.284 } 1.285 1.286 1.287 -// remove file 1.288 -// 1.289 -// this method removes the file with the given file name in the 1.290 -// named directory. 1.291 -// 1.292 -static void remove_file(const char* dirname, const char* filename) { 1.293 - 1.294 - size_t nbytes = strlen(dirname) + strlen(filename) + 2; 1.295 - char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); 1.296 - 1.297 - strcpy(path, dirname); 1.298 - strcat(path, "/"); 1.299 - strcat(path, filename); 1.300 - 1.301 - remove_file(path); 1.302 - 1.303 - FREE_C_HEAP_ARRAY(char, path, mtInternal); 1.304 -} 1.305 - 1.306 - 1.307 // cleanup stale shared memory resources 1.308 // 1.309 // This method attempts to remove all stale shared memory files in 1.310 @@ -496,16 +656,11 @@ 1.311 // 1.312 static void cleanup_sharedmem_resources(const char* dirname) { 1.313 1.314 - // open the user temp directory 1.315 - DIR* dirp = os::opendir(dirname); 1.316 - 1.317 + int saved_cwd_fd; 1.318 + // open the directory and set the current working directory to it 1.319 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 1.320 if (dirp == NULL) { 1.321 - // directory doesn't exist, so there is nothing to cleanup 1.322 - return; 1.323 - } 1.324 - 1.325 - if (!is_directory_secure(dirname)) { 1.326 - // the directory is not a secure directory 1.327 + // directory doesn't exist or is insecure, so there is nothing to cleanup 1.328 return; 1.329 } 1.330 1.331 @@ -519,6 +674,7 @@ 1.332 // 1.333 struct dirent* entry; 1.334 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); 1.335 + 1.336 errno = 0; 1.337 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { 1.338 1.339 @@ -529,7 +685,7 @@ 1.340 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { 1.341 1.342 // attempt to remove all unexpected files, except "." and ".." 1.343 - remove_file(dirname, entry->d_name); 1.344 + unlink(entry->d_name); 1.345 } 1.346 1.347 errno = 0; 1.348 @@ -552,11 +708,14 @@ 1.349 if ((pid == os::current_process_id()) || 1.350 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { 1.351 1.352 - remove_file(dirname, entry->d_name); 1.353 + unlink(entry->d_name); 1.354 } 1.355 errno = 0; 1.356 } 1.357 - os::closedir(dirp); 1.358 + 1.359 + // close the directory and reset the current working directory 1.360 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.361 + 1.362 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 1.363 } 1.364 1.365 @@ -613,19 +772,54 @@ 1.366 return -1; 1.367 } 1.368 1.369 + int saved_cwd_fd; 1.370 + // open the directory and set the current working directory to it 1.371 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 1.372 + if (dirp == NULL) { 1.373 + // Directory doesn't exist or is insecure, so cannot create shared 1.374 + // memory file. 1.375 + return -1; 1.376 + } 1.377 + 1.378 + // Open the filename in the current directory. 1.379 + // Cannot use O_TRUNC here; truncation of an existing file has to happen 1.380 + // after the is_file_secure() check below. 1.381 int result; 1.382 - 1.383 - RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); 1.384 + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); 1.385 if (result == OS_ERR) { 1.386 if (PrintMiscellaneous && Verbose) { 1.387 - warning("could not create file %s: %s\n", filename, strerror(errno)); 1.388 + if (errno == ELOOP) { 1.389 + warning("file %s is a symlink and is not secure\n", filename); 1.390 + } else { 1.391 + warning("could not create file %s: %s\n", filename, strerror(errno)); 1.392 + } 1.393 } 1.394 + // close the directory and reset the current working directory 1.395 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.396 + 1.397 return -1; 1.398 } 1.399 + // close the directory and reset the current working directory 1.400 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.401 1.402 // save the file descriptor 1.403 int fd = result; 1.404 1.405 + // check to see if the file is secure 1.406 + if (!is_file_secure(fd, filename)) { 1.407 + ::close(fd); 1.408 + return -1; 1.409 + } 1.410 + 1.411 + // truncate the file to get rid of any existing data 1.412 + RESTARTABLE(::ftruncate(fd, (off_t)0), result); 1.413 + if (result == OS_ERR) { 1.414 + if (PrintMiscellaneous && Verbose) { 1.415 + warning("could not truncate shared memory file: %s\n", strerror(errno)); 1.416 + } 1.417 + ::close(fd); 1.418 + return -1; 1.419 + } 1.420 // set the file size 1.421 RESTARTABLE(::ftruncate(fd, (off_t)size), result); 1.422 if (result == OS_ERR) { 1.423 @@ -683,8 +877,15 @@ 1.424 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); 1.425 } 1.426 } 1.427 + int fd = result; 1.428 1.429 - return result; 1.430 + // check to see if the file is secure 1.431 + if (!is_file_secure(fd, filename)) { 1.432 + ::close(fd); 1.433 + return -1; 1.434 + } 1.435 + 1.436 + return fd; 1.437 } 1.438 1.439 // create a named shared memory region. returns the address of the 1.440 @@ -716,13 +917,21 @@ 1.441 char* dirname = get_user_tmp_dir(user_name); 1.442 char* filename = get_sharedmem_filename(dirname, vmid); 1.443 1.444 + // get the short filename 1.445 + char* short_filename = strrchr(filename, '/'); 1.446 + if (short_filename == NULL) { 1.447 + short_filename = filename; 1.448 + } else { 1.449 + short_filename++; 1.450 + } 1.451 + 1.452 // cleanup any stale shared memory files 1.453 cleanup_sharedmem_resources(dirname); 1.454 1.455 assert(((size > 0) && (size % os::vm_page_size() == 0)), 1.456 "unexpected PerfMemory region size"); 1.457 1.458 - fd = create_sharedmem_resources(dirname, filename, size); 1.459 + fd = create_sharedmem_resources(dirname, short_filename, size); 1.460 1.461 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); 1.462 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); 1.463 @@ -837,12 +1046,12 @@ 1.464 // constructs for the file and the shared memory mapping. 1.465 if (mode == PerfMemory::PERF_MODE_RO) { 1.466 mmap_prot = PROT_READ; 1.467 - file_flags = O_RDONLY; 1.468 + file_flags = O_RDONLY | O_NOFOLLOW; 1.469 } 1.470 else if (mode == PerfMemory::PERF_MODE_RW) { 1.471 #ifdef LATER 1.472 mmap_prot = PROT_READ | PROT_WRITE; 1.473 - file_flags = O_RDWR; 1.474 + file_flags = O_RDWR | O_NOFOLLOW; 1.475 #else 1.476 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 1.477 "Unsupported access mode");
2.1 --- a/src/os/linux/vm/perfMemory_linux.cpp Mon Nov 10 09:47:41 2014 -0800 2.2 +++ b/src/os/linux/vm/perfMemory_linux.cpp Mon Nov 17 15:51:46 2014 -0500 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,180 @@ 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 + if (PrintMiscellaneous && Verbose) { 2.123 + if (errno == ELOOP) { 2.124 + warning("directory %s is a symlink and is not secure\n", dirname); 2.125 + } else { 2.126 + warning("could not open directory %s: %s\n", dirname, strerror(errno)); 2.127 + } 2.128 } 2.129 + return dirp; 2.130 + } 2.131 + int fd = result; 2.132 + 2.133 + // Determine if the open directory is secure. 2.134 + if (!is_dirfd_secure(fd)) { 2.135 + // The directory is not a secure directory. 2.136 + os::close(fd); 2.137 + return dirp; 2.138 + } 2.139 + 2.140 + // Open the directory. 2.141 + dirp = ::opendir(dirname); 2.142 + if (dirp == NULL) { 2.143 + // The directory doesn't exist, close fd and return. 2.144 + os::close(fd); 2.145 + return dirp; 2.146 + } 2.147 + 2.148 + // Check to make sure fd and dirp are referencing the same file system object. 2.149 + if (!is_same_fsobject(fd, dirfd(dirp))) { 2.150 + // The directory is not secure. 2.151 + os::close(fd); 2.152 + os::closedir(dirp); 2.153 + dirp = NULL; 2.154 + return dirp; 2.155 + } 2.156 + 2.157 + // Close initial open now that we know directory is secure 2.158 + os::close(fd); 2.159 + 2.160 + return dirp; 2.161 +} 2.162 + 2.163 +// NOTE: The code below uses fchdir(), open() and unlink() because 2.164 +// fdopendir(), openat() and unlinkat() are not supported on all 2.165 +// versions. Once the support for fdopendir(), openat() and unlinkat() 2.166 +// is available on all supported versions the code can be changed 2.167 +// to use these functions. 2.168 + 2.169 +// Open the directory of the given path, validate it and set the 2.170 +// current working directory to it. 2.171 +// Return a DIR * of the open directory and the saved cwd fd. 2.172 +// 2.173 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { 2.174 + 2.175 + // Open the directory. 2.176 + DIR* dirp = open_directory_secure(dirname); 2.177 + if (dirp == NULL) { 2.178 + // Directory doesn't exist or is insecure, so there is nothing to cleanup. 2.179 + return dirp; 2.180 + } 2.181 + int fd = dirfd(dirp); 2.182 + 2.183 + // Open a fd to the cwd and save it off. 2.184 + int result; 2.185 + RESTARTABLE(::open(".", O_RDONLY), result); 2.186 + if (result == OS_ERR) { 2.187 + *saved_cwd_fd = -1; 2.188 + } else { 2.189 + *saved_cwd_fd = result; 2.190 + } 2.191 + 2.192 + // Set the current directory to dirname by using the fd of the directory. 2.193 + result = fchdir(fd); 2.194 + 2.195 + return dirp; 2.196 +} 2.197 + 2.198 +// Close the directory and restore the current working directory. 2.199 +// 2.200 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { 2.201 + 2.202 + int result; 2.203 + // If we have a saved cwd change back to it and close the fd. 2.204 + if (saved_cwd_fd != -1) { 2.205 + result = fchdir(saved_cwd_fd); 2.206 + ::close(saved_cwd_fd); 2.207 + } 2.208 + 2.209 + // Close the directory. 2.210 + os::closedir(dirp); 2.211 +} 2.212 + 2.213 +// Check if the given file descriptor is considered a secure. 2.214 +// 2.215 +static bool is_file_secure(int fd, const char *filename) { 2.216 + 2.217 + int result; 2.218 + struct stat statbuf; 2.219 + 2.220 + // Determine if the file is secure. 2.221 + RESTARTABLE(::fstat(fd, &statbuf), result); 2.222 + if (result == OS_ERR) { 2.223 + if (PrintMiscellaneous && Verbose) { 2.224 + warning("fstat failed on %s: %s\n", filename, strerror(errno)); 2.225 + } 2.226 + return false; 2.227 + } 2.228 + if (statbuf.st_nlink > 1) { 2.229 + // A file with multiple links is not expected. 2.230 + if (PrintMiscellaneous && Verbose) { 2.231 + warning("file %s has multiple links\n", filename); 2.232 + } 2.233 + return false; 2.234 } 2.235 return true; 2.236 } 2.237 @@ -317,9 +506,11 @@ 2.238 2.239 const char* tmpdirname = os::get_temp_directory(); 2.240 2.241 + // open the temp directory 2.242 DIR* tmpdirp = os::opendir(tmpdirname); 2.243 2.244 if (tmpdirp == NULL) { 2.245 + // Cannot open the directory to get the user name, return. 2.246 return NULL; 2.247 } 2.248 2.249 @@ -344,7 +535,8 @@ 2.250 strcat(usrdir_name, "/"); 2.251 strcat(usrdir_name, dentry->d_name); 2.252 2.253 - DIR* subdirp = os::opendir(usrdir_name); 2.254 + // open the user directory 2.255 + DIR* subdirp = open_directory_secure(usrdir_name); 2.256 2.257 if (subdirp == NULL) { 2.258 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); 2.259 @@ -465,26 +657,6 @@ 2.260 } 2.261 2.262 2.263 -// remove file 2.264 -// 2.265 -// this method removes the file with the given file name in the 2.266 -// named directory. 2.267 -// 2.268 -static void remove_file(const char* dirname, const char* filename) { 2.269 - 2.270 - size_t nbytes = strlen(dirname) + strlen(filename) + 2; 2.271 - char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); 2.272 - 2.273 - strcpy(path, dirname); 2.274 - strcat(path, "/"); 2.275 - strcat(path, filename); 2.276 - 2.277 - remove_file(path); 2.278 - 2.279 - FREE_C_HEAP_ARRAY(char, path, mtInternal); 2.280 -} 2.281 - 2.282 - 2.283 // cleanup stale shared memory resources 2.284 // 2.285 // This method attempts to remove all stale shared memory files in 2.286 @@ -496,16 +668,11 @@ 2.287 // 2.288 static void cleanup_sharedmem_resources(const char* dirname) { 2.289 2.290 - // open the user temp directory 2.291 - DIR* dirp = os::opendir(dirname); 2.292 - 2.293 + int saved_cwd_fd; 2.294 + // open the directory 2.295 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 2.296 if (dirp == NULL) { 2.297 - // directory doesn't exist, so there is nothing to cleanup 2.298 - return; 2.299 - } 2.300 - 2.301 - if (!is_directory_secure(dirname)) { 2.302 - // the directory is not a secure directory 2.303 + // directory doesn't exist or is insecure, so there is nothing to cleanup 2.304 return; 2.305 } 2.306 2.307 @@ -519,6 +686,7 @@ 2.308 // 2.309 struct dirent* entry; 2.310 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); 2.311 + 2.312 errno = 0; 2.313 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { 2.314 2.315 @@ -527,9 +695,8 @@ 2.316 if (pid == 0) { 2.317 2.318 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { 2.319 - 2.320 // attempt to remove all unexpected files, except "." and ".." 2.321 - remove_file(dirname, entry->d_name); 2.322 + unlink(entry->d_name); 2.323 } 2.324 2.325 errno = 0; 2.326 @@ -551,12 +718,14 @@ 2.327 // 2.328 if ((pid == os::current_process_id()) || 2.329 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { 2.330 - 2.331 - remove_file(dirname, entry->d_name); 2.332 + unlink(entry->d_name); 2.333 } 2.334 errno = 0; 2.335 } 2.336 - os::closedir(dirp); 2.337 + 2.338 + // close the directory and reset the current working directory 2.339 + close_directory_secure_cwd(dirp, saved_cwd_fd); 2.340 + 2.341 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 2.342 } 2.343 2.344 @@ -613,19 +782,54 @@ 2.345 return -1; 2.346 } 2.347 2.348 + int saved_cwd_fd; 2.349 + // open the directory and set the current working directory to it 2.350 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 2.351 + if (dirp == NULL) { 2.352 + // Directory doesn't exist or is insecure, so cannot create shared 2.353 + // memory file. 2.354 + return -1; 2.355 + } 2.356 + 2.357 + // Open the filename in the current directory. 2.358 + // Cannot use O_TRUNC here; truncation of an existing file has to happen 2.359 + // after the is_file_secure() check below. 2.360 int result; 2.361 - 2.362 - RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); 2.363 + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); 2.364 if (result == OS_ERR) { 2.365 if (PrintMiscellaneous && Verbose) { 2.366 - warning("could not create file %s: %s\n", filename, strerror(errno)); 2.367 + if (errno == ELOOP) { 2.368 + warning("file %s is a symlink and is not secure\n", filename); 2.369 + } else { 2.370 + warning("could not create file %s: %s\n", filename, strerror(errno)); 2.371 + } 2.372 } 2.373 + // close the directory and reset the current working directory 2.374 + close_directory_secure_cwd(dirp, saved_cwd_fd); 2.375 + 2.376 return -1; 2.377 } 2.378 + // close the directory and reset the current working directory 2.379 + close_directory_secure_cwd(dirp, saved_cwd_fd); 2.380 2.381 // save the file descriptor 2.382 int fd = result; 2.383 2.384 + // check to see if the file is secure 2.385 + if (!is_file_secure(fd, filename)) { 2.386 + ::close(fd); 2.387 + return -1; 2.388 + } 2.389 + 2.390 + // truncate the file to get rid of any existing data 2.391 + RESTARTABLE(::ftruncate(fd, (off_t)0), result); 2.392 + if (result == OS_ERR) { 2.393 + if (PrintMiscellaneous && Verbose) { 2.394 + warning("could not truncate shared memory file: %s\n", strerror(errno)); 2.395 + } 2.396 + ::close(fd); 2.397 + return -1; 2.398 + } 2.399 // set the file size 2.400 RESTARTABLE(::ftruncate(fd, (off_t)size), result); 2.401 if (result == OS_ERR) { 2.402 @@ -683,8 +887,15 @@ 2.403 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); 2.404 } 2.405 } 2.406 + int fd = result; 2.407 2.408 - return result; 2.409 + // check to see if the file is secure 2.410 + if (!is_file_secure(fd, filename)) { 2.411 + ::close(fd); 2.412 + return -1; 2.413 + } 2.414 + 2.415 + return fd; 2.416 } 2.417 2.418 // create a named shared memory region. returns the address of the 2.419 @@ -715,6 +926,13 @@ 2.420 2.421 char* dirname = get_user_tmp_dir(user_name); 2.422 char* filename = get_sharedmem_filename(dirname, vmid); 2.423 + // get the short filename 2.424 + char* short_filename = strrchr(filename, '/'); 2.425 + if (short_filename == NULL) { 2.426 + short_filename = filename; 2.427 + } else { 2.428 + short_filename++; 2.429 + } 2.430 2.431 // cleanup any stale shared memory files 2.432 cleanup_sharedmem_resources(dirname); 2.433 @@ -722,7 +940,7 @@ 2.434 assert(((size > 0) && (size % os::vm_page_size() == 0)), 2.435 "unexpected PerfMemory region size"); 2.436 2.437 - fd = create_sharedmem_resources(dirname, filename, size); 2.438 + fd = create_sharedmem_resources(dirname, short_filename, size); 2.439 2.440 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); 2.441 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); 2.442 @@ -837,12 +1055,12 @@ 2.443 // constructs for the file and the shared memory mapping. 2.444 if (mode == PerfMemory::PERF_MODE_RO) { 2.445 mmap_prot = PROT_READ; 2.446 - file_flags = O_RDONLY; 2.447 + file_flags = O_RDONLY | O_NOFOLLOW; 2.448 } 2.449 else if (mode == PerfMemory::PERF_MODE_RW) { 2.450 #ifdef LATER 2.451 mmap_prot = PROT_READ | PROT_WRITE; 2.452 - file_flags = O_RDWR; 2.453 + file_flags = O_RDWR | O_NOFOLLOW; 2.454 #else 2.455 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 2.456 "Unsupported access mode");
3.1 --- a/src/os/solaris/vm/perfMemory_solaris.cpp Mon Nov 10 09:47:41 2014 -0800 3.2 +++ b/src/os/solaris/vm/perfMemory_solaris.cpp Mon Nov 17 15:51:46 2014 -0500 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,11 @@ 3.244 3.245 const char* tmpdirname = os::get_temp_directory(); 3.246 3.247 + // open the temp directory 3.248 DIR* tmpdirp = os::opendir(tmpdirname); 3.249 3.250 if (tmpdirp == NULL) { 3.251 + // Cannot open the directory to get the user name, return. 3.252 return NULL; 3.253 } 3.254 3.255 @@ -335,7 +526,8 @@ 3.256 strcat(usrdir_name, "/"); 3.257 strcat(usrdir_name, dentry->d_name); 3.258 3.259 - DIR* subdirp = os::opendir(usrdir_name); 3.260 + // open the user directory 3.261 + DIR* subdirp = open_directory_secure(usrdir_name); 3.262 3.263 if (subdirp == NULL) { 3.264 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); 3.265 @@ -504,26 +696,6 @@ 3.266 } 3.267 3.268 3.269 -// remove file 3.270 -// 3.271 -// this method removes the file with the given file name in the 3.272 -// named directory. 3.273 -// 3.274 -static void remove_file(const char* dirname, const char* filename) { 3.275 - 3.276 - size_t nbytes = strlen(dirname) + strlen(filename) + 2; 3.277 - char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); 3.278 - 3.279 - strcpy(path, dirname); 3.280 - strcat(path, "/"); 3.281 - strcat(path, filename); 3.282 - 3.283 - remove_file(path); 3.284 - 3.285 - FREE_C_HEAP_ARRAY(char, path, mtInternal); 3.286 -} 3.287 - 3.288 - 3.289 // cleanup stale shared memory resources 3.290 // 3.291 // This method attempts to remove all stale shared memory files in 3.292 @@ -535,16 +707,11 @@ 3.293 // 3.294 static void cleanup_sharedmem_resources(const char* dirname) { 3.295 3.296 - // open the user temp directory 3.297 - DIR* dirp = os::opendir(dirname); 3.298 - 3.299 + int saved_cwd_fd; 3.300 + // open the directory 3.301 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 3.302 if (dirp == NULL) { 3.303 - // directory doesn't exist, so there is nothing to cleanup 3.304 - return; 3.305 - } 3.306 - 3.307 - if (!is_directory_secure(dirname)) { 3.308 - // the directory is not a secure directory 3.309 + // directory doesn't exist or is insecure, so there is nothing to cleanup 3.310 return; 3.311 } 3.312 3.313 @@ -558,6 +725,7 @@ 3.314 // 3.315 struct dirent* entry; 3.316 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); 3.317 + 3.318 errno = 0; 3.319 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { 3.320 3.321 @@ -568,7 +736,7 @@ 3.322 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { 3.323 3.324 // attempt to remove all unexpected files, except "." and ".." 3.325 - remove_file(dirname, entry->d_name); 3.326 + unlink(entry->d_name); 3.327 } 3.328 3.329 errno = 0; 3.330 @@ -591,11 +759,14 @@ 3.331 if ((pid == os::current_process_id()) || 3.332 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { 3.333 3.334 - remove_file(dirname, entry->d_name); 3.335 + unlink(entry->d_name); 3.336 } 3.337 errno = 0; 3.338 } 3.339 - os::closedir(dirp); 3.340 + 3.341 + // close the directory and reset the current working directory 3.342 + close_directory_secure_cwd(dirp, saved_cwd_fd); 3.343 + 3.344 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 3.345 } 3.346 3.347 @@ -652,19 +823,54 @@ 3.348 return -1; 3.349 } 3.350 3.351 + int saved_cwd_fd; 3.352 + // open the directory and set the current working directory to it 3.353 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 3.354 + if (dirp == NULL) { 3.355 + // Directory doesn't exist or is insecure, so cannot create shared 3.356 + // memory file. 3.357 + return -1; 3.358 + } 3.359 + 3.360 + // Open the filename in the current directory. 3.361 + // Cannot use O_TRUNC here; truncation of an existing file has to happen 3.362 + // after the is_file_secure() check below. 3.363 int result; 3.364 - 3.365 - RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); 3.366 + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); 3.367 if (result == OS_ERR) { 3.368 if (PrintMiscellaneous && Verbose) { 3.369 - warning("could not create file %s: %s\n", filename, strerror(errno)); 3.370 + if (errno == ELOOP) { 3.371 + warning("file %s is a symlink and is not secure\n", filename); 3.372 + } else { 3.373 + warning("could not create file %s: %s\n", filename, strerror(errno)); 3.374 + } 3.375 } 3.376 + // close the directory and reset the current working directory 3.377 + close_directory_secure_cwd(dirp, saved_cwd_fd); 3.378 + 3.379 return -1; 3.380 } 3.381 + // close the directory and reset the current working directory 3.382 + close_directory_secure_cwd(dirp, saved_cwd_fd); 3.383 3.384 // save the file descriptor 3.385 int fd = result; 3.386 3.387 + // check to see if the file is secure 3.388 + if (!is_file_secure(fd, filename)) { 3.389 + ::close(fd); 3.390 + return -1; 3.391 + } 3.392 + 3.393 + // truncate the file to get rid of any existing data 3.394 + RESTARTABLE(::ftruncate(fd, (off_t)0), result); 3.395 + if (result == OS_ERR) { 3.396 + if (PrintMiscellaneous && Verbose) { 3.397 + warning("could not truncate shared memory file: %s\n", strerror(errno)); 3.398 + } 3.399 + ::close(fd); 3.400 + return -1; 3.401 + } 3.402 // set the file size 3.403 RESTARTABLE(::ftruncate(fd, (off_t)size), result); 3.404 if (result == OS_ERR) { 3.405 @@ -700,8 +906,15 @@ 3.406 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); 3.407 } 3.408 } 3.409 + int fd = result; 3.410 3.411 - return result; 3.412 + // check to see if the file is secure 3.413 + if (!is_file_secure(fd, filename)) { 3.414 + ::close(fd); 3.415 + return -1; 3.416 + } 3.417 + 3.418 + return fd; 3.419 } 3.420 3.421 // create a named shared memory region. returns the address of the 3.422 @@ -733,13 +946,21 @@ 3.423 char* dirname = get_user_tmp_dir(user_name); 3.424 char* filename = get_sharedmem_filename(dirname, vmid); 3.425 3.426 + // get the short filename 3.427 + char* short_filename = strrchr(filename, '/'); 3.428 + if (short_filename == NULL) { 3.429 + short_filename = filename; 3.430 + } else { 3.431 + short_filename++; 3.432 + } 3.433 + 3.434 // cleanup any stale shared memory files 3.435 cleanup_sharedmem_resources(dirname); 3.436 3.437 assert(((size > 0) && (size % os::vm_page_size() == 0)), 3.438 "unexpected PerfMemory region size"); 3.439 3.440 - fd = create_sharedmem_resources(dirname, filename, size); 3.441 + fd = create_sharedmem_resources(dirname, short_filename, size); 3.442 3.443 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); 3.444 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); 3.445 @@ -855,12 +1076,12 @@ 3.446 // constructs for the file and the shared memory mapping. 3.447 if (mode == PerfMemory::PERF_MODE_RO) { 3.448 mmap_prot = PROT_READ; 3.449 - file_flags = O_RDONLY; 3.450 + file_flags = O_RDONLY | O_NOFOLLOW; 3.451 } 3.452 else if (mode == PerfMemory::PERF_MODE_RW) { 3.453 #ifdef LATER 3.454 mmap_prot = PROT_READ | PROT_WRITE; 3.455 - file_flags = O_RDWR; 3.456 + file_flags = O_RDWR | O_NOFOLLOW; 3.457 #else 3.458 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 3.459 "Unsupported access mode");
4.1 --- a/src/share/vm/utilities/vmError.cpp Mon Nov 10 09:47:41 2014 -0800 4.2 +++ b/src/share/vm/utilities/vmError.cpp Mon Nov 17 15:51:46 2014 -0500 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 }