197 // successful conversion, return the pid |
197 // successful conversion, return the pid |
198 return pid; |
198 return pid; |
199 } |
199 } |
200 |
200 |
201 |
201 |
202 // check if the given path is considered a secure directory for |
202 // Check if the given statbuf is considered a secure directory for |
|
203 // the backing store files. Returns true if the directory is considered |
|
204 // a secure location. Returns false if the statbuf is a symbolic link or |
|
205 // if an error occurred. |
|
206 // |
|
207 static bool is_statbuf_secure(struct stat *statp) { |
|
208 if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { |
|
209 // The path represents a link or some non-directory file type, |
|
210 // which is not what we expected. Declare it insecure. |
|
211 // |
|
212 return false; |
|
213 } |
|
214 // We have an existing directory, check if the permissions are safe. |
|
215 // |
|
216 if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { |
|
217 // The directory is open for writing and could be subjected |
|
218 // to a symlink or a hard link attack. Declare it insecure. |
|
219 // |
|
220 return false; |
|
221 } |
|
222 // See if the uid of the directory matches the effective uid of the process. |
|
223 // |
|
224 if (statp->st_uid != geteuid()) { |
|
225 // The directory was not created by this user, declare it insecure. |
|
226 // |
|
227 return false; |
|
228 } |
|
229 return true; |
|
230 } |
|
231 |
|
232 |
|
233 // Check if the given path is considered a secure directory for |
203 // the backing store files. Returns true if the directory exists |
234 // the backing store files. Returns true if the directory exists |
204 // and is considered a secure location. Returns false if the path |
235 // and is considered a secure location. Returns false if the path |
205 // is a symbolic link or if an error occurred. |
236 // is a symbolic link or if an error occurred. |
206 // |
237 // |
207 static bool is_directory_secure(const char* path) { |
238 static bool is_directory_secure(const char* path) { |
211 RESTARTABLE(::lstat(path, &statbuf), result); |
242 RESTARTABLE(::lstat(path, &statbuf), result); |
212 if (result == OS_ERR) { |
243 if (result == OS_ERR) { |
213 return false; |
244 return false; |
214 } |
245 } |
215 |
246 |
216 // the path exists, now check it's mode |
247 // The path exists, see if it is secure. |
217 if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { |
248 return is_statbuf_secure(&statbuf); |
218 // the path represents a link or some non-directory file type, |
249 } |
219 // which is not what we expected. declare it insecure. |
250 |
220 // |
251 |
|
252 // Check if the given directory file descriptor is considered a secure |
|
253 // directory for the backing store files. Returns true if the directory |
|
254 // exists and is considered a secure location. Returns false if the path |
|
255 // is a symbolic link or if an error occurred. |
|
256 // |
|
257 static bool is_dirfd_secure(int dir_fd) { |
|
258 struct stat statbuf; |
|
259 int result = 0; |
|
260 |
|
261 RESTARTABLE(::fstat(dir_fd, &statbuf), result); |
|
262 if (result == OS_ERR) { |
221 return false; |
263 return false; |
222 } |
264 } |
223 else { |
265 |
224 // we have an existing directory, check if the permissions are safe. |
266 // The path exists, now check its mode. |
225 // |
267 return is_statbuf_secure(&statbuf); |
226 if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { |
268 } |
227 // the directory is open for writing and could be subjected |
269 |
228 // to a symlnk attack. declare it insecure. |
270 |
229 // |
271 // Check to make sure fd1 and fd2 are referencing the same file system object. |
230 return false; |
272 // |
231 } |
273 static bool is_same_fsobject(int fd1, int fd2) { |
|
274 struct stat statbuf1; |
|
275 struct stat statbuf2; |
|
276 int result = 0; |
|
277 |
|
278 RESTARTABLE(::fstat(fd1, &statbuf1), result); |
|
279 if (result == OS_ERR) { |
|
280 return false; |
|
281 } |
|
282 RESTARTABLE(::fstat(fd2, &statbuf2), result); |
|
283 if (result == OS_ERR) { |
|
284 return false; |
|
285 } |
|
286 |
|
287 if ((statbuf1.st_ino == statbuf2.st_ino) && |
|
288 (statbuf1.st_dev == statbuf2.st_dev)) { |
|
289 return true; |
|
290 } else { |
|
291 return false; |
|
292 } |
|
293 } |
|
294 |
|
295 |
|
296 // Open the directory of the given path and validate it. |
|
297 // Return a DIR * of the open directory. |
|
298 // |
|
299 static DIR *open_directory_secure(const char* dirname) { |
|
300 // Open the directory using open() so that it can be verified |
|
301 // to be secure by calling is_dirfd_secure(), opendir() and then check |
|
302 // to see if they are the same file system object. This method does not |
|
303 // introduce a window of opportunity for the directory to be attacked that |
|
304 // calling opendir() and is_directory_secure() does. |
|
305 int result; |
|
306 DIR *dirp = NULL; |
|
307 RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); |
|
308 if (result == OS_ERR) { |
|
309 // Directory doesn't exist or is a symlink, so there is nothing to cleanup. |
|
310 if (PrintMiscellaneous && Verbose) { |
|
311 if (errno == ELOOP) { |
|
312 warning("directory %s is a symlink and is not secure\n", dirname); |
|
313 } else { |
|
314 warning("could not open directory %s: %s\n", dirname, strerror(errno)); |
|
315 } |
|
316 } |
|
317 return dirp; |
|
318 } |
|
319 int fd = result; |
|
320 |
|
321 // Determine if the open directory is secure. |
|
322 if (!is_dirfd_secure(fd)) { |
|
323 // The directory is not a secure directory. |
|
324 os::close(fd); |
|
325 return dirp; |
|
326 } |
|
327 |
|
328 // Open the directory. |
|
329 dirp = ::opendir(dirname); |
|
330 if (dirp == NULL) { |
|
331 // The directory doesn't exist, close fd and return. |
|
332 os::close(fd); |
|
333 return dirp; |
|
334 } |
|
335 |
|
336 // Check to make sure fd and dirp are referencing the same file system object. |
|
337 if (!is_same_fsobject(fd, dirp->dd_fd)) { |
|
338 // The directory is not secure. |
|
339 os::close(fd); |
|
340 os::closedir(dirp); |
|
341 dirp = NULL; |
|
342 return dirp; |
|
343 } |
|
344 |
|
345 // Close initial open now that we know directory is secure |
|
346 os::close(fd); |
|
347 |
|
348 return dirp; |
|
349 } |
|
350 |
|
351 // NOTE: The code below uses fchdir(), open() and unlink() because |
|
352 // fdopendir(), openat() and unlinkat() are not supported on all |
|
353 // versions. Once the support for fdopendir(), openat() and unlinkat() |
|
354 // is available on all supported versions the code can be changed |
|
355 // to use these functions. |
|
356 |
|
357 // Open the directory of the given path, validate it and set the |
|
358 // current working directory to it. |
|
359 // Return a DIR * of the open directory and the saved cwd fd. |
|
360 // |
|
361 static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { |
|
362 |
|
363 // Open the directory. |
|
364 DIR* dirp = open_directory_secure(dirname); |
|
365 if (dirp == NULL) { |
|
366 // Directory doesn't exist or is insecure, so there is nothing to cleanup. |
|
367 return dirp; |
|
368 } |
|
369 int fd = dirp->dd_fd; |
|
370 |
|
371 // Open a fd to the cwd and save it off. |
|
372 int result; |
|
373 RESTARTABLE(::open(".", O_RDONLY), result); |
|
374 if (result == OS_ERR) { |
|
375 *saved_cwd_fd = -1; |
|
376 } else { |
|
377 *saved_cwd_fd = result; |
|
378 } |
|
379 |
|
380 // Set the current directory to dirname by using the fd of the directory. |
|
381 result = fchdir(fd); |
|
382 |
|
383 return dirp; |
|
384 } |
|
385 |
|
386 // Close the directory and restore the current working directory. |
|
387 // |
|
388 static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { |
|
389 |
|
390 int result; |
|
391 // If we have a saved cwd change back to it and close the fd. |
|
392 if (saved_cwd_fd != -1) { |
|
393 result = fchdir(saved_cwd_fd); |
|
394 ::close(saved_cwd_fd); |
|
395 } |
|
396 |
|
397 // Close the directory. |
|
398 os::closedir(dirp); |
|
399 } |
|
400 |
|
401 // Check if the given file descriptor is considered a secure. |
|
402 // |
|
403 static bool is_file_secure(int fd, const char *filename) { |
|
404 |
|
405 int result; |
|
406 struct stat statbuf; |
|
407 |
|
408 // Determine if the file is secure. |
|
409 RESTARTABLE(::fstat(fd, &statbuf), result); |
|
410 if (result == OS_ERR) { |
|
411 if (PrintMiscellaneous && Verbose) { |
|
412 warning("fstat failed on %s: %s\n", filename, strerror(errno)); |
|
413 } |
|
414 return false; |
|
415 } |
|
416 if (statbuf.st_nlink > 1) { |
|
417 // A file with multiple links is not expected. |
|
418 if (PrintMiscellaneous && Verbose) { |
|
419 warning("file %s has multiple links\n", filename); |
|
420 } |
|
421 return false; |
232 } |
422 } |
233 return true; |
423 return true; |
234 } |
424 } |
235 |
|
236 |
425 |
237 // return the user name for the given user id |
426 // return the user name for the given user id |
238 // |
427 // |
239 // the caller is expected to free the allocated memory. |
428 // the caller is expected to free the allocated memory. |
240 // |
429 // |
650 // could not make/find the directory or the found directory |
820 // could not make/find the directory or the found directory |
651 // was not secure |
821 // was not secure |
652 return -1; |
822 return -1; |
653 } |
823 } |
654 |
824 |
|
825 int saved_cwd_fd; |
|
826 // open the directory and set the current working directory to it |
|
827 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); |
|
828 if (dirp == NULL) { |
|
829 // Directory doesn't exist or is insecure, so cannot create shared |
|
830 // memory file. |
|
831 return -1; |
|
832 } |
|
833 |
|
834 // Open the filename in the current directory. |
|
835 // Cannot use O_TRUNC here; truncation of an existing file has to happen |
|
836 // after the is_file_secure() check below. |
655 int result; |
837 int result; |
656 |
838 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); |
657 RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); |
|
658 if (result == OS_ERR) { |
839 if (result == OS_ERR) { |
659 if (PrintMiscellaneous && Verbose) { |
840 if (PrintMiscellaneous && Verbose) { |
660 warning("could not create file %s: %s\n", filename, strerror(errno)); |
841 if (errno == ELOOP) { |
661 } |
842 warning("file %s is a symlink and is not secure\n", filename); |
|
843 } else { |
|
844 warning("could not create file %s: %s\n", filename, strerror(errno)); |
|
845 } |
|
846 } |
|
847 // close the directory and reset the current working directory |
|
848 close_directory_secure_cwd(dirp, saved_cwd_fd); |
|
849 |
662 return -1; |
850 return -1; |
663 } |
851 } |
|
852 // close the directory and reset the current working directory |
|
853 close_directory_secure_cwd(dirp, saved_cwd_fd); |
664 |
854 |
665 // save the file descriptor |
855 // save the file descriptor |
666 int fd = result; |
856 int fd = result; |
667 |
857 |
|
858 // check to see if the file is secure |
|
859 if (!is_file_secure(fd, filename)) { |
|
860 ::close(fd); |
|
861 return -1; |
|
862 } |
|
863 |
|
864 // truncate the file to get rid of any existing data |
|
865 RESTARTABLE(::ftruncate(fd, (off_t)0), result); |
|
866 if (result == OS_ERR) { |
|
867 if (PrintMiscellaneous && Verbose) { |
|
868 warning("could not truncate shared memory file: %s\n", strerror(errno)); |
|
869 } |
|
870 ::close(fd); |
|
871 return -1; |
|
872 } |
668 // set the file size |
873 // set the file size |
669 RESTARTABLE(::ftruncate(fd, (off_t)size), result); |
874 RESTARTABLE(::ftruncate(fd, (off_t)size), result); |
670 if (result == OS_ERR) { |
875 if (result == OS_ERR) { |
671 if (PrintMiscellaneous && Verbose) { |
876 if (PrintMiscellaneous && Verbose) { |
672 warning("could not set shared memory file size: %s\n", strerror(errno)); |
877 warning("could not set shared memory file size: %s\n", strerror(errno)); |
731 return NULL; |
943 return NULL; |
732 |
944 |
733 char* dirname = get_user_tmp_dir(user_name); |
945 char* dirname = get_user_tmp_dir(user_name); |
734 char* filename = get_sharedmem_filename(dirname, vmid); |
946 char* filename = get_sharedmem_filename(dirname, vmid); |
735 |
947 |
|
948 // get the short filename |
|
949 char* short_filename = strrchr(filename, '/'); |
|
950 if (short_filename == NULL) { |
|
951 short_filename = filename; |
|
952 } else { |
|
953 short_filename++; |
|
954 } |
|
955 |
736 // cleanup any stale shared memory files |
956 // cleanup any stale shared memory files |
737 cleanup_sharedmem_resources(dirname); |
957 cleanup_sharedmem_resources(dirname); |
738 |
958 |
739 assert(((size > 0) && (size % os::vm_page_size() == 0)), |
959 assert(((size > 0) && (size % os::vm_page_size() == 0)), |
740 "unexpected PerfMemory region size"); |
960 "unexpected PerfMemory region size"); |
741 |
961 |
742 fd = create_sharedmem_resources(dirname, filename, size); |
962 fd = create_sharedmem_resources(dirname, short_filename, size); |
743 |
963 |
744 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
964 FREE_C_HEAP_ARRAY(char, user_name, mtInternal); |
745 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
965 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
746 |
966 |
747 if (fd == -1) { |
967 if (fd == -1) { |