Bug Summary

File:jdk/src/hotspot/os/posix/perfMemory_posix.cpp
Warning:line 416, column 5
Value stored to 'result' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name perfMemory_posix.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp
1/*
2 * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2012, 2021 SAP SE. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26#include "precompiled.hpp"
27#include "jvm_io.h"
28#include "classfile/vmSymbols.hpp"
29#include "logging/log.hpp"
30#include "memory/allocation.inline.hpp"
31#include "memory/resourceArea.hpp"
32#include "oops/oop.inline.hpp"
33#include "os_posix.inline.hpp"
34#include "runtime/globals_extension.hpp"
35#include "runtime/handles.inline.hpp"
36#include "runtime/os.hpp"
37#include "runtime/perfMemory.hpp"
38#include "services/memTracker.hpp"
39#include "utilities/exceptions.hpp"
40
41// put OS-includes here
42# include <sys/types.h>
43# include <sys/mman.h>
44# include <errno(*__errno_location ()).h>
45# include <stdio.h>
46# include <unistd.h>
47# include <sys/stat.h>
48# include <signal.h>
49# include <pwd.h>
50
51static char* backing_store_file_name = NULL__null; // name of the backing store
52 // file, if successfully created.
53
54// Standard Memory Implementation Details
55
56// create the PerfData memory region in standard memory.
57//
58static char* create_standard_memory(size_t size) {
59
60 // allocate an aligned chuck of memory
61 char* mapAddress = os::reserve_memory(size);
62
63 if (mapAddress == NULL__null) {
64 return NULL__null;
65 }
66
67 // commit memory
68 if (!os::commit_memory(mapAddress, size, !ExecMem)) {
69 if (PrintMiscellaneous && Verbose) {
70 warning("Could not commit PerfData memory\n");
71 }
72 os::release_memory(mapAddress, size);
73 return NULL__null;
74 }
75
76 return mapAddress;
77}
78
79// delete the PerfData memory region
80//
81static void delete_standard_memory(char* addr, size_t size) {
82
83 // there are no persistent external resources to cleanup for standard
84 // memory. since DestroyJavaVM does not support unloading of the JVM,
85 // cleanup of the memory resource is not performed. The memory will be
86 // reclaimed by the OS upon termination of the process.
87 //
88 return;
89}
90
91// save the specified memory region to the given file
92//
93// Note: this function might be called from signal handler (by os::abort()),
94// don't allocate heap memory.
95//
96static void save_memory_to_file(char* addr, size_t size) {
97
98 const char* destfile = PerfMemory::get_perfdata_file_path();
99 assert(destfile[0] != '\0', "invalid PerfData file path")do { if (!(destfile[0] != '\0')) { (*g_assert_poison) = 'X';;
report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 99, "assert(" "destfile[0] != '\\0'" ") failed", "invalid PerfData file path"
); ::breakpoint(); } } while (0)
;
100
101 int result;
102
103 RESTARTABLE(os::open(destfile, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR),do { result = os::open(destfile, 0100|01|01000, 0400|0200); }
while(((int)result == OS_ERR) && ((*__errno_location
()) == 4))
104 result)do { result = os::open(destfile, 0100|01|01000, 0400|0200); }
while(((int)result == OS_ERR) && ((*__errno_location
()) == 4))
;
105 if (result == OS_ERR) {
106 if (PrintMiscellaneous && Verbose) {
107 warning("Could not create Perfdata save file: %s: %s\n",
108 destfile, os::strerror(errno(*__errno_location ())));
109 }
110 } else {
111 int fd = result;
112
113 for (size_t remaining = size; remaining > 0;) {
114
115 RESTARTABLE(::write(fd, addr, remaining), result)do { result = ::write(fd, addr, remaining); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
116 if (result == OS_ERR) {
117 if (PrintMiscellaneous && Verbose) {
118 warning("Could not write Perfdata save file: %s: %s\n",
119 destfile, os::strerror(errno(*__errno_location ())));
120 }
121 break;
122 }
123
124 remaining -= (size_t)result;
125 addr += result;
126 }
127
128 result = ::close(fd);
129 if (PrintMiscellaneous && Verbose) {
130 if (result == OS_ERR) {
131 warning("Could not close %s: %s\n", destfile, os::strerror(errno(*__errno_location ())));
132 }
133 }
134 }
135 FREE_C_HEAP_ARRAY(char, destfile)FreeHeap((char*)(destfile));
136}
137
138
139// Shared Memory Implementation Details
140
141// Note: the Posix shared memory implementation uses the mmap
142// interface with a backing store file to implement named shared memory.
143// Using the file system as the name space for shared memory allows a
144// common name space to be supported across a variety of platforms. It
145// also provides a name space that Java applications can deal with through
146// simple file apis.
147//
148
149// return the user specific temporary directory name.
150// the caller is expected to free the allocated memory.
151//
152#define TMP_BUFFER_LEN(4+22) (4+22)
153static char* get_user_tmp_dir(const char* user, int vmid, int nspid) {
154 char* tmpdir = (char *)os::get_temp_directory();
155#if defined(LINUX1)
156 // On linux, if containerized process, get dirname of
157 // /proc/{vmid}/root/tmp/{PERFDATA_NAME_user}
158 // otherwise /tmp/{PERFDATA_NAME_user}
159 char buffer[TMP_BUFFER_LEN(4+22)];
160 assert(strlen(tmpdir) == 4, "No longer using /tmp - update buffer size")do { if (!(strlen(tmpdir) == 4)) { (*g_assert_poison) = 'X';;
report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 160, "assert(" "strlen(tmpdir) == 4" ") failed", "No longer using /tmp - update buffer size"
); ::breakpoint(); } } while (0)
;
161
162 if (nspid != -1) {
163 jio_snprintf(buffer, TMP_BUFFER_LEN(4+22), "/proc/%d/root%s", vmid, tmpdir);
164 tmpdir = buffer;
165 }
166#endif
167 const char* perfdir = PERFDATA_NAME;
168 size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
169 char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal)(char*) (AllocateHeap((nbytes) * sizeof(char), mtInternal));
170
171 // construct the path name to user specific tmp directory
172 snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
173
174 return dirname;
175}
176
177// convert the given file name into a process id. if the file
178// does not meet the file naming constraints, return 0.
179//
180static pid_t filename_to_pid(const char* filename) {
181
182 // a filename that doesn't begin with a digit is not a
183 // candidate for conversion.
184 //
185 if (!isdigit(*filename)) {
186 return 0;
187 }
188
189 // check if file name can be converted to an integer without
190 // any leftover characters.
191 //
192 char* remainder = NULL__null;
193 errno(*__errno_location ()) = 0;
194 pid_t pid = (pid_t)strtol(filename, &remainder, 10);
195
196 if (errno(*__errno_location ()) != 0) {
197 return 0;
198 }
199
200 // check for left over characters. If any, then the filename is
201 // not a candidate for conversion.
202 //
203 if (remainder != NULL__null && *remainder != '\0') {
204 return 0;
205 }
206
207 // successful conversion, return the pid
208 return pid;
209}
210
211
212// Check if the given statbuf is considered a secure directory for
213// the backing store files. Returns true if the directory is considered
214// a secure location. Returns false if the statbuf is a symbolic link or
215// if an error occurred.
216//
217static bool is_statbuf_secure(struct stat *statp) {
218 if (S_ISLNK(statp->st_mode)((((statp->st_mode)) & 0170000) == (0120000)) || !S_ISDIR(statp->st_mode)((((statp->st_mode)) & 0170000) == (0040000))) {
219 // The path represents a link or some non-directory file type,
220 // which is not what we expected. Declare it insecure.
221 //
222 return false;
223 }
224 // We have an existing directory, check if the permissions are safe.
225 //
226 if ((statp->st_mode & (S_IWGRP(0200 >> 3)|S_IWOTH((0200 >> 3) >> 3))) != 0) {
227 // The directory is open for writing and could be subjected
228 // to a symlink or a hard link attack. Declare it insecure.
229 //
230 return false;
231 }
232 // If user is not root then see if the uid of the directory matches the effective uid of the process.
233 uid_t euid = geteuid();
234 if ((euid != 0) && (statp->st_uid != euid)) {
235 // The directory was not created by this user, declare it insecure.
236 //
237 return false;
238 }
239 return true;
240}
241
242
243// Check if the given path is considered a secure directory for
244// the backing store files. Returns true if the directory exists
245// and is considered a secure location. Returns false if the path
246// is a symbolic link or if an error occurred.
247//
248static bool is_directory_secure(const char* path) {
249 struct stat statbuf;
250 int result = 0;
251
252 RESTARTABLE(::lstat(path, &statbuf), result)do { result = ::lstat(path, &statbuf); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
253 if (result == OS_ERR) {
254 return false;
255 }
256
257 // The path exists, see if it is secure.
258 return is_statbuf_secure(&statbuf);
259}
260
261
262// Check if the given directory file descriptor is considered a secure
263// directory for the backing store files. Returns true if the directory
264// exists and is considered a secure location. Returns false if the path
265// is a symbolic link or if an error occurred.
266//
267static bool is_dirfd_secure(int dir_fd) {
268 struct stat statbuf;
269 int result = 0;
270
271 RESTARTABLE(::fstat(dir_fd, &statbuf), result)do { result = ::fstat(dir_fd, &statbuf); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
272 if (result == OS_ERR) {
273 return false;
274 }
275
276 // The path exists, now check its mode.
277 return is_statbuf_secure(&statbuf);
278}
279
280
281// Check to make sure fd1 and fd2 are referencing the same file system object.
282//
283static bool is_same_fsobject(int fd1, int fd2) {
284 struct stat statbuf1;
285 struct stat statbuf2;
286 int result = 0;
287
288 RESTARTABLE(::fstat(fd1, &statbuf1), result)do { result = ::fstat(fd1, &statbuf1); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
289 if (result == OS_ERR) {
290 return false;
291 }
292 RESTARTABLE(::fstat(fd2, &statbuf2), result)do { result = ::fstat(fd2, &statbuf2); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
293 if (result == OS_ERR) {
294 return false;
295 }
296
297 if ((statbuf1.st_ino == statbuf2.st_ino) &&
298 (statbuf1.st_dev == statbuf2.st_dev)) {
299 return true;
300 } else {
301 return false;
302 }
303}
304
305
306// Open the directory of the given path and validate it.
307// Return a DIR * of the open directory.
308//
309static DIR *open_directory_secure(const char* dirname) {
310 // Open the directory using open() so that it can be verified
311 // to be secure by calling is_dirfd_secure(), opendir() and then check
312 // to see if they are the same file system object. This method does not
313 // introduce a window of opportunity for the directory to be attacked that
314 // calling opendir() and is_directory_secure() does.
315 int result;
316 DIR *dirp = NULL__null;
317 RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result)do { result = ::open(dirname, 00|0400000); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
318 if (result == OS_ERR) {
319 // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
320 if (PrintMiscellaneous && Verbose) {
321 if (errno(*__errno_location ()) == ELOOP40) {
322 warning("directory %s is a symlink and is not secure\n", dirname);
323 } else {
324 warning("could not open directory %s: %s\n", dirname, os::strerror(errno(*__errno_location ())));
325 }
326 }
327 return dirp;
328 }
329 int fd = result;
330
331 // Determine if the open directory is secure.
332 if (!is_dirfd_secure(fd)) {
333 // The directory is not a secure directory.
334 os::close(fd);
335 return dirp;
336 }
337
338 // Open the directory.
339 dirp = ::opendir(dirname);
340 if (dirp == NULL__null) {
341 // The directory doesn't exist, close fd and return.
342 os::close(fd);
343 return dirp;
344 }
345
346 // Check to make sure fd and dirp are referencing the same file system object.
347 if (!is_same_fsobject(fd, AIX_ONLY(dirp->dd_fd) NOT_AIX(dirfd(dirp))dirfd(dirp))) {
348 // The directory is not secure.
349 os::close(fd);
350 os::closedir(dirp);
351 dirp = NULL__null;
352 return dirp;
353 }
354
355 // Close initial open now that we know directory is secure
356 os::close(fd);
357
358 return dirp;
359}
360
361// NOTE: The code below uses fchdir(), open() and unlink() because
362// fdopendir(), openat() and unlinkat() are not supported on all
363// versions. Once the support for fdopendir(), openat() and unlinkat()
364// is available on all supported versions the code can be changed
365// to use these functions.
366
367// Open the directory of the given path, validate it and set the
368// current working directory to it.
369// Return a DIR * of the open directory and the saved cwd fd.
370//
371static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
372
373 // Open the directory.
374 DIR* dirp = open_directory_secure(dirname);
375 if (dirp == NULL__null) {
376 // Directory doesn't exist or is insecure, so there is nothing to cleanup.
377 return dirp;
378 }
379 int fd = AIX_ONLY(dirp->dd_fd) NOT_AIX(dirfd(dirp))dirfd(dirp);
380
381 // Open a fd to the cwd and save it off.
382 int result;
383 RESTARTABLE(::open(".", O_RDONLY), result)do { result = ::open(".", 00); } while(((int)result == OS_ERR
) && ((*__errno_location ()) == 4))
;
384 if (result == OS_ERR) {
385 *saved_cwd_fd = -1;
386 } else {
387 *saved_cwd_fd = result;
388 }
389
390 // Set the current directory to dirname by using the fd of the directory and
391 // handle errors, otherwise shared memory files will be created in cwd.
392 result = fchdir(fd);
393 if (result == OS_ERR) {
394 if (PrintMiscellaneous && Verbose) {
395 warning("could not change to directory %s", dirname);
396 }
397 if (*saved_cwd_fd != -1) {
398 ::close(*saved_cwd_fd);
399 *saved_cwd_fd = -1;
400 }
401 // Close the directory.
402 os::closedir(dirp);
403 return NULL__null;
404 } else {
405 return dirp;
406 }
407}
408
409// Close the directory and restore the current working directory.
410//
411static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
412
413 int result;
414 // If we have a saved cwd change back to it and close the fd.
415 if (saved_cwd_fd != -1) {
416 result = fchdir(saved_cwd_fd);
Value stored to 'result' is never read
417 ::close(saved_cwd_fd);
418 }
419
420 // Close the directory.
421 os::closedir(dirp);
422}
423
424// Check if the given file descriptor is considered a secure.
425//
426static bool is_file_secure(int fd, const char *filename) {
427
428 int result;
429 struct stat statbuf;
430
431 // Determine if the file is secure.
432 RESTARTABLE(::fstat(fd, &statbuf), result)do { result = ::fstat(fd, &statbuf); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
433 if (result == OS_ERR) {
434 if (PrintMiscellaneous && Verbose) {
435 warning("fstat failed on %s: %s\n", filename, os::strerror(errno(*__errno_location ())));
436 }
437 return false;
438 }
439 if (statbuf.st_nlink > 1) {
440 // A file with multiple links is not expected.
441 if (PrintMiscellaneous && Verbose) {
442 warning("file %s has multiple links\n", filename);
443 }
444 return false;
445 }
446 return true;
447}
448
449
450// return the user name for the given user id
451//
452// the caller is expected to free the allocated memory.
453//
454static char* get_user_name(uid_t uid) {
455
456 struct passwd pwent;
457
458 // Determine the max pwbuf size from sysconf, and hardcode
459 // a default if this not available through sysconf.
460 long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX_SC_GETPW_R_SIZE_MAX);
461 if (bufsize == -1)
462 bufsize = 1024;
463
464 char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal)(char*) (AllocateHeap((bufsize) * sizeof(char), mtInternal));
465
466 struct passwd* p = NULL__null;
467 int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p);
468
469 if (result != 0 || p == NULL__null || p->pw_name == NULL__null || *(p->pw_name) == '\0') {
470 if (PrintMiscellaneous && Verbose) {
471 if (result != 0) {
472 warning("Could not retrieve passwd entry: %s\n",
473 os::strerror(result));
474 }
475 else if (p == NULL__null) {
476 // this check is added to protect against an observed problem
477 // with getpwuid_r() on RedHat 9 where getpwuid_r returns 0,
478 // indicating success, but has p == NULL. This was observed when
479 // inserting a file descriptor exhaustion fault prior to the call
480 // getpwuid_r() call. In this case, error is set to the appropriate
481 // error condition, but this is undocumented behavior. This check
482 // is safe under any condition, but the use of errno in the output
483 // message may result in an erroneous message.
484 // Bug Id 89052 was opened with RedHat.
485 //
486 warning("Could not retrieve passwd entry: %s\n",
487 os::strerror(errno(*__errno_location ())));
488 }
489 else {
490 warning("Could not determine user name: %s\n",
491 p->pw_name == NULL__null ? "pw_name = NULL" :
492 "pw_name zero length");
493 }
494 }
495 FREE_C_HEAP_ARRAY(char, pwbuf)FreeHeap((char*)(pwbuf));
496 return NULL__null;
497 }
498
499 char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal)(char*) (AllocateHeap((strlen(p->pw_name) + 1) * sizeof(char
), mtInternal))
;
500 strcpy(user_name, p->pw_name);
501
502 FREE_C_HEAP_ARRAY(char, pwbuf)FreeHeap((char*)(pwbuf));
503 return user_name;
504}
505
506// return the name of the user that owns the process identified by vmid.
507//
508// This method uses a slow directory search algorithm to find the backing
509// store file for the specified vmid and returns the user name, as determined
510// by the user name suffix of the hsperfdata_<username> directory name.
511//
512// the caller is expected to free the allocated memory.
513//
514//
515static char* get_user_name_slow(int vmid, int nspid, TRAPSJavaThread* __the_thread__) {
516
517 // short circuit the directory search if the process doesn't even exist.
518 if (kill(vmid, 0) == OS_ERR) {
519 if (errno(*__errno_location ()) == ESRCH3) {
520 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 521, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return 0; }
521 "Process not found"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 521, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return 0; }
;
522 }
523 else /* EPERM */ {
524 THROW_MSG_0(vmSymbols::java_io_IOException(), os::strerror(errno)){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 524, vmSymbols::java_io_IOException(), os::strerror((*__errno_location
()))); return 0; }
;
525 }
526 }
527
528 // directory search
529 char* oldest_user = NULL__null;
530 time_t oldest_ctime = 0;
531 int searchpid;
532 char* tmpdirname = (char *)os::get_temp_directory();
533#if defined(LINUX1)
534 char buffer[MAXPATHLEN4096 + 1];
535 assert(strlen(tmpdirname) == 4, "No longer using /tmp - update buffer size")do { if (!(strlen(tmpdirname) == 4)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 535, "assert(" "strlen(tmpdirname) == 4" ") failed", "No longer using /tmp - update buffer size"
); ::breakpoint(); } } while (0)
;
536
537 // On Linux, if nspid != -1, look in /proc/{vmid}/root/tmp for directories
538 // containing nspid, otherwise just look for vmid in /tmp.
539 if (nspid == -1) {
540 searchpid = vmid;
541 } else {
542 jio_snprintf(buffer, MAXPATHLEN4096, "/proc/%d/root%s", vmid, tmpdirname);
543 tmpdirname = buffer;
544 searchpid = nspid;
545 }
546#else
547 searchpid = vmid;
548#endif
549
550 // open the temp directory
551 DIR* tmpdirp = os::opendir(tmpdirname);
552
553 if (tmpdirp == NULL__null) {
554 // Cannot open the directory to get the user name, return.
555 return NULL__null;
556 }
557
558 // for each entry in the directory that matches the pattern hsperfdata_*,
559 // open the directory and check if the file for the given vmid (or nspid) exists.
560 // The file with the expected name and the latest creation date is used
561 // to determine the user name for the process id.
562 //
563 struct dirent* dentry;
564 errno(*__errno_location ()) = 0;
565 while ((dentry = os::readdir(tmpdirp)) != NULL__null) {
566
567 // check if the directory entry is a hsperfdata file
568 if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
569 continue;
570 }
571
572 char* usrdir_name = NEW_C_HEAP_ARRAY(char,(char*) (AllocateHeap((strlen(tmpdirname) + strlen(dentry->
d_name) + 2) * sizeof(char), mtInternal))
573 strlen(tmpdirname) + strlen(dentry->d_name) + 2,(char*) (AllocateHeap((strlen(tmpdirname) + strlen(dentry->
d_name) + 2) * sizeof(char), mtInternal))
574 mtInternal)(char*) (AllocateHeap((strlen(tmpdirname) + strlen(dentry->
d_name) + 2) * sizeof(char), mtInternal))
;
575 strcpy(usrdir_name, tmpdirname);
576 strcat(usrdir_name, "/");
577 strcat(usrdir_name, dentry->d_name);
578
579 // open the user directory
580 DIR* subdirp = open_directory_secure(usrdir_name);
581
582 if (subdirp == NULL__null) {
583 FREE_C_HEAP_ARRAY(char, usrdir_name)FreeHeap((char*)(usrdir_name));
584 continue;
585 }
586
587 // Since we don't create the backing store files in directories
588 // pointed to by symbolic links, we also don't follow them when
589 // looking for the files. We check for a symbolic link after the
590 // call to opendir in order to eliminate a small window where the
591 // symlink can be exploited.
592 //
593 if (!is_directory_secure(usrdir_name)) {
594 FREE_C_HEAP_ARRAY(char, usrdir_name)FreeHeap((char*)(usrdir_name));
595 os::closedir(subdirp);
596 continue;
597 }
598
599 struct dirent* udentry;
600 errno(*__errno_location ()) = 0;
601 while ((udentry = os::readdir(subdirp)) != NULL__null) {
602
603 if (filename_to_pid(udentry->d_name) == searchpid) {
604 struct stat statbuf;
605 int result;
606
607 char* filename = NEW_C_HEAP_ARRAY(char,(char*) (AllocateHeap((strlen(usrdir_name) + strlen(udentry->
d_name) + 2) * sizeof(char), mtInternal))
608 strlen(usrdir_name) + strlen(udentry->d_name) + 2,(char*) (AllocateHeap((strlen(usrdir_name) + strlen(udentry->
d_name) + 2) * sizeof(char), mtInternal))
609 mtInternal)(char*) (AllocateHeap((strlen(usrdir_name) + strlen(udentry->
d_name) + 2) * sizeof(char), mtInternal))
;
610
611 strcpy(filename, usrdir_name);
612 strcat(filename, "/");
613 strcat(filename, udentry->d_name);
614
615 // don't follow symbolic links for the file
616 RESTARTABLE(::lstat(filename, &statbuf), result)do { result = ::lstat(filename, &statbuf); } while(((int)
result == OS_ERR) && ((*__errno_location ()) == 4))
;
617 if (result == OS_ERR) {
618 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
619 continue;
620 }
621
622 // skip over files that are not regular files.
623 if (!S_ISREG(statbuf.st_mode)((((statbuf.st_mode)) & 0170000) == (0100000))) {
624 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
625 continue;
626 }
627
628 // compare and save filename with latest creation time
629 if (statbuf.st_size > 0 && statbuf.st_ctimest_ctim.tv_sec > oldest_ctime) {
630
631 if (statbuf.st_ctimest_ctim.tv_sec > oldest_ctime) {
632 char* user = strchr(dentry->d_name, '_') + 1;
633
634 FREE_C_HEAP_ARRAY(char, oldest_user)FreeHeap((char*)(oldest_user));
635 oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal)(char*) (AllocateHeap((strlen(user)+1) * sizeof(char), mtInternal
))
;
636
637 strcpy(oldest_user, user);
638 oldest_ctime = statbuf.st_ctimest_ctim.tv_sec;
639 }
640 }
641
642 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
643 }
644 }
645 os::closedir(subdirp);
646 FREE_C_HEAP_ARRAY(char, usrdir_name)FreeHeap((char*)(usrdir_name));
647 }
648 os::closedir(tmpdirp);
649
650 return(oldest_user);
651}
652
653// return the name of the user that owns the JVM indicated by the given vmid.
654//
655static char* get_user_name(int vmid, int *nspid, TRAPSJavaThread* __the_thread__) {
656 char *result = get_user_name_slow(vmid, *nspid, THREAD__the_thread__);
657
658#if defined(LINUX1)
659 // If we are examining a container process without PID namespaces enabled
660 // we need to use /proc/{pid}/root/tmp to find hsperfdata files.
661 if (result == NULL__null) {
662 result = get_user_name_slow(vmid, vmid, THREAD__the_thread__);
663 // Enable nspid logic going forward
664 if (result != NULL__null) *nspid = vmid;
665 }
666#endif
667 return result;
668}
669
670// return the file name of the backing store file for the named
671// shared memory region for the given user name and vmid.
672//
673// the caller is expected to free the allocated memory.
674//
675static char* get_sharedmem_filename(const char* dirname, int vmid, int nspid) {
676
677 int pid = LINUX_ONLY((nspid == -1) ? vmid : nspid)(nspid == -1) ? vmid : nspid NOT_LINUX(vmid);
678
679 // add 2 for the file separator and a null terminator.
680 size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
681
682 char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal)(char*) (AllocateHeap((nbytes) * sizeof(char), mtInternal));
683 snprintf(name, nbytes, "%s/%d", dirname, pid);
684
685 return name;
686}
687
688
689// remove file
690//
691// this method removes the file specified by the given path
692//
693static void remove_file(const char* path) {
694
695 int result;
696
697 // if the file is a directory, the following unlink will fail. since
698 // we don't expect to find directories in the user temp directory, we
699 // won't try to handle this situation. even if accidentially or
700 // maliciously planted, the directory's presence won't hurt anything.
701 //
702 RESTARTABLE(::unlink(path), result)do { result = ::unlink(path); } while(((int)result == OS_ERR)
&& ((*__errno_location ()) == 4))
;
703 if (PrintMiscellaneous && Verbose && result == OS_ERR) {
704 if (errno(*__errno_location ()) != ENOENT2) {
705 warning("Could not unlink shared memory backing"
706 " store file %s : %s\n", path, os::strerror(errno(*__errno_location ())));
707 }
708 }
709}
710
711
712// cleanup stale shared memory resources
713//
714// This method attempts to remove all stale shared memory files in
715// the named user temporary directory. It scans the named directory
716// for files matching the pattern ^$[0-9]*$. For each file found, the
717// process id is extracted from the file name and a test is run to
718// determine if the process is alive. If the process is not alive,
719// any stale file resources are removed.
720//
721static void cleanup_sharedmem_resources(const char* dirname) {
722
723 int saved_cwd_fd;
724 // open the directory and set the current working directory to it
725 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
726 if (dirp == NULL__null) {
727 // directory doesn't exist or is insecure, so there is nothing to cleanup
728 return;
729 }
730
731 // for each entry in the directory that matches the expected file
732 // name pattern, determine if the file resources are stale and if
733 // so, remove the file resources. Note, instrumented HotSpot processes
734 // for this user may start and/or terminate during this search and
735 // remove or create new files in this directory. The behavior of this
736 // loop under these conditions is dependent upon the implementation of
737 // opendir/readdir.
738 //
739 struct dirent* entry;
740 errno(*__errno_location ()) = 0;
741 while ((entry = os::readdir(dirp)) != NULL__null) {
742
743 pid_t pid = filename_to_pid(entry->d_name);
744
745 if (pid == 0) {
746
747 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
748 // attempt to remove all unexpected files, except "." and ".."
749 unlink(entry->d_name);
750 }
751
752 errno(*__errno_location ()) = 0;
753 continue;
754 }
755
756 // we now have a file name that converts to a valid integer
757 // that could represent a process id . if this process id
758 // matches the current process id or the process is not running,
759 // then remove the stale file resources.
760 //
761 // process liveness is detected by sending signal number 0 to
762 // the process id (see kill(2)). if kill determines that the
763 // process does not exist, then the file resources are removed.
764 // if kill determines that that we don't have permission to
765 // signal the process, then the file resources are assumed to
766 // be stale and are removed because the resources for such a
767 // process should be in a different user specific directory.
768 //
769 if ((pid == os::current_process_id()) ||
770 (kill(pid, 0) == OS_ERR && (errno(*__errno_location ()) == ESRCH3 || errno(*__errno_location ()) == EPERM1))) {
771 unlink(entry->d_name);
772 }
773 errno(*__errno_location ()) = 0;
774 }
775
776 // close the directory and reset the current working directory
777 close_directory_secure_cwd(dirp, saved_cwd_fd);
778}
779
780// make the user specific temporary directory. Returns true if
781// the directory exists and is secure upon return. Returns false
782// if the directory exists but is either a symlink, is otherwise
783// insecure, or if an error occurred.
784//
785static bool make_user_tmp_dir(const char* dirname) {
786
787 // create the directory with 0755 permissions. note that the directory
788 // will be owned by euid::egid, which may not be the same as uid::gid.
789 //
790 if (mkdir(dirname, S_IRWXU(0400|0200|0100)|S_IRGRP(0400 >> 3)|S_IXGRP(0100 >> 3)|S_IROTH((0400 >> 3) >> 3)|S_IXOTH((0100 >> 3) >> 3)) == OS_ERR) {
791 if (errno(*__errno_location ()) == EEXIST17) {
792 // The directory already exists and was probably created by another
793 // JVM instance. However, this could also be the result of a
794 // deliberate symlink. Verify that the existing directory is safe.
795 //
796 if (!is_directory_secure(dirname)) {
797 // directory is not secure
798 if (PrintMiscellaneous && Verbose) {
799 warning("%s directory is insecure\n", dirname);
800 }
801 return false;
802 }
803 }
804 else {
805 // we encountered some other failure while attempting
806 // to create the directory
807 //
808 if (PrintMiscellaneous && Verbose) {
809 warning("could not create directory %s: %s\n",
810 dirname, os::strerror(errno(*__errno_location ())));
811 }
812 return false;
813 }
814 }
815 return true;
816}
817
818// create the shared memory file resources
819//
820// This method creates the shared memory file with the given size
821// This method also creates the user specific temporary directory, if
822// it does not yet exist.
823//
824static int create_sharedmem_resources(const char* dirname, const char* filename, size_t size) {
825
826 // make the user temporary directory
827 if (!make_user_tmp_dir(dirname)) {
828 // could not make/find the directory or the found directory
829 // was not secure
830 return -1;
831 }
832
833 int saved_cwd_fd;
834 // open the directory and set the current working directory to it
835 DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
836 if (dirp == NULL__null) {
837 // Directory doesn't exist or is insecure, so cannot create shared
838 // memory file.
839 return -1;
840 }
841
842 // Open the filename in the current directory.
843 // Cannot use O_TRUNC here; truncation of an existing file has to happen
844 // after the is_file_secure() check below.
845 int result;
846 RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), result)do { result = os::open(filename, 02|0100|0400000, 0400|0200);
} while(((int)result == OS_ERR) && ((*__errno_location
()) == 4))
;
847 if (result == OS_ERR) {
848 if (PrintMiscellaneous && Verbose) {
849 if (errno(*__errno_location ()) == ELOOP40) {
850 warning("file %s is a symlink and is not secure\n", filename);
851 } else {
852 warning("could not create file %s: %s\n", filename, os::strerror(errno(*__errno_location ())));
853 }
854 }
855 // close the directory and reset the current working directory
856 close_directory_secure_cwd(dirp, saved_cwd_fd);
857
858 return -1;
859 }
860 // close the directory and reset the current working directory
861 close_directory_secure_cwd(dirp, saved_cwd_fd);
862
863 // save the file descriptor
864 int fd = result;
865
866 // check to see if the file is secure
867 if (!is_file_secure(fd, filename)) {
868 ::close(fd);
869 return -1;
870 }
871
872 // truncate the file to get rid of any existing data
873 RESTARTABLE(::ftruncate(fd, (off_t)0), result)do { result = ::ftruncate(fd, (off_t)0); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
874 if (result == OS_ERR) {
875 if (PrintMiscellaneous && Verbose) {
876 warning("could not truncate shared memory file: %s\n", os::strerror(errno(*__errno_location ())));
877 }
878 ::close(fd);
879 return -1;
880 }
881 // set the file size
882 RESTARTABLE(::ftruncate(fd, (off_t)size), result)do { result = ::ftruncate(fd, (off_t)size); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
883 if (result == OS_ERR) {
884 if (PrintMiscellaneous && Verbose) {
885 warning("could not set shared memory file size: %s\n", os::strerror(errno(*__errno_location ())));
886 }
887 ::close(fd);
888 return -1;
889 }
890
891 // Verify that we have enough disk space for this file.
892 // We'll get random SIGBUS crashes on memory accesses if
893 // we don't.
894 for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) {
895 int zero_int = 0;
896 result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
897 if (result == -1 ) break;
898 RESTARTABLE(::write(fd, &zero_int, 1), result)do { result = ::write(fd, &zero_int, 1); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
899 if (result != 1) {
900 if (errno(*__errno_location ()) == ENOSPC28) {
901 warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
902 }
903 break;
904 }
905 }
906
907 if (result != -1) {
908 return fd;
909 } else {
910 ::close(fd);
911 return -1;
912 }
913}
914
915// open the shared memory file for the given user and vmid. returns
916// the file descriptor for the open file or -1 if the file could not
917// be opened.
918//
919static int open_sharedmem_file(const char* filename, int oflags, TRAPSJavaThread* __the_thread__) {
920
921 // open the file
922 int result;
923 RESTARTABLE(os::open(filename, oflags, 0), result)do { result = os::open(filename, oflags, 0); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
924 if (result == OS_ERR) {
925 if (errno(*__errno_location ()) == ENOENT2) {
926 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 927, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return OS_ERR; }
927 "Process not found", OS_ERR){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 927, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return OS_ERR; }
;
928 }
929 else if (errno(*__errno_location ()) == EACCES13) {
930 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 931, vmSymbols::java_lang_IllegalArgumentException(), "Permission denied"
); return OS_ERR; }
931 "Permission denied", OS_ERR){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 931, vmSymbols::java_lang_IllegalArgumentException(), "Permission denied"
); return OS_ERR; }
;
932 }
933 else {
934 THROW_MSG_(vmSymbols::java_io_IOException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 935, vmSymbols::java_io_IOException(), os::strerror((*__errno_location
()))); return OS_ERR; }
935 os::strerror(errno), OS_ERR){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 935, vmSymbols::java_io_IOException(), os::strerror((*__errno_location
()))); return OS_ERR; }
;
936 }
937 }
938 int fd = result;
939
940 // check to see if the file is secure
941 if (!is_file_secure(fd, filename)) {
942 ::close(fd);
943 return -1;
944 }
945
946 return fd;
947}
948
949// create a named shared memory region. returns the address of the
950// memory region on success or NULL on failure. A return value of
951// NULL will ultimately disable the shared memory feature.
952//
953// The name space for shared memory objects is the file system name space.
954//
955// A monitoring application attaching to a JVM does not need to know
956// the file system name of the shared memory object. However, it may
957// be convenient for applications to discover the existence of newly
958// created and terminating JVMs by watching the file system name space
959// for files being created or removed.
960//
961static char* mmap_create_shared(size_t size) {
962
963 int result;
964 int fd;
965 char* mapAddress;
966
967 int vmid = os::current_process_id();
968
969 char* user_name = get_user_name(geteuid());
970
971 if (user_name == NULL__null)
972 return NULL__null;
973
974 char* dirname = get_user_tmp_dir(user_name, vmid, -1);
975 char* filename = get_sharedmem_filename(dirname, vmid, -1);
976
977 // get the short filename
978 char* short_filename = strrchr(filename, '/');
979 if (short_filename == NULL__null) {
980 short_filename = filename;
981 } else {
982 short_filename++;
983 }
984
985 // cleanup any stale shared memory files
986 cleanup_sharedmem_resources(dirname);
987
988 assert(((size > 0) && (size % os::vm_page_size() == 0)),do { if (!(((size > 0) && (size % os::vm_page_size
() == 0)))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 989, "assert(" "((size > 0) && (size % os::vm_page_size() == 0))"
") failed", "unexpected PerfMemory region size"); ::breakpoint
(); } } while (0)
989 "unexpected PerfMemory region size")do { if (!(((size > 0) && (size % os::vm_page_size
() == 0)))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 989, "assert(" "((size > 0) && (size % os::vm_page_size() == 0))"
") failed", "unexpected PerfMemory region size"); ::breakpoint
(); } } while (0)
;
990
991 fd = create_sharedmem_resources(dirname, short_filename, size);
992
993 FREE_C_HEAP_ARRAY(char, user_name)FreeHeap((char*)(user_name));
994 FREE_C_HEAP_ARRAY(char, dirname)FreeHeap((char*)(dirname));
995
996 if (fd == -1) {
997 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
998 return NULL__null;
999 }
1000
1001 mapAddress = (char*)::mmap((char*)0, size, PROT_READ0x1|PROT_WRITE0x2, MAP_SHARED0x01, fd, 0);
1002
1003 result = ::close(fd);
1004 assert(result != OS_ERR, "could not close file")do { if (!(result != OS_ERR)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1004, "assert(" "result != OS_ERR" ") failed", "could not close file"
); ::breakpoint(); } } while (0)
;
1005
1006 if (mapAddress == MAP_FAILED((void *) -1)) {
1007 if (PrintMiscellaneous && Verbose) {
1008 warning("mmap failed - %s\n", os::strerror(errno(*__errno_location ())));
1009 }
1010 remove_file(filename);
1011 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
1012 return NULL__null;
1013 }
1014
1015 // save the file name for use in delete_shared_memory()
1016 backing_store_file_name = filename;
1017
1018 // clear the shared memory region
1019 (void)::memset((void*) mapAddress, 0, size);
1020
1021 // it does not go through os api, the operation has to record from here
1022 MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC((MemTracker::tracking_level() == NMT_detail) ? NativeCallStack
(0) : NativeCallStack::empty_stack())
, mtInternal);
1023
1024 return mapAddress;
1025}
1026
1027// release a named shared memory region that was mmap-ed.
1028//
1029static void unmap_shared(char* addr, size_t bytes) {
1030 int res;
1031 if (MemTracker::enabled()) {
1032 // Note: Tracker contains a ThreadCritical.
1033 Tracker tkr(Tracker::release);
1034 res = ::munmap(addr, bytes);
1035 if (res == 0) {
1036 tkr.record((address)addr, bytes);
1037 }
1038 } else {
1039 res = ::munmap(addr, bytes);
1040 }
1041 if (res != 0) {
1042 log_info(os)(!(LogImpl<(LogTag::_os), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)
>::is_level(LogLevel::Info))) ? (void)0 : LogImpl<(LogTag
::_os), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel
::Info>
("os::release_memory failed (" PTR_FORMAT"0x%016" "l" "x" ", " SIZE_FORMAT"%" "l" "u" ")", p2i(addr), bytes);
1043 }
1044}
1045
1046// create the PerfData memory region in shared memory.
1047//
1048static char* create_shared_memory(size_t size) {
1049
1050 // create the shared memory region.
1051 return mmap_create_shared(size);
1052}
1053
1054// delete the shared PerfData memory region
1055//
1056static void delete_shared_memory(char* addr, size_t size) {
1057
1058 // cleanup the persistent shared memory resources. since DestroyJavaVM does
1059 // not support unloading of the JVM, unmapping of the memory resource is
1060 // not performed. The memory will be reclaimed by the OS upon termination of
1061 // the process. The backing store file is deleted from the file system.
1062
1063 assert(!PerfDisableSharedMem, "shouldn't be here")do { if (!(!PerfDisableSharedMem)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1063, "assert(" "!PerfDisableSharedMem" ") failed", "shouldn't be here"
); ::breakpoint(); } } while (0)
;
1064
1065 if (backing_store_file_name != NULL__null) {
1066 remove_file(backing_store_file_name);
1067 // Don't.. Free heap memory could deadlock os::abort() if it is called
1068 // from signal handler. OS will reclaim the heap memory.
1069 // FREE_C_HEAP_ARRAY(char, backing_store_file_name);
1070 backing_store_file_name = NULL__null;
1071 }
1072}
1073
1074// return the size of the file for the given file descriptor
1075// or 0 if it is not a valid size for a shared memory file
1076//
1077static size_t sharedmem_filesize(int fd, TRAPSJavaThread* __the_thread__) {
1078
1079 struct stat statbuf;
1080 int result;
1081
1082 RESTARTABLE(::fstat(fd, &statbuf), result)do { result = ::fstat(fd, &statbuf); } while(((int)result
== OS_ERR) && ((*__errno_location ()) == 4))
;
1083 if (result == OS_ERR) {
1084 if (PrintMiscellaneous && Verbose) {
1085 warning("fstat failed: %s\n", os::strerror(errno(*__errno_location ())));
1086 }
1087 THROW_MSG_0(vmSymbols::java_io_IOException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1088, vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"
); return 0; }
1088 "Could not determine PerfMemory size"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1088, vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"
); return 0; }
;
1089 }
1090
1091 if ((statbuf.st_size == 0) ||
1092 ((size_t)statbuf.st_size % os::vm_page_size() != 0)) {
1093 THROW_MSG_0(vmSymbols::java_io_IOException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1094, vmSymbols::java_io_IOException(), "Invalid PerfMemory size"
); return 0; }
1094 "Invalid PerfMemory size"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1094, vmSymbols::java_io_IOException(), "Invalid PerfMemory size"
); return 0; }
;
1095 }
1096
1097 return (size_t)statbuf.st_size;
1098}
1099
1100// attach to a named shared memory region.
1101//
1102static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemoryMode mode, char** addr, size_t* sizep, TRAPSJavaThread* __the_thread__) {
1103
1104 char* mapAddress;
1105 int result;
1106 int fd;
1107 size_t size = 0;
1108 const char* luser = NULL__null;
1109
1110 int mmap_prot;
1111 int file_flags;
1112
1113 ResourceMark rm;
1114
1115 // map the high level access mode to the appropriate permission
1116 // constructs for the file and the shared memory mapping.
1117 if (mode == PerfMemory::PERF_MODE_RO) {
1118 mmap_prot = PROT_READ0x1;
1119 file_flags = O_RDONLY00 | O_NOFOLLOW0400000;
1120 }
1121 else if (mode == PerfMemory::PERF_MODE_RW) {
1122#ifdef LATER
1123 mmap_prot = PROT_READ0x1 | PROT_WRITE0x2;
1124 file_flags = O_RDWR02 | O_NOFOLLOW0400000;
1125#else
1126 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1127, vmSymbols::java_lang_IllegalArgumentException(), "Unsupported access mode"
); return; }
1127 "Unsupported access mode"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1127, vmSymbols::java_lang_IllegalArgumentException(), "Unsupported access mode"
); return; }
;
1128#endif
1129 }
1130 else {
1131 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1132, vmSymbols::java_lang_IllegalArgumentException(), "Illegal access mode"
); return; }
1132 "Illegal access mode"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1132, vmSymbols::java_lang_IllegalArgumentException(), "Illegal access mode"
); return; }
;
1133 }
1134
1135 // for linux, determine if vmid is for a containerized process
1136 int nspid = LINUX_ONLY(os::Linux::get_namespace_pid(vmid))os::Linux::get_namespace_pid(vmid) NOT_LINUX(-1);
1137
1138 if (user == NULL__null || strlen(user) == 0) {
1139 luser = get_user_name(vmid, &nspid, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception
())) return ; (void)(0
);
1140 }
1141 else {
1142 luser = user;
1143 }
1144
1145 if (luser == NULL__null) {
1146 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1147, vmSymbols::java_lang_IllegalArgumentException(), "Could not map vmid to user Name"
); return; }
1147 "Could not map vmid to user Name"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1147, vmSymbols::java_lang_IllegalArgumentException(), "Could not map vmid to user Name"
); return; }
;
1148 }
1149
1150 char* dirname = get_user_tmp_dir(luser, vmid, nspid);
1151
1152 // since we don't follow symbolic links when creating the backing
1153 // store file, we don't follow them when attaching either.
1154 //
1155 if (!is_directory_secure(dirname)) {
1156 FREE_C_HEAP_ARRAY(char, dirname)FreeHeap((char*)(dirname));
1157 if (luser != user) {
1158 FREE_C_HEAP_ARRAY(char, luser)FreeHeap((char*)(luser));
1159 }
1160 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1161, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return; }
1161 "Process not found"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1161, vmSymbols::java_lang_IllegalArgumentException(), "Process not found"
); return; }
;
1162 }
1163
1164 char* filename = get_sharedmem_filename(dirname, vmid, nspid);
1165
1166 // copy heap memory to resource memory. the open_sharedmem_file
1167 // method below need to use the filename, but could throw an
1168 // exception. using a resource array prevents the leak that
1169 // would otherwise occur.
1170 char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1)(char*) resource_allocate_bytes((strlen(filename) + 1) * sizeof
(char))
;
1171 strcpy(rfilename, filename);
1172
1173 // free the c heap resources that are no longer needed
1174 if (luser != user) FREE_C_HEAP_ARRAY(char, luser)FreeHeap((char*)(luser));
1175 FREE_C_HEAP_ARRAY(char, dirname)FreeHeap((char*)(dirname));
1176 FREE_C_HEAP_ARRAY(char, filename)FreeHeap((char*)(filename));
1177
1178 // open the shared memory file for the give vmid
1179 fd = open_sharedmem_file(rfilename, file_flags, THREAD__the_thread__);
1180
1181 if (fd == OS_ERR) {
1182 return;
1183 }
1184
1185 if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) {
1186 ::close(fd);
1187 return;
1188 }
1189
1190 if (*sizep == 0) {
1191 size = sharedmem_filesize(fd, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception
())) return ; (void)(0
);
1192 } else {
1193 size = *sizep;
1194 }
1195
1196 assert(size > 0, "unexpected size <= 0")do { if (!(size > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1196, "assert(" "size > 0" ") failed", "unexpected size <= 0"
); ::breakpoint(); } } while (0)
;
1197
1198 mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED0x01, fd, 0);
1199
1200 result = ::close(fd);
1201 assert(result != OS_ERR, "could not close file")do { if (!(result != OS_ERR)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1201, "assert(" "result != OS_ERR" ") failed", "could not close file"
); ::breakpoint(); } } while (0)
;
1202
1203 if (mapAddress == MAP_FAILED((void *) -1)) {
1204 if (PrintMiscellaneous && Verbose) {
1205 warning("mmap failed: %s\n", os::strerror(errno(*__errno_location ())));
1206 }
1207 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),{ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1208, vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory"
); return; }
1208 "Could not map PerfMemory"){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1208, vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory"
); return; }
;
1209 }
1210
1211 // it does not go through os api, the operation has to record from here
1212 MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC((MemTracker::tracking_level() == NMT_detail) ? NativeCallStack
(0) : NativeCallStack::empty_stack())
, mtInternal);
1213
1214 *addr = mapAddress;
1215 *sizep = size;
1216
1217 log_debug(perf, memops)(!(LogImpl<(LogTag::_perf), (LogTag::_memops), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG)
>::is_level(LogLevel::Debug))) ? (void)0 : LogImpl<(LogTag
::_perf), (LogTag::_memops), (LogTag::__NO_TAG), (LogTag::__NO_TAG
), (LogTag::__NO_TAG), (LogTag::__NO_TAG)>::write<LogLevel
::Debug>
("mapped " SIZE_FORMAT"%" "l" "u" " bytes for vmid %d at "
1218 INTPTR_FORMAT"0x%016" "l" "x", size, vmid, p2i((void*)mapAddress));
1219}
1220
1221// create the PerfData memory region
1222//
1223// This method creates the memory region used to store performance
1224// data for the JVM. The memory may be created in standard or
1225// shared memory.
1226//
1227void PerfMemory::create_memory_region(size_t size) {
1228
1229 if (PerfDisableSharedMem) {
1230 // do not share the memory for the performance data.
1231 _start = create_standard_memory(size);
1232 }
1233 else {
1234 _start = create_shared_memory(size);
1235 if (_start == NULL__null) {
1236
1237 // creation of the shared memory region failed, attempt
1238 // to create a contiguous, non-shared memory region instead.
1239 //
1240 if (PrintMiscellaneous && Verbose) {
1241 warning("Reverting to non-shared PerfMemory region.\n");
1242 }
1243 FLAG_SET_ERGO(PerfDisableSharedMem, true)(Flag_PerfDisableSharedMem_set((true), JVMFlagOrigin::ERGONOMIC
))
;
1244 _start = create_standard_memory(size);
1245 }
1246 }
1247
1248 if (_start != NULL__null) _capacity = size;
1249
1250}
1251
1252// delete the PerfData memory region
1253//
1254// This method deletes the memory region used to store performance
1255// data for the JVM. The memory region indicated by the <address, size>
1256// tuple will be inaccessible after a call to this method.
1257//
1258void PerfMemory::delete_memory_region() {
1259
1260 assert((start() != NULL && capacity() > 0), "verify proper state")do { if (!((start() != __null && capacity() > 0)))
{ (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1260, "assert(" "(start() != __null && capacity() > 0)"
") failed", "verify proper state"); ::breakpoint(); } } while
(0)
;
1261
1262 // If user specifies PerfDataSaveFile, it will save the performance data
1263 // to the specified file name no matter whether PerfDataSaveToFile is specified
1264 // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag
1265 // -XX:+PerfDataSaveToFile.
1266 if (PerfDataSaveToFile || PerfDataSaveFile != NULL__null) {
1267 save_memory_to_file(start(), capacity());
1268 }
1269
1270 if (PerfDisableSharedMem) {
1271 delete_standard_memory(start(), capacity());
1272 }
1273 else {
1274 delete_shared_memory(start(), capacity());
1275 }
1276}
1277
1278// attach to the PerfData memory region for another JVM
1279//
1280// This method returns an <address, size> tuple that points to
1281// a memory buffer that is kept reasonably synchronized with
1282// the PerfData memory region for the indicated JVM. This
1283// buffer may be kept in synchronization via shared memory
1284// or some other mechanism that keeps the buffer updated.
1285//
1286// If the JVM chooses not to support the attachability feature,
1287// this method should throw an UnsupportedOperation exception.
1288//
1289// This implementation utilizes named shared memory to map
1290// the indicated process's PerfData memory region into this JVMs
1291// address space.
1292//
1293void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, char** addrp, size_t* sizep, TRAPSJavaThread* __the_thread__) {
1294
1295 if (vmid == 0 || vmid == os::current_process_id()) {
1296 *addrp = start();
1297 *sizep = capacity();
1298 return;
1299 }
1300
1301 mmap_attach_shared(user, vmid, mode, addrp, sizep, CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception
())) return ; (void)(0
);
1302}
1303
1304// detach from the PerfData memory region of another JVM
1305//
1306// This method detaches the PerfData memory region of another
1307// JVM, specified as an <address, size> tuple of a buffer
1308// in this process's address space. This method may perform
1309// arbitrary actions to accomplish the detachment. The memory
1310// region specified by <address, size> will be inaccessible after
1311// a call to this method.
1312//
1313// If the JVM chooses not to support the attachability feature,
1314// this method should throw an UnsupportedOperation exception.
1315//
1316// This implementation utilizes named shared memory to detach
1317// the indicated process's PerfData memory region from this
1318// process's address space.
1319//
1320void PerfMemory::detach(char* addr, size_t bytes) {
1321
1322 assert(addr != 0, "address sanity check")do { if (!(addr != 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1322, "assert(" "addr != 0" ") failed", "address sanity check"
); ::breakpoint(); } } while (0)
;
1323 assert(bytes > 0, "capacity sanity check")do { if (!(bytes > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/os/posix/perfMemory_posix.cpp"
, 1323, "assert(" "bytes > 0" ") failed", "capacity sanity check"
); ::breakpoint(); } } while (0)
;
1324
1325 if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) {
1326 // prevent accidental detachment of this process's PerfMemory region
1327 return;
1328 }
1329
1330 unmap_shared(addr, bytes);
1331}