1.1 --- a/src/os/linux/vm/perfMemory_linux.cpp Mon Nov 24 09:18:13 2014 -0800 1.2 +++ b/src/os/linux/vm/perfMemory_linux.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,22 +242,180 @@ 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 + if (PrintMiscellaneous && Verbose) { 1.123 + if (errno == ELOOP) { 1.124 + warning("directory %s is a symlink and is not secure\n", dirname); 1.125 + } else { 1.126 + warning("could not open directory %s: %s\n", dirname, strerror(errno)); 1.127 + } 1.128 } 1.129 + return dirp; 1.130 + } 1.131 + int fd = result; 1.132 + 1.133 + // Determine if the open directory is secure. 1.134 + if (!is_dirfd_secure(fd)) { 1.135 + // The directory is not a secure directory. 1.136 + os::close(fd); 1.137 + return dirp; 1.138 + } 1.139 + 1.140 + // Open the directory. 1.141 + dirp = ::opendir(dirname); 1.142 + if (dirp == NULL) { 1.143 + // The directory doesn't exist, close fd and return. 1.144 + os::close(fd); 1.145 + return dirp; 1.146 + } 1.147 + 1.148 + // Check to make sure fd and dirp are referencing the same file system object. 1.149 + if (!is_same_fsobject(fd, dirfd(dirp))) { 1.150 + // The directory is not secure. 1.151 + os::close(fd); 1.152 + os::closedir(dirp); 1.153 + dirp = NULL; 1.154 + return dirp; 1.155 + } 1.156 + 1.157 + // Close initial open now that we know directory is secure 1.158 + os::close(fd); 1.159 + 1.160 + return dirp; 1.161 +} 1.162 + 1.163 +// NOTE: The code below uses fchdir(), open() and unlink() because 1.164 +// fdopendir(), openat() and unlinkat() are not supported on all 1.165 +// versions. Once the support for fdopendir(), openat() and unlinkat() 1.166 +// is available on all supported versions the code can be changed 1.167 +// to use these functions. 1.168 + 1.169 +// Open the directory of the given path, validate it and set the 1.170 +// current working directory to it. 1.171 +// Return a DIR * of the open directory and the saved cwd fd. 1.172 +// 1.173 +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { 1.174 + 1.175 + // Open the directory. 1.176 + DIR* dirp = open_directory_secure(dirname); 1.177 + if (dirp == NULL) { 1.178 + // Directory doesn't exist or is insecure, so there is nothing to cleanup. 1.179 + return dirp; 1.180 + } 1.181 + int fd = dirfd(dirp); 1.182 + 1.183 + // Open a fd to the cwd and save it off. 1.184 + int result; 1.185 + RESTARTABLE(::open(".", O_RDONLY), result); 1.186 + if (result == OS_ERR) { 1.187 + *saved_cwd_fd = -1; 1.188 + } else { 1.189 + *saved_cwd_fd = result; 1.190 + } 1.191 + 1.192 + // Set the current directory to dirname by using the fd of the directory. 1.193 + result = fchdir(fd); 1.194 + 1.195 + return dirp; 1.196 +} 1.197 + 1.198 +// Close the directory and restore the current working directory. 1.199 +// 1.200 +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { 1.201 + 1.202 + int result; 1.203 + // If we have a saved cwd change back to it and close the fd. 1.204 + if (saved_cwd_fd != -1) { 1.205 + result = fchdir(saved_cwd_fd); 1.206 + ::close(saved_cwd_fd); 1.207 + } 1.208 + 1.209 + // Close the directory. 1.210 + os::closedir(dirp); 1.211 +} 1.212 + 1.213 +// Check if the given file descriptor is considered a secure. 1.214 +// 1.215 +static bool is_file_secure(int fd, const char *filename) { 1.216 + 1.217 + int result; 1.218 + struct stat statbuf; 1.219 + 1.220 + // Determine if the file is secure. 1.221 + RESTARTABLE(::fstat(fd, &statbuf), result); 1.222 + if (result == OS_ERR) { 1.223 + if (PrintMiscellaneous && Verbose) { 1.224 + warning("fstat failed on %s: %s\n", filename, strerror(errno)); 1.225 + } 1.226 + return false; 1.227 + } 1.228 + if (statbuf.st_nlink > 1) { 1.229 + // A file with multiple links is not expected. 1.230 + if (PrintMiscellaneous && Verbose) { 1.231 + warning("file %s has multiple links\n", filename); 1.232 + } 1.233 + return false; 1.234 } 1.235 return true; 1.236 } 1.237 @@ -317,9 +506,11 @@ 1.238 1.239 const char* tmpdirname = os::get_temp_directory(); 1.240 1.241 + // open the temp directory 1.242 DIR* tmpdirp = os::opendir(tmpdirname); 1.243 1.244 if (tmpdirp == NULL) { 1.245 + // Cannot open the directory to get the user name, return. 1.246 return NULL; 1.247 } 1.248 1.249 @@ -344,7 +535,8 @@ 1.250 strcat(usrdir_name, "/"); 1.251 strcat(usrdir_name, dentry->d_name); 1.252 1.253 - DIR* subdirp = os::opendir(usrdir_name); 1.254 + // open the user directory 1.255 + DIR* subdirp = open_directory_secure(usrdir_name); 1.256 1.257 if (subdirp == NULL) { 1.258 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); 1.259 @@ -465,26 +657,6 @@ 1.260 } 1.261 1.262 1.263 -// remove file 1.264 -// 1.265 -// this method removes the file with the given file name in the 1.266 -// named directory. 1.267 -// 1.268 -static void remove_file(const char* dirname, const char* filename) { 1.269 - 1.270 - size_t nbytes = strlen(dirname) + strlen(filename) + 2; 1.271 - char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); 1.272 - 1.273 - strcpy(path, dirname); 1.274 - strcat(path, "/"); 1.275 - strcat(path, filename); 1.276 - 1.277 - remove_file(path); 1.278 - 1.279 - FREE_C_HEAP_ARRAY(char, path, mtInternal); 1.280 -} 1.281 - 1.282 - 1.283 // cleanup stale shared memory resources 1.284 // 1.285 // This method attempts to remove all stale shared memory files in 1.286 @@ -496,16 +668,11 @@ 1.287 // 1.288 static void cleanup_sharedmem_resources(const char* dirname) { 1.289 1.290 - // open the user temp directory 1.291 - DIR* dirp = os::opendir(dirname); 1.292 - 1.293 + int saved_cwd_fd; 1.294 + // open the directory 1.295 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 1.296 if (dirp == NULL) { 1.297 - // directory doesn't exist, so there is nothing to cleanup 1.298 - return; 1.299 - } 1.300 - 1.301 - if (!is_directory_secure(dirname)) { 1.302 - // the directory is not a secure directory 1.303 + // directory doesn't exist or is insecure, so there is nothing to cleanup 1.304 return; 1.305 } 1.306 1.307 @@ -519,6 +686,7 @@ 1.308 // 1.309 struct dirent* entry; 1.310 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); 1.311 + 1.312 errno = 0; 1.313 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { 1.314 1.315 @@ -527,9 +695,8 @@ 1.316 if (pid == 0) { 1.317 1.318 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { 1.319 - 1.320 // attempt to remove all unexpected files, except "." and ".." 1.321 - remove_file(dirname, entry->d_name); 1.322 + unlink(entry->d_name); 1.323 } 1.324 1.325 errno = 0; 1.326 @@ -551,12 +718,14 @@ 1.327 // 1.328 if ((pid == os::current_process_id()) || 1.329 (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { 1.330 - 1.331 - remove_file(dirname, entry->d_name); 1.332 + unlink(entry->d_name); 1.333 } 1.334 errno = 0; 1.335 } 1.336 - os::closedir(dirp); 1.337 + 1.338 + // close the directory and reset the current working directory 1.339 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.340 + 1.341 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); 1.342 } 1.343 1.344 @@ -613,19 +782,54 @@ 1.345 return -1; 1.346 } 1.347 1.348 + int saved_cwd_fd; 1.349 + // open the directory and set the current working directory to it 1.350 + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); 1.351 + if (dirp == NULL) { 1.352 + // Directory doesn't exist or is insecure, so cannot create shared 1.353 + // memory file. 1.354 + return -1; 1.355 + } 1.356 + 1.357 + // Open the filename in the current directory. 1.358 + // Cannot use O_TRUNC here; truncation of an existing file has to happen 1.359 + // after the is_file_secure() check below. 1.360 int result; 1.361 - 1.362 - RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); 1.363 + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); 1.364 if (result == OS_ERR) { 1.365 if (PrintMiscellaneous && Verbose) { 1.366 - warning("could not create file %s: %s\n", filename, strerror(errno)); 1.367 + if (errno == ELOOP) { 1.368 + warning("file %s is a symlink and is not secure\n", filename); 1.369 + } else { 1.370 + warning("could not create file %s: %s\n", filename, strerror(errno)); 1.371 + } 1.372 } 1.373 + // close the directory and reset the current working directory 1.374 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.375 + 1.376 return -1; 1.377 } 1.378 + // close the directory and reset the current working directory 1.379 + close_directory_secure_cwd(dirp, saved_cwd_fd); 1.380 1.381 // save the file descriptor 1.382 int fd = result; 1.383 1.384 + // check to see if the file is secure 1.385 + if (!is_file_secure(fd, filename)) { 1.386 + ::close(fd); 1.387 + return -1; 1.388 + } 1.389 + 1.390 + // truncate the file to get rid of any existing data 1.391 + RESTARTABLE(::ftruncate(fd, (off_t)0), result); 1.392 + if (result == OS_ERR) { 1.393 + if (PrintMiscellaneous && Verbose) { 1.394 + warning("could not truncate shared memory file: %s\n", strerror(errno)); 1.395 + } 1.396 + ::close(fd); 1.397 + return -1; 1.398 + } 1.399 // set the file size 1.400 RESTARTABLE(::ftruncate(fd, (off_t)size), result); 1.401 if (result == OS_ERR) { 1.402 @@ -683,8 +887,15 @@ 1.403 THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR); 1.404 } 1.405 } 1.406 + int fd = result; 1.407 1.408 - return result; 1.409 + // check to see if the file is secure 1.410 + if (!is_file_secure(fd, filename)) { 1.411 + ::close(fd); 1.412 + return -1; 1.413 + } 1.414 + 1.415 + return fd; 1.416 } 1.417 1.418 // create a named shared memory region. returns the address of the 1.419 @@ -715,6 +926,13 @@ 1.420 1.421 char* dirname = get_user_tmp_dir(user_name); 1.422 char* filename = get_sharedmem_filename(dirname, vmid); 1.423 + // get the short filename 1.424 + char* short_filename = strrchr(filename, '/'); 1.425 + if (short_filename == NULL) { 1.426 + short_filename = filename; 1.427 + } else { 1.428 + short_filename++; 1.429 + } 1.430 1.431 // cleanup any stale shared memory files 1.432 cleanup_sharedmem_resources(dirname); 1.433 @@ -722,7 +940,7 @@ 1.434 assert(((size > 0) && (size % os::vm_page_size() == 0)), 1.435 "unexpected PerfMemory region size"); 1.436 1.437 - fd = create_sharedmem_resources(dirname, filename, size); 1.438 + fd = create_sharedmem_resources(dirname, short_filename, size); 1.439 1.440 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); 1.441 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); 1.442 @@ -837,12 +1055,12 @@ 1.443 // constructs for the file and the shared memory mapping. 1.444 if (mode == PerfMemory::PERF_MODE_RO) { 1.445 mmap_prot = PROT_READ; 1.446 - file_flags = O_RDONLY; 1.447 + file_flags = O_RDONLY | O_NOFOLLOW; 1.448 } 1.449 else if (mode == PerfMemory::PERF_MODE_RW) { 1.450 #ifdef LATER 1.451 mmap_prot = PROT_READ | PROT_WRITE; 1.452 - file_flags = O_RDWR; 1.453 + file_flags = O_RDWR | O_NOFOLLOW; 1.454 #else 1.455 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), 1.456 "Unsupported access mode");