Mercurial > hg > graal-compiler
annotate src/os/windows/vm/perfMemory_windows.cpp @ 11956:8a6d0cd7971b
Label: allocate ArrayList lazily
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Thu, 10 Oct 2013 13:03:26 +0200 |
parents | 1f4355cee9a2 |
children | 833b0f92429a |
rev | line source |
---|---|
0 | 1 /* |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
9064
diff
changeset
|
2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1353
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/vmSymbols.hpp" | |
27 #include "memory/allocation.inline.hpp" | |
28 #include "memory/resourceArea.hpp" | |
29 #include "oops/oop.inline.hpp" | |
30 #include "os_windows.inline.hpp" | |
31 #include "runtime/handles.inline.hpp" | |
32 #include "runtime/perfMemory.hpp" | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
33 #include "services/memTracker.hpp" |
1972 | 34 #include "utilities/exceptions.hpp" |
0 | 35 |
36 #include <windows.h> | |
37 #include <sys/types.h> | |
38 #include <sys/stat.h> | |
39 #include <errno.h> | |
40 #include <lmcons.h> | |
41 | |
42 typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( | |
43 IN PSECURITY_DESCRIPTOR pSecurityDescriptor, | |
44 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, | |
45 IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); | |
46 | |
47 // Standard Memory Implementation Details | |
48 | |
49 // create the PerfData memory region in standard memory. | |
50 // | |
51 static char* create_standard_memory(size_t size) { | |
52 | |
53 // allocate an aligned chuck of memory | |
54 char* mapAddress = os::reserve_memory(size); | |
55 | |
56 if (mapAddress == NULL) { | |
57 return NULL; | |
58 } | |
59 | |
60 // commit memory | |
10969
a837fa3d3f86
8013057: assert(_needs_gc || SafepointSynchronize::is_at_safepoint()) failed: only read at safepoint
dcubed
parents:
9064
diff
changeset
|
61 if (!os::commit_memory(mapAddress, size, !ExecMem)) { |
0 | 62 if (PrintMiscellaneous && Verbose) { |
63 warning("Could not commit PerfData memory\n"); | |
64 } | |
65 os::release_memory(mapAddress, size); | |
66 return NULL; | |
67 } | |
68 | |
69 return mapAddress; | |
70 } | |
71 | |
72 // delete the PerfData memory region | |
73 // | |
74 static void delete_standard_memory(char* addr, size_t size) { | |
75 | |
76 // there are no persistent external resources to cleanup for standard | |
77 // memory. since DestroyJavaVM does not support unloading of the JVM, | |
78 // cleanup of the memory resource is not performed. The memory will be | |
79 // reclaimed by the OS upon termination of the process. | |
80 // | |
81 return; | |
82 | |
83 } | |
84 | |
85 // save the specified memory region to the given file | |
86 // | |
87 static void save_memory_to_file(char* addr, size_t size) { | |
88 | |
89 const char* destfile = PerfMemory::get_perfdata_file_path(); | |
90 assert(destfile[0] != '\0', "invalid Perfdata file path"); | |
91 | |
92 int fd = ::_open(destfile, _O_BINARY|_O_CREAT|_O_WRONLY|_O_TRUNC, | |
93 _S_IREAD|_S_IWRITE); | |
94 | |
95 if (fd == OS_ERR) { | |
96 if (PrintMiscellaneous && Verbose) { | |
97 warning("Could not create Perfdata save file: %s: %s\n", | |
98 destfile, strerror(errno)); | |
99 } | |
100 } else { | |
101 for (size_t remaining = size; remaining > 0;) { | |
102 | |
103 int nbytes = ::_write(fd, addr, (unsigned int)remaining); | |
104 if (nbytes == OS_ERR) { | |
105 if (PrintMiscellaneous && Verbose) { | |
106 warning("Could not write Perfdata save file: %s: %s\n", | |
107 destfile, strerror(errno)); | |
108 } | |
109 break; | |
110 } | |
111 | |
112 remaining -= (size_t)nbytes; | |
113 addr += nbytes; | |
114 } | |
115 | |
116 int result = ::_close(fd); | |
117 if (PrintMiscellaneous && Verbose) { | |
118 if (result == OS_ERR) { | |
119 warning("Could not close %s: %s\n", destfile, strerror(errno)); | |
120 } | |
121 } | |
122 } | |
123 | |
6197 | 124 FREE_C_HEAP_ARRAY(char, destfile, mtInternal); |
0 | 125 } |
126 | |
127 // Shared Memory Implementation Details | |
128 | |
129 // Note: the win32 shared memory implementation uses two objects to represent | |
130 // the shared memory: a windows kernel based file mapping object and a backing | |
131 // store file. On windows, the name space for shared memory is a kernel | |
132 // based name space that is disjoint from other win32 name spaces. Since Java | |
133 // is unaware of this name space, a parallel file system based name space is | |
134 // maintained, which provides a common file system based shared memory name | |
135 // space across the supported platforms and one that Java apps can deal with | |
136 // through simple file apis. | |
137 // | |
138 // For performance and resource cleanup reasons, it is recommended that the | |
139 // user specific directory and the backing store file be stored in either a | |
140 // RAM based file system or a local disk based file system. Network based | |
141 // file systems are not recommended for performance reasons. In addition, | |
142 // use of SMB network based file systems may result in unsuccesful cleanup | |
143 // of the disk based resource on exit of the VM. The Windows TMP and TEMP | |
144 // environement variables, as used by the GetTempPath() Win32 API (see | |
145 // os::get_temp_directory() in os_win32.cpp), control the location of the | |
146 // user specific directory and the shared memory backing store file. | |
147 | |
148 static HANDLE sharedmem_fileMapHandle = NULL; | |
149 static HANDLE sharedmem_fileHandle = INVALID_HANDLE_VALUE; | |
150 static char* sharedmem_fileName = NULL; | |
151 | |
152 // return the user specific temporary directory name. | |
153 // | |
154 // the caller is expected to free the allocated memory. | |
155 // | |
156 static char* get_user_tmp_dir(const char* user) { | |
157 | |
158 const char* tmpdir = os::get_temp_directory(); | |
159 const char* perfdir = PERFDATA_NAME; | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
160 size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3; |
6197 | 161 char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 162 |
163 // construct the path name to user specific tmp directory | |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
164 _snprintf(dirname, nbytes, "%s\\%s_%s", tmpdir, perfdir, user); |
0 | 165 |
166 return dirname; | |
167 } | |
168 | |
169 // convert the given file name into a process id. if the file | |
170 // does not meet the file naming constraints, return 0. | |
171 // | |
172 static int filename_to_pid(const char* filename) { | |
173 | |
174 // a filename that doesn't begin with a digit is not a | |
175 // candidate for conversion. | |
176 // | |
177 if (!isdigit(*filename)) { | |
178 return 0; | |
179 } | |
180 | |
181 // check if file name can be converted to an integer without | |
182 // any leftover characters. | |
183 // | |
184 char* remainder = NULL; | |
185 errno = 0; | |
186 int pid = (int)strtol(filename, &remainder, 10); | |
187 | |
188 if (errno != 0) { | |
189 return 0; | |
190 } | |
191 | |
192 // check for left over characters. If any, then the filename is | |
193 // not a candidate for conversion. | |
194 // | |
195 if (remainder != NULL && *remainder != '\0') { | |
196 return 0; | |
197 } | |
198 | |
199 // successful conversion, return the pid | |
200 return pid; | |
201 } | |
202 | |
203 // check if the given path is considered a secure directory for | |
204 // the backing store files. Returns true if the directory exists | |
205 // and is considered a secure location. Returns false if the path | |
605 | 206 // is a symbolic link or if an error occurred. |
0 | 207 // |
208 static bool is_directory_secure(const char* path) { | |
209 | |
210 DWORD fa; | |
211 | |
212 fa = GetFileAttributes(path); | |
213 if (fa == 0xFFFFFFFF) { | |
214 DWORD lasterror = GetLastError(); | |
215 if (lasterror == ERROR_FILE_NOT_FOUND) { | |
216 return false; | |
217 } | |
218 else { | |
219 // unexpected error, declare the path insecure | |
220 if (PrintMiscellaneous && Verbose) { | |
221 warning("could not get attributes for file %s: ", | |
222 " lasterror = %d\n", path, lasterror); | |
223 } | |
224 return false; | |
225 } | |
226 } | |
227 | |
228 if (fa & FILE_ATTRIBUTE_REPARSE_POINT) { | |
229 // we don't accept any redirection for the user specific directory | |
230 // so declare the path insecure. This may be too conservative, | |
231 // as some types of reparse points might be acceptable, but it | |
232 // is probably more secure to avoid these conditions. | |
233 // | |
234 if (PrintMiscellaneous && Verbose) { | |
235 warning("%s is a reparse point\n", path); | |
236 } | |
237 return false; | |
238 } | |
239 | |
240 if (fa & FILE_ATTRIBUTE_DIRECTORY) { | |
241 // this is the expected case. Since windows supports symbolic | |
242 // links to directories only, not to files, there is no need | |
243 // to check for open write permissions on the directory. If the | |
244 // directory has open write permissions, any files deposited that | |
245 // are not expected will be removed by the cleanup code. | |
246 // | |
247 return true; | |
248 } | |
249 else { | |
250 // this is either a regular file or some other type of file, | |
251 // any of which are unexpected and therefore insecure. | |
252 // | |
253 if (PrintMiscellaneous && Verbose) { | |
254 warning("%s is not a directory, file attributes = " | |
255 INTPTR_FORMAT "\n", path, fa); | |
256 } | |
257 return false; | |
258 } | |
259 } | |
260 | |
261 // return the user name for the owner of this process | |
262 // | |
263 // the caller is expected to free the allocated memory. | |
264 // | |
265 static char* get_user_name() { | |
266 | |
267 /* get the user name. This code is adapted from code found in | |
268 * the jdk in src/windows/native/java/lang/java_props_md.c | |
269 * java_props_md.c 1.29 02/02/06. According to the original | |
270 * source, the call to GetUserName is avoided because of a resulting | |
271 * increase in footprint of 100K. | |
272 */ | |
273 char* user = getenv("USERNAME"); | |
274 char buf[UNLEN+1]; | |
275 DWORD buflen = sizeof(buf); | |
276 if (user == NULL || strlen(user) == 0) { | |
277 if (GetUserName(buf, &buflen)) { | |
278 user = buf; | |
279 } | |
280 else { | |
281 return NULL; | |
282 } | |
283 } | |
284 | |
6197 | 285 char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal); |
0 | 286 strcpy(user_name, user); |
287 | |
288 return user_name; | |
289 } | |
290 | |
291 // return the name of the user that owns the process identified by vmid. | |
292 // | |
293 // This method uses a slow directory search algorithm to find the backing | |
294 // store file for the specified vmid and returns the user name, as determined | |
295 // by the user name suffix of the hsperfdata_<username> directory name. | |
296 // | |
297 // the caller is expected to free the allocated memory. | |
298 // | |
299 static char* get_user_name_slow(int vmid) { | |
300 | |
301 // directory search | |
2236
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
302 char* latest_user = NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
303 time_t latest_ctime = 0; |
0 | 304 |
305 const char* tmpdirname = os::get_temp_directory(); | |
306 | |
307 DIR* tmpdirp = os::opendir(tmpdirname); | |
308 | |
309 if (tmpdirp == NULL) { | |
310 return NULL; | |
311 } | |
312 | |
313 // for each entry in the directory that matches the pattern hsperfdata_*, | |
314 // open the directory and check if the file for the given vmid exists. | |
315 // The file with the expected name and the latest creation date is used | |
316 // to determine the user name for the process id. | |
317 // | |
318 struct dirent* dentry; | |
6197 | 319 char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal); |
0 | 320 errno = 0; |
321 while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) { | |
322 | |
323 // check if the directory entry is a hsperfdata file | |
324 if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) { | |
325 continue; | |
326 } | |
327 | |
328 char* usrdir_name = NEW_C_HEAP_ARRAY(char, | |
6197 | 329 strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); |
0 | 330 strcpy(usrdir_name, tmpdirname); |
1353
a2ea687fdc7c
6938627: Make temporary directory use property java.io.tmpdir when specified
coleenp
parents:
605
diff
changeset
|
331 strcat(usrdir_name, "\\"); |
0 | 332 strcat(usrdir_name, dentry->d_name); |
333 | |
334 DIR* subdirp = os::opendir(usrdir_name); | |
335 | |
336 if (subdirp == NULL) { | |
6197 | 337 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
0 | 338 continue; |
339 } | |
340 | |
341 // Since we don't create the backing store files in directories | |
342 // pointed to by symbolic links, we also don't follow them when | |
343 // looking for the files. We check for a symbolic link after the | |
344 // call to opendir in order to eliminate a small window where the | |
345 // symlink can be exploited. | |
346 // | |
347 if (!is_directory_secure(usrdir_name)) { | |
6197 | 348 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); |
0 | 349 os::closedir(subdirp); |
350 continue; | |
351 } | |
352 | |
353 struct dirent* udentry; | |
6197 | 354 char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); |
0 | 355 errno = 0; |
356 while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) { | |
357 | |
358 if (filename_to_pid(udentry->d_name) == vmid) { | |
359 struct stat statbuf; | |
360 | |
361 char* filename = NEW_C_HEAP_ARRAY(char, | |
6197 | 362 strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal); |
0 | 363 |
364 strcpy(filename, usrdir_name); | |
365 strcat(filename, "\\"); | |
366 strcat(filename, udentry->d_name); | |
367 | |
368 if (::stat(filename, &statbuf) == OS_ERR) { | |
6197 | 369 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 370 continue; |
371 } | |
372 | |
373 // skip over files that are not regular files. | |
374 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { | |
6197 | 375 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 376 continue; |
377 } | |
378 | |
2236
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
379 // If we found a matching file with a newer creation time, then |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
380 // save the user name. The newer creation time indicates that |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
381 // we found a newer incarnation of the process associated with |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
382 // vmid. Due to the way that Windows recycles pids and the fact |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
383 // that we can't delete the file from the file system namespace |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
384 // until last close, it is possible for there to be more than |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
385 // one hsperfdata file with a name matching vmid (diff users). |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
386 // |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
387 // We no longer ignore hsperfdata files where (st_size == 0). |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
388 // In this function, all we're trying to do is determine the |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
389 // name of the user that owns the process associated with vmid |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
390 // so the size doesn't matter. Very rarely, we have observed |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
391 // hsperfdata files where (st_size == 0) and the st_size field |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
392 // later becomes the expected value. |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
393 // |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
394 if (statbuf.st_ctime > latest_ctime) { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
395 char* user = strchr(dentry->d_name, '_') + 1; |
0 | 396 |
6197 | 397 if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user, mtInternal); |
398 latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal); | |
0 | 399 |
2236
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
400 strcpy(latest_user, user); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
401 latest_ctime = statbuf.st_ctime; |
0 | 402 } |
403 | |
6197 | 404 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
0 | 405 } |
406 } | |
407 os::closedir(subdirp); | |
6197 | 408 FREE_C_HEAP_ARRAY(char, udbuf, mtInternal); |
409 FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); | |
0 | 410 } |
411 os::closedir(tmpdirp); | |
6197 | 412 FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal); |
0 | 413 |
2236
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
414 return(latest_user); |
0 | 415 } |
416 | |
417 // return the name of the user that owns the process identified by vmid. | |
418 // | |
419 // note: this method should only be used via the Perf native methods. | |
420 // There are various costs to this method and limiting its use to the | |
421 // Perf native methods limits the impact to monitoring applications only. | |
422 // | |
423 static char* get_user_name(int vmid) { | |
424 | |
425 // A fast implementation is not provided at this time. It's possible | |
426 // to provide a fast process id to user name mapping function using | |
427 // the win32 apis, but the default ACL for the process object only | |
428 // allows processes with the same owner SID to acquire the process | |
429 // handle (via OpenProcess(PROCESS_QUERY_INFORMATION)). It's possible | |
430 // to have the JVM change the ACL for the process object to allow arbitrary | |
431 // users to access the process handle and the process security token. | |
432 // The security ramifications need to be studied before providing this | |
433 // mechanism. | |
434 // | |
435 return get_user_name_slow(vmid); | |
436 } | |
437 | |
438 // return the name of the shared memory file mapping object for the | |
439 // named shared memory region for the given user name and vmid. | |
440 // | |
441 // The file mapping object's name is not the file name. It is a name | |
442 // in a separate name space. | |
443 // | |
444 // the caller is expected to free the allocated memory. | |
445 // | |
446 static char *get_sharedmem_objectname(const char* user, int vmid) { | |
447 | |
448 // construct file mapping object's name, add 3 for two '_' and a | |
449 // null terminator. | |
450 int nbytes = (int)strlen(PERFDATA_NAME) + (int)strlen(user) + 3; | |
451 | |
452 // the id is converted to an unsigned value here because win32 allows | |
453 // negative process ids. However, OpenFileMapping API complains | |
454 // about a name containing a '-' characters. | |
455 // | |
456 nbytes += UINT_CHARS; | |
6197 | 457 char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 458 _snprintf(name, nbytes, "%s_%s_%u", PERFDATA_NAME, user, vmid); |
459 | |
460 return name; | |
461 } | |
462 | |
463 // return the file name of the backing store file for the named | |
464 // shared memory region for the given user name and vmid. | |
465 // | |
466 // the caller is expected to free the allocated memory. | |
467 // | |
468 static char* get_sharedmem_filename(const char* dirname, int vmid) { | |
469 | |
470 // add 2 for the file separator and a null terminator. | |
471 size_t nbytes = strlen(dirname) + UINT_CHARS + 2; | |
472 | |
6197 | 473 char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 474 _snprintf(name, nbytes, "%s\\%d", dirname, vmid); |
475 | |
476 return name; | |
477 } | |
478 | |
479 // remove file | |
480 // | |
481 // this method removes the file with the given file name. | |
482 // | |
483 // Note: if the indicated file is on an SMB network file system, this | |
484 // method may be unsuccessful in removing the file. | |
485 // | |
486 static void remove_file(const char* dirname, const char* filename) { | |
487 | |
488 size_t nbytes = strlen(dirname) + strlen(filename) + 2; | |
6197 | 489 char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 490 |
491 strcpy(path, dirname); | |
492 strcat(path, "\\"); | |
493 strcat(path, filename); | |
494 | |
495 if (::unlink(path) == OS_ERR) { | |
496 if (PrintMiscellaneous && Verbose) { | |
497 if (errno != ENOENT) { | |
498 warning("Could not unlink shared memory backing" | |
499 " store file %s : %s\n", path, strerror(errno)); | |
500 } | |
501 } | |
502 } | |
503 | |
6197 | 504 FREE_C_HEAP_ARRAY(char, path, mtInternal); |
0 | 505 } |
506 | |
507 // returns true if the process represented by pid is alive, otherwise | |
508 // returns false. the validity of the result is only accurate if the | |
509 // target process is owned by the same principal that owns this process. | |
510 // this method should not be used if to test the status of an otherwise | |
511 // arbitrary process unless it is know that this process has the appropriate | |
512 // privileges to guarantee a result valid. | |
513 // | |
514 static bool is_alive(int pid) { | |
515 | |
516 HANDLE ph = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); | |
517 if (ph == NULL) { | |
518 // the process does not exist. | |
519 if (PrintMiscellaneous && Verbose) { | |
520 DWORD lastError = GetLastError(); | |
521 if (lastError != ERROR_INVALID_PARAMETER) { | |
522 warning("OpenProcess failed: %d\n", GetLastError()); | |
523 } | |
524 } | |
525 return false; | |
526 } | |
527 | |
528 DWORD exit_status; | |
529 if (!GetExitCodeProcess(ph, &exit_status)) { | |
530 if (PrintMiscellaneous && Verbose) { | |
531 warning("GetExitCodeProcess failed: %d\n", GetLastError()); | |
532 } | |
533 CloseHandle(ph); | |
534 return false; | |
535 } | |
536 | |
537 CloseHandle(ph); | |
538 return (exit_status == STILL_ACTIVE) ? true : false; | |
539 } | |
540 | |
541 // check if the file system is considered secure for the backing store files | |
542 // | |
543 static bool is_filesystem_secure(const char* path) { | |
544 | |
545 char root_path[MAX_PATH]; | |
546 char fs_type[MAX_PATH]; | |
547 | |
548 if (PerfBypassFileSystemCheck) { | |
549 if (PrintMiscellaneous && Verbose) { | |
550 warning("bypassing file system criteria checks for %s\n", path); | |
551 } | |
552 return true; | |
553 } | |
554 | |
555 char* first_colon = strchr((char *)path, ':'); | |
556 if (first_colon == NULL) { | |
557 if (PrintMiscellaneous && Verbose) { | |
558 warning("expected device specifier in path: %s\n", path); | |
559 } | |
560 return false; | |
561 } | |
562 | |
563 size_t len = (size_t)(first_colon - path); | |
564 assert(len + 2 <= MAX_PATH, "unexpected device specifier length"); | |
565 strncpy(root_path, path, len + 1); | |
566 root_path[len + 1] = '\\'; | |
567 root_path[len + 2] = '\0'; | |
568 | |
569 // check that we have something like "C:\" or "AA:\" | |
570 assert(strlen(root_path) >= 3, "device specifier too short"); | |
571 assert(strchr(root_path, ':') != NULL, "bad device specifier format"); | |
572 assert(strchr(root_path, '\\') != NULL, "bad device specifier format"); | |
573 | |
574 DWORD maxpath; | |
575 DWORD flags; | |
576 | |
577 if (!GetVolumeInformation(root_path, NULL, 0, NULL, &maxpath, | |
578 &flags, fs_type, MAX_PATH)) { | |
579 // we can't get information about the volume, so assume unsafe. | |
580 if (PrintMiscellaneous && Verbose) { | |
581 warning("could not get device information for %s: " | |
582 " path = %s: lasterror = %d\n", | |
583 root_path, path, GetLastError()); | |
584 } | |
585 return false; | |
586 } | |
587 | |
588 if ((flags & FS_PERSISTENT_ACLS) == 0) { | |
589 // file system doesn't support ACLs, declare file system unsafe | |
590 if (PrintMiscellaneous && Verbose) { | |
591 warning("file system type %s on device %s does not support" | |
592 " ACLs\n", fs_type, root_path); | |
593 } | |
594 return false; | |
595 } | |
596 | |
597 if ((flags & FS_VOL_IS_COMPRESSED) != 0) { | |
598 // file system is compressed, declare file system unsafe | |
599 if (PrintMiscellaneous && Verbose) { | |
600 warning("file system type %s on device %s is compressed\n", | |
601 fs_type, root_path); | |
602 } | |
603 return false; | |
604 } | |
605 | |
606 return true; | |
607 } | |
608 | |
609 // cleanup stale shared memory resources | |
610 // | |
611 // This method attempts to remove all stale shared memory files in | |
612 // the named user temporary directory. It scans the named directory | |
613 // for files matching the pattern ^$[0-9]*$. For each file found, the | |
614 // process id is extracted from the file name and a test is run to | |
615 // determine if the process is alive. If the process is not alive, | |
616 // any stale file resources are removed. | |
617 // | |
618 static void cleanup_sharedmem_resources(const char* dirname) { | |
619 | |
620 // open the user temp directory | |
621 DIR* dirp = os::opendir(dirname); | |
622 | |
623 if (dirp == NULL) { | |
624 // directory doesn't exist, so there is nothing to cleanup | |
625 return; | |
626 } | |
627 | |
628 if (!is_directory_secure(dirname)) { | |
629 // the directory is not secure, don't attempt any cleanup | |
630 return; | |
631 } | |
632 | |
633 // for each entry in the directory that matches the expected file | |
634 // name pattern, determine if the file resources are stale and if | |
635 // so, remove the file resources. Note, instrumented HotSpot processes | |
636 // for this user may start and/or terminate during this search and | |
637 // remove or create new files in this directory. The behavior of this | |
638 // loop under these conditions is dependent upon the implementation of | |
639 // opendir/readdir. | |
640 // | |
641 struct dirent* entry; | |
6197 | 642 char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); |
0 | 643 errno = 0; |
644 while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { | |
645 | |
646 int pid = filename_to_pid(entry->d_name); | |
647 | |
648 if (pid == 0) { | |
649 | |
650 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { | |
651 | |
652 // attempt to remove all unexpected files, except "." and ".." | |
653 remove_file(dirname, entry->d_name); | |
654 } | |
655 | |
656 errno = 0; | |
657 continue; | |
658 } | |
659 | |
660 // we now have a file name that converts to a valid integer | |
661 // that could represent a process id . if this process id | |
662 // matches the current process id or the process is not running, | |
663 // then remove the stale file resources. | |
664 // | |
665 // process liveness is detected by checking the exit status | |
666 // of the process. if the process id is valid and the exit status | |
667 // indicates that it is still running, the file file resources | |
668 // are not removed. If the process id is invalid, or if we don't | |
669 // have permissions to check the process status, or if the process | |
670 // id is valid and the process has terminated, the the file resources | |
671 // are assumed to be stale and are removed. | |
672 // | |
673 if (pid == os::current_process_id() || !is_alive(pid)) { | |
674 | |
675 // we can only remove the file resources. Any mapped views | |
676 // of the file can only be unmapped by the processes that | |
677 // opened those views and the file mapping object will not | |
678 // get removed until all views are unmapped. | |
679 // | |
680 remove_file(dirname, entry->d_name); | |
681 } | |
682 errno = 0; | |
683 } | |
684 os::closedir(dirp); | |
6197 | 685 FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); |
0 | 686 } |
687 | |
688 // create a file mapping object with the requested name, and size | |
689 // from the file represented by the given Handle object | |
690 // | |
691 static HANDLE create_file_mapping(const char* name, HANDLE fh, LPSECURITY_ATTRIBUTES fsa, size_t size) { | |
692 | |
693 DWORD lowSize = (DWORD)size; | |
694 DWORD highSize = 0; | |
695 HANDLE fmh = NULL; | |
696 | |
697 // Create a file mapping object with the given name. This function | |
698 // will grow the file to the specified size. | |
699 // | |
700 fmh = CreateFileMapping( | |
701 fh, /* HANDLE file handle for backing store */ | |
702 fsa, /* LPSECURITY_ATTRIBUTES Not inheritable */ | |
703 PAGE_READWRITE, /* DWORD protections */ | |
704 highSize, /* DWORD High word of max size */ | |
705 lowSize, /* DWORD Low word of max size */ | |
706 name); /* LPCTSTR name for object */ | |
707 | |
708 if (fmh == NULL) { | |
709 if (PrintMiscellaneous && Verbose) { | |
710 warning("CreateFileMapping failed, lasterror = %d\n", GetLastError()); | |
711 } | |
712 return NULL; | |
713 } | |
714 | |
715 if (GetLastError() == ERROR_ALREADY_EXISTS) { | |
716 | |
717 // a stale file mapping object was encountered. This object may be | |
718 // owned by this or some other user and cannot be removed until | |
719 // the other processes either exit or close their mapping objects | |
720 // and/or mapped views of this mapping object. | |
721 // | |
722 if (PrintMiscellaneous && Verbose) { | |
723 warning("file mapping already exists, lasterror = %d\n", GetLastError()); | |
724 } | |
725 | |
726 CloseHandle(fmh); | |
727 return NULL; | |
728 } | |
729 | |
730 return fmh; | |
731 } | |
732 | |
733 | |
734 // method to free the given security descriptor and the contained | |
735 // access control list. | |
736 // | |
737 static void free_security_desc(PSECURITY_DESCRIPTOR pSD) { | |
738 | |
739 BOOL success, exists, isdefault; | |
740 PACL pACL; | |
741 | |
742 if (pSD != NULL) { | |
743 | |
744 // get the access control list from the security descriptor | |
745 success = GetSecurityDescriptorDacl(pSD, &exists, &pACL, &isdefault); | |
746 | |
747 // if an ACL existed and it was not a default acl, then it must | |
748 // be an ACL we enlisted. free the resources. | |
749 // | |
750 if (success && exists && pACL != NULL && !isdefault) { | |
6197 | 751 FREE_C_HEAP_ARRAY(char, pACL, mtInternal); |
0 | 752 } |
753 | |
754 // free the security descriptor | |
6197 | 755 FREE_C_HEAP_ARRAY(char, pSD, mtInternal); |
0 | 756 } |
757 } | |
758 | |
759 // method to free up a security attributes structure and any | |
760 // contained security descriptors and ACL | |
761 // | |
762 static void free_security_attr(LPSECURITY_ATTRIBUTES lpSA) { | |
763 | |
764 if (lpSA != NULL) { | |
765 // free the contained security descriptor and the ACL | |
766 free_security_desc(lpSA->lpSecurityDescriptor); | |
767 lpSA->lpSecurityDescriptor = NULL; | |
768 | |
769 // free the security attributes structure | |
6197 | 770 FREE_C_HEAP_ARRAY(char, lpSA, mtInternal); |
0 | 771 } |
772 } | |
773 | |
774 // get the user SID for the process indicated by the process handle | |
775 // | |
776 static PSID get_user_sid(HANDLE hProcess) { | |
777 | |
778 HANDLE hAccessToken; | |
779 PTOKEN_USER token_buf = NULL; | |
780 DWORD rsize = 0; | |
781 | |
782 if (hProcess == NULL) { | |
783 return NULL; | |
784 } | |
785 | |
786 // get the process token | |
787 if (!OpenProcessToken(hProcess, TOKEN_READ, &hAccessToken)) { | |
788 if (PrintMiscellaneous && Verbose) { | |
789 warning("OpenProcessToken failure: lasterror = %d \n", GetLastError()); | |
790 } | |
791 return NULL; | |
792 } | |
793 | |
794 // determine the size of the token structured needed to retrieve | |
795 // the user token information from the access token. | |
796 // | |
797 if (!GetTokenInformation(hAccessToken, TokenUser, NULL, rsize, &rsize)) { | |
798 DWORD lasterror = GetLastError(); | |
799 if (lasterror != ERROR_INSUFFICIENT_BUFFER) { | |
800 if (PrintMiscellaneous && Verbose) { | |
801 warning("GetTokenInformation failure: lasterror = %d," | |
802 " rsize = %d\n", lasterror, rsize); | |
803 } | |
804 CloseHandle(hAccessToken); | |
805 return NULL; | |
806 } | |
807 } | |
808 | |
6197 | 809 token_buf = (PTOKEN_USER) NEW_C_HEAP_ARRAY(char, rsize, mtInternal); |
0 | 810 |
811 // get the user token information | |
812 if (!GetTokenInformation(hAccessToken, TokenUser, token_buf, rsize, &rsize)) { | |
813 if (PrintMiscellaneous && Verbose) { | |
814 warning("GetTokenInformation failure: lasterror = %d," | |
815 " rsize = %d\n", GetLastError(), rsize); | |
816 } | |
6197 | 817 FREE_C_HEAP_ARRAY(char, token_buf, mtInternal); |
0 | 818 CloseHandle(hAccessToken); |
819 return NULL; | |
820 } | |
821 | |
822 DWORD nbytes = GetLengthSid(token_buf->User.Sid); | |
6197 | 823 PSID pSID = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); |
0 | 824 |
825 if (!CopySid(nbytes, pSID, token_buf->User.Sid)) { | |
826 if (PrintMiscellaneous && Verbose) { | |
827 warning("GetTokenInformation failure: lasterror = %d," | |
828 " rsize = %d\n", GetLastError(), rsize); | |
829 } | |
6197 | 830 FREE_C_HEAP_ARRAY(char, token_buf, mtInternal); |
831 FREE_C_HEAP_ARRAY(char, pSID, mtInternal); | |
0 | 832 CloseHandle(hAccessToken); |
833 return NULL; | |
834 } | |
835 | |
836 // close the access token. | |
837 CloseHandle(hAccessToken); | |
6197 | 838 FREE_C_HEAP_ARRAY(char, token_buf, mtInternal); |
0 | 839 |
840 return pSID; | |
841 } | |
842 | |
843 // structure used to consolidate access control entry information | |
844 // | |
845 typedef struct ace_data { | |
846 PSID pSid; // SID of the ACE | |
847 DWORD mask; // mask for the ACE | |
848 } ace_data_t; | |
849 | |
850 | |
851 // method to add an allow access control entry with the access rights | |
852 // indicated in mask for the principal indicated in SID to the given | |
853 // security descriptor. Much of the DACL handling was adapted from | |
854 // the example provided here: | |
855 // http://support.microsoft.com/kb/102102/EN-US/ | |
856 // | |
857 | |
858 static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, | |
859 ace_data_t aces[], int ace_count) { | |
860 PACL newACL = NULL; | |
861 PACL oldACL = NULL; | |
862 | |
863 if (pSD == NULL) { | |
864 return false; | |
865 } | |
866 | |
867 BOOL exists, isdefault; | |
868 | |
869 // retrieve any existing access control list. | |
870 if (!GetSecurityDescriptorDacl(pSD, &exists, &oldACL, &isdefault)) { | |
871 if (PrintMiscellaneous && Verbose) { | |
872 warning("GetSecurityDescriptor failure: lasterror = %d \n", | |
873 GetLastError()); | |
874 } | |
875 return false; | |
876 } | |
877 | |
878 // get the size of the DACL | |
879 ACL_SIZE_INFORMATION aclinfo; | |
880 | |
881 // GetSecurityDescriptorDacl may return true value for exists (lpbDaclPresent) | |
882 // while oldACL is NULL for some case. | |
883 if (oldACL == NULL) { | |
884 exists = FALSE; | |
885 } | |
886 | |
887 if (exists) { | |
888 if (!GetAclInformation(oldACL, &aclinfo, | |
889 sizeof(ACL_SIZE_INFORMATION), | |
890 AclSizeInformation)) { | |
891 if (PrintMiscellaneous && Verbose) { | |
892 warning("GetAclInformation failure: lasterror = %d \n", GetLastError()); | |
893 return false; | |
894 } | |
895 } | |
896 } else { | |
897 aclinfo.AceCount = 0; // assume NULL DACL | |
898 aclinfo.AclBytesFree = 0; | |
899 aclinfo.AclBytesInUse = sizeof(ACL); | |
900 } | |
901 | |
902 // compute the size needed for the new ACL | |
903 // initial size of ACL is sum of the following: | |
904 // * size of ACL structure. | |
905 // * size of each ACE structure that ACL is to contain minus the sid | |
906 // sidStart member (DWORD) of the ACE. | |
907 // * length of the SID that each ACE is to contain. | |
908 DWORD newACLsize = aclinfo.AclBytesInUse + | |
909 (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) * ace_count; | |
910 for (int i = 0; i < ace_count; i++) { | |
1968
0b33f0736406
6837842: JNI_CreateJavaVM crashes under impersonation
poonam
parents:
1552
diff
changeset
|
911 assert(aces[i].pSid != 0, "pSid should not be 0"); |
0 | 912 newACLsize += GetLengthSid(aces[i].pSid); |
913 } | |
914 | |
915 // create the new ACL | |
6197 | 916 newACL = (PACL) NEW_C_HEAP_ARRAY(char, newACLsize, mtInternal); |
0 | 917 |
918 if (!InitializeAcl(newACL, newACLsize, ACL_REVISION)) { | |
919 if (PrintMiscellaneous && Verbose) { | |
920 warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); | |
921 } | |
6197 | 922 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 923 return false; |
924 } | |
925 | |
926 unsigned int ace_index = 0; | |
927 // copy any existing ACEs from the old ACL (if any) to the new ACL. | |
928 if (aclinfo.AceCount != 0) { | |
929 while (ace_index < aclinfo.AceCount) { | |
930 LPVOID ace; | |
931 if (!GetAce(oldACL, ace_index, &ace)) { | |
932 if (PrintMiscellaneous && Verbose) { | |
933 warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); | |
934 } | |
6197 | 935 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 936 return false; |
937 } | |
938 if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceFlags && INHERITED_ACE) { | |
939 // this is an inherited, allowed ACE; break from loop so we can | |
940 // add the new access allowed, non-inherited ACE in the correct | |
941 // position, immediately following all non-inherited ACEs. | |
942 break; | |
943 } | |
944 | |
945 // determine if the SID of this ACE matches any of the SIDs | |
946 // for which we plan to set ACEs. | |
947 int matches = 0; | |
948 for (int i = 0; i < ace_count; i++) { | |
949 if (EqualSid(aces[i].pSid, &(((ACCESS_ALLOWED_ACE *)ace)->SidStart))) { | |
950 matches++; | |
951 break; | |
952 } | |
953 } | |
954 | |
955 // if there are no SID matches, then add this existing ACE to the new ACL | |
956 if (matches == 0) { | |
957 if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace, | |
958 ((PACE_HEADER)ace)->AceSize)) { | |
959 if (PrintMiscellaneous && Verbose) { | |
960 warning("AddAce failure: lasterror = %d \n", GetLastError()); | |
961 } | |
6197 | 962 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 963 return false; |
964 } | |
965 } | |
966 ace_index++; | |
967 } | |
968 } | |
969 | |
970 // add the passed-in access control entries to the new ACL | |
971 for (int i = 0; i < ace_count; i++) { | |
972 if (!AddAccessAllowedAce(newACL, ACL_REVISION, | |
973 aces[i].mask, aces[i].pSid)) { | |
974 if (PrintMiscellaneous && Verbose) { | |
975 warning("AddAccessAllowedAce failure: lasterror = %d \n", | |
976 GetLastError()); | |
977 } | |
6197 | 978 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 979 return false; |
980 } | |
981 } | |
982 | |
983 // now copy the rest of the inherited ACEs from the old ACL | |
984 if (aclinfo.AceCount != 0) { | |
985 // picking up at ace_index, where we left off in the | |
986 // previous ace_index loop | |
987 while (ace_index < aclinfo.AceCount) { | |
988 LPVOID ace; | |
989 if (!GetAce(oldACL, ace_index, &ace)) { | |
990 if (PrintMiscellaneous && Verbose) { | |
991 warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); | |
992 } | |
6197 | 993 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 994 return false; |
995 } | |
996 if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace, | |
997 ((PACE_HEADER)ace)->AceSize)) { | |
998 if (PrintMiscellaneous && Verbose) { | |
999 warning("AddAce failure: lasterror = %d \n", GetLastError()); | |
1000 } | |
6197 | 1001 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 1002 return false; |
1003 } | |
1004 ace_index++; | |
1005 } | |
1006 } | |
1007 | |
1008 // add the new ACL to the security descriptor. | |
1009 if (!SetSecurityDescriptorDacl(pSD, TRUE, newACL, FALSE)) { | |
1010 if (PrintMiscellaneous && Verbose) { | |
1011 warning("SetSecurityDescriptorDacl failure:" | |
1012 " lasterror = %d \n", GetLastError()); | |
1013 } | |
6197 | 1014 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 1015 return false; |
1016 } | |
1017 | |
605 | 1018 // if running on windows 2000 or later, set the automatic inheritance |
0 | 1019 // control flags. |
1020 SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl; | |
1021 _SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr) | |
1022 GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")), | |
1023 "SetSecurityDescriptorControl"); | |
1024 | |
1025 if (_SetSecurityDescriptorControl != NULL) { | |
605 | 1026 // We do not want to further propagate inherited DACLs, so making them |
0 | 1027 // protected prevents that. |
1028 if (!_SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED, | |
1029 SE_DACL_PROTECTED)) { | |
1030 if (PrintMiscellaneous && Verbose) { | |
1031 warning("SetSecurityDescriptorControl failure:" | |
1032 " lasterror = %d \n", GetLastError()); | |
1033 } | |
6197 | 1034 FREE_C_HEAP_ARRAY(char, newACL, mtInternal); |
0 | 1035 return false; |
1036 } | |
1037 } | |
1038 // Note, the security descriptor maintains a reference to the newACL, not | |
1039 // a copy of it. Therefore, the newACL is not freed here. It is freed when | |
1040 // the security descriptor containing its reference is freed. | |
1041 // | |
1042 return true; | |
1043 } | |
1044 | |
1045 // method to create a security attributes structure, which contains a | |
1046 // security descriptor and an access control list comprised of 0 or more | |
1047 // access control entries. The method take an array of ace_data structures | |
1048 // that indicate the ACE to be added to the security descriptor. | |
1049 // | |
1050 // the caller must free the resources associated with the security | |
1051 // attributes structure created by this method by calling the | |
1052 // free_security_attr() method. | |
1053 // | |
1054 static LPSECURITY_ATTRIBUTES make_security_attr(ace_data_t aces[], int count) { | |
1055 | |
1056 // allocate space for a security descriptor | |
1057 PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR) | |
6197 | 1058 NEW_C_HEAP_ARRAY(char, SECURITY_DESCRIPTOR_MIN_LENGTH, mtInternal); |
0 | 1059 |
1060 // initialize the security descriptor | |
1061 if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { | |
1062 if (PrintMiscellaneous && Verbose) { | |
1063 warning("InitializeSecurityDescriptor failure: " | |
1064 "lasterror = %d \n", GetLastError()); | |
1065 } | |
1066 free_security_desc(pSD); | |
1067 return NULL; | |
1068 } | |
1069 | |
1070 // add the access control entries | |
1071 if (!add_allow_aces(pSD, aces, count)) { | |
1072 free_security_desc(pSD); | |
1073 return NULL; | |
1074 } | |
1075 | |
1076 // allocate and initialize the security attributes structure and | |
1077 // return it to the caller. | |
1078 // | |
1079 LPSECURITY_ATTRIBUTES lpSA = (LPSECURITY_ATTRIBUTES) | |
6197 | 1080 NEW_C_HEAP_ARRAY(char, sizeof(SECURITY_ATTRIBUTES), mtInternal); |
0 | 1081 lpSA->nLength = sizeof(SECURITY_ATTRIBUTES); |
1082 lpSA->lpSecurityDescriptor = pSD; | |
1083 lpSA->bInheritHandle = FALSE; | |
1084 | |
1085 return(lpSA); | |
1086 } | |
1087 | |
1088 // method to create a security attributes structure with a restrictive | |
1089 // access control list that creates a set access rights for the user/owner | |
1090 // of the securable object and a separate set access rights for everyone else. | |
1091 // also provides for full access rights for the administrator group. | |
1092 // | |
1093 // the caller must free the resources associated with the security | |
1094 // attributes structure created by this method by calling the | |
1095 // free_security_attr() method. | |
1096 // | |
1097 | |
1098 static LPSECURITY_ATTRIBUTES make_user_everybody_admin_security_attr( | |
1099 DWORD umask, DWORD emask, DWORD amask) { | |
1100 | |
1101 ace_data_t aces[3]; | |
1102 | |
1103 // initialize the user ace data | |
1104 aces[0].pSid = get_user_sid(GetCurrentProcess()); | |
1105 aces[0].mask = umask; | |
1106 | |
1968
0b33f0736406
6837842: JNI_CreateJavaVM crashes under impersonation
poonam
parents:
1552
diff
changeset
|
1107 if (aces[0].pSid == 0) |
0b33f0736406
6837842: JNI_CreateJavaVM crashes under impersonation
poonam
parents:
1552
diff
changeset
|
1108 return NULL; |
0b33f0736406
6837842: JNI_CreateJavaVM crashes under impersonation
poonam
parents:
1552
diff
changeset
|
1109 |
0 | 1110 // get the well known SID for BUILTIN\Administrators |
1111 PSID administratorsSid = NULL; | |
1112 SID_IDENTIFIER_AUTHORITY SIDAuthAdministrators = SECURITY_NT_AUTHORITY; | |
1113 | |
1114 if (!AllocateAndInitializeSid( &SIDAuthAdministrators, 2, | |
1115 SECURITY_BUILTIN_DOMAIN_RID, | |
1116 DOMAIN_ALIAS_RID_ADMINS, | |
1117 0, 0, 0, 0, 0, 0, &administratorsSid)) { | |
1118 | |
1119 if (PrintMiscellaneous && Verbose) { | |
1120 warning("AllocateAndInitializeSid failure: " | |
1121 "lasterror = %d \n", GetLastError()); | |
1122 } | |
1123 return NULL; | |
1124 } | |
1125 | |
1126 // initialize the ace data for administrator group | |
1127 aces[1].pSid = administratorsSid; | |
1128 aces[1].mask = amask; | |
1129 | |
1130 // get the well known SID for the universal Everybody | |
1131 PSID everybodySid = NULL; | |
1132 SID_IDENTIFIER_AUTHORITY SIDAuthEverybody = SECURITY_WORLD_SID_AUTHORITY; | |
1133 | |
1134 if (!AllocateAndInitializeSid( &SIDAuthEverybody, 1, SECURITY_WORLD_RID, | |
1135 0, 0, 0, 0, 0, 0, 0, &everybodySid)) { | |
1136 | |
1137 if (PrintMiscellaneous && Verbose) { | |
1138 warning("AllocateAndInitializeSid failure: " | |
1139 "lasterror = %d \n", GetLastError()); | |
1140 } | |
1141 return NULL; | |
1142 } | |
1143 | |
1144 // initialize the ace data for everybody else. | |
1145 aces[2].pSid = everybodySid; | |
1146 aces[2].mask = emask; | |
1147 | |
1148 // create a security attributes structure with access control | |
1149 // entries as initialized above. | |
1150 LPSECURITY_ATTRIBUTES lpSA = make_security_attr(aces, 3); | |
6197 | 1151 FREE_C_HEAP_ARRAY(char, aces[0].pSid, mtInternal); |
0 | 1152 FreeSid(everybodySid); |
1153 FreeSid(administratorsSid); | |
1154 return(lpSA); | |
1155 } | |
1156 | |
1157 | |
1158 // method to create the security attributes structure for restricting | |
1159 // access to the user temporary directory. | |
1160 // | |
1161 // the caller must free the resources associated with the security | |
1162 // attributes structure created by this method by calling the | |
1163 // free_security_attr() method. | |
1164 // | |
1165 static LPSECURITY_ATTRIBUTES make_tmpdir_security_attr() { | |
1166 | |
1167 // create full access rights for the user/owner of the directory | |
1168 // and read-only access rights for everybody else. This is | |
1169 // effectively equivalent to UNIX 755 permissions on a directory. | |
1170 // | |
1171 DWORD umask = STANDARD_RIGHTS_REQUIRED | FILE_ALL_ACCESS; | |
1172 DWORD emask = GENERIC_READ | FILE_LIST_DIRECTORY | FILE_TRAVERSE; | |
1173 DWORD amask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS; | |
1174 | |
1175 return make_user_everybody_admin_security_attr(umask, emask, amask); | |
1176 } | |
1177 | |
1178 // method to create the security attributes structure for restricting | |
1179 // access to the shared memory backing store file. | |
1180 // | |
1181 // the caller must free the resources associated with the security | |
1182 // attributes structure created by this method by calling the | |
1183 // free_security_attr() method. | |
1184 // | |
1185 static LPSECURITY_ATTRIBUTES make_file_security_attr() { | |
1186 | |
1187 // create extensive access rights for the user/owner of the file | |
1188 // and attribute read-only access rights for everybody else. This | |
1189 // is effectively equivalent to UNIX 600 permissions on a file. | |
1190 // | |
1191 DWORD umask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS; | |
1192 DWORD emask = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | | |
1193 FILE_READ_EA | FILE_LIST_DIRECTORY | FILE_TRAVERSE; | |
1194 DWORD amask = STANDARD_RIGHTS_ALL | FILE_ALL_ACCESS; | |
1195 | |
1196 return make_user_everybody_admin_security_attr(umask, emask, amask); | |
1197 } | |
1198 | |
1199 // method to create the security attributes structure for restricting | |
1200 // access to the name shared memory file mapping object. | |
1201 // | |
1202 // the caller must free the resources associated with the security | |
1203 // attributes structure created by this method by calling the | |
1204 // free_security_attr() method. | |
1205 // | |
1206 static LPSECURITY_ATTRIBUTES make_smo_security_attr() { | |
1207 | |
1208 // create extensive access rights for the user/owner of the shared | |
1209 // memory object and attribute read-only access rights for everybody | |
1210 // else. This is effectively equivalent to UNIX 600 permissions on | |
1211 // on the shared memory object. | |
1212 // | |
1213 DWORD umask = STANDARD_RIGHTS_REQUIRED | FILE_MAP_ALL_ACCESS; | |
1214 DWORD emask = STANDARD_RIGHTS_READ; // attributes only | |
1215 DWORD amask = STANDARD_RIGHTS_ALL | FILE_MAP_ALL_ACCESS; | |
1216 | |
1217 return make_user_everybody_admin_security_attr(umask, emask, amask); | |
1218 } | |
1219 | |
1220 // make the user specific temporary directory | |
1221 // | |
1222 static bool make_user_tmp_dir(const char* dirname) { | |
1223 | |
1224 | |
1225 LPSECURITY_ATTRIBUTES pDirSA = make_tmpdir_security_attr(); | |
1226 if (pDirSA == NULL) { | |
1227 return false; | |
1228 } | |
1229 | |
1230 | |
1231 // create the directory with the given security attributes | |
1232 if (!CreateDirectory(dirname, pDirSA)) { | |
1233 DWORD lasterror = GetLastError(); | |
1234 if (lasterror == ERROR_ALREADY_EXISTS) { | |
1235 // The directory already exists and was probably created by another | |
1236 // JVM instance. However, this could also be the result of a | |
1237 // deliberate symlink. Verify that the existing directory is safe. | |
1238 // | |
1239 if (!is_directory_secure(dirname)) { | |
1240 // directory is not secure | |
1241 if (PrintMiscellaneous && Verbose) { | |
1242 warning("%s directory is insecure\n", dirname); | |
1243 } | |
1244 return false; | |
1245 } | |
1246 // The administrator should be able to delete this directory. | |
1247 // But the directory created by previous version of JVM may not | |
1248 // have permission for administrators to delete this directory. | |
1249 // So add full permission to the administrator. Also setting new | |
1250 // DACLs might fix the corrupted the DACLs. | |
1251 SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; | |
1252 if (!SetFileSecurity(dirname, secInfo, pDirSA->lpSecurityDescriptor)) { | |
1253 if (PrintMiscellaneous && Verbose) { | |
1254 lasterror = GetLastError(); | |
1255 warning("SetFileSecurity failed for %s directory. lasterror %d \n", | |
1256 dirname, lasterror); | |
1257 } | |
1258 } | |
1259 } | |
1260 else { | |
1261 if (PrintMiscellaneous && Verbose) { | |
1262 warning("CreateDirectory failed: %d\n", GetLastError()); | |
1263 } | |
1264 return false; | |
1265 } | |
1266 } | |
1267 | |
1268 // free the security attributes structure | |
1269 free_security_attr(pDirSA); | |
1270 | |
1271 return true; | |
1272 } | |
1273 | |
1274 // create the shared memory resources | |
1275 // | |
1276 // This function creates the shared memory resources. This includes | |
1277 // the backing store file and the file mapping shared memory object. | |
1278 // | |
1279 static HANDLE create_sharedmem_resources(const char* dirname, const char* filename, const char* objectname, size_t size) { | |
1280 | |
1281 HANDLE fh = INVALID_HANDLE_VALUE; | |
1282 HANDLE fmh = NULL; | |
1283 | |
1284 | |
1285 // create the security attributes for the backing store file | |
1286 LPSECURITY_ATTRIBUTES lpFileSA = make_file_security_attr(); | |
1287 if (lpFileSA == NULL) { | |
1288 return NULL; | |
1289 } | |
1290 | |
1291 // create the security attributes for the shared memory object | |
1292 LPSECURITY_ATTRIBUTES lpSmoSA = make_smo_security_attr(); | |
1293 if (lpSmoSA == NULL) { | |
1294 free_security_attr(lpFileSA); | |
1295 return NULL; | |
1296 } | |
1297 | |
1298 // create the user temporary directory | |
1299 if (!make_user_tmp_dir(dirname)) { | |
1300 // could not make/find the directory or the found directory | |
1301 // was not secure | |
1302 return NULL; | |
1303 } | |
1304 | |
1305 // Create the file - the FILE_FLAG_DELETE_ON_CLOSE flag allows the | |
1306 // file to be deleted by the last process that closes its handle to | |
1307 // the file. This is important as the apis do not allow a terminating | |
1308 // JVM being monitored by another process to remove the file name. | |
1309 // | |
1310 // the FILE_SHARE_DELETE share mode is valid only in winnt | |
1311 // | |
1312 fh = CreateFile( | |
1313 filename, /* LPCTSTR file name */ | |
1314 | |
1315 GENERIC_READ|GENERIC_WRITE, /* DWORD desired access */ | |
1316 | |
1317 (os::win32::is_nt() ? FILE_SHARE_DELETE : 0)| | |
1318 FILE_SHARE_READ, /* DWORD share mode, future READONLY | |
1319 * open operations allowed | |
1320 */ | |
1321 lpFileSA, /* LPSECURITY security attributes */ | |
1322 CREATE_ALWAYS, /* DWORD creation disposition | |
1323 * create file, if it already | |
1324 * exists, overwrite it. | |
1325 */ | |
1326 FILE_FLAG_DELETE_ON_CLOSE, /* DWORD flags and attributes */ | |
1327 | |
1328 NULL); /* HANDLE template file access */ | |
1329 | |
1330 free_security_attr(lpFileSA); | |
1331 | |
1332 if (fh == INVALID_HANDLE_VALUE) { | |
1333 DWORD lasterror = GetLastError(); | |
1334 if (PrintMiscellaneous && Verbose) { | |
1335 warning("could not create file %s: %d\n", filename, lasterror); | |
1336 } | |
1337 return NULL; | |
1338 } | |
1339 | |
1340 // try to create the file mapping | |
1341 fmh = create_file_mapping(objectname, fh, lpSmoSA, size); | |
1342 | |
1343 free_security_attr(lpSmoSA); | |
1344 | |
1345 if (fmh == NULL) { | |
1346 // closing the file handle here will decrement the reference count | |
1347 // on the file. When all processes accessing the file close their | |
1348 // handle to it, the reference count will decrement to 0 and the | |
1349 // OS will delete the file. These semantics are requested by the | |
1350 // FILE_FLAG_DELETE_ON_CLOSE flag in CreateFile call above. | |
1351 CloseHandle(fh); | |
1352 fh = NULL; | |
1353 return NULL; | |
2236
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1354 } else { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1355 // We created the file mapping, but rarely the size of the |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1356 // backing store file is reported as zero (0) which can cause |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1357 // failures when trying to use the hsperfdata file. |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1358 struct stat statbuf; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1359 int ret_code = ::stat(filename, &statbuf); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1360 if (ret_code == OS_ERR) { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1361 if (PrintMiscellaneous && Verbose) { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1362 warning("Could not get status information from file %s: %s\n", |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1363 filename, strerror(errno)); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1364 } |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1365 CloseHandle(fmh); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1366 CloseHandle(fh); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1367 fh = NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1368 fmh = NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1369 return NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1370 } |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1371 |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1372 // We could always call FlushFileBuffers() but the Microsoft |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1373 // docs indicate that it is considered expensive so we only |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1374 // call it when we observe the size as zero (0). |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1375 if (statbuf.st_size == 0 && FlushFileBuffers(fh) != TRUE) { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1376 DWORD lasterror = GetLastError(); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1377 if (PrintMiscellaneous && Verbose) { |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1378 warning("could not flush file %s: %d\n", filename, lasterror); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1379 } |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1380 CloseHandle(fmh); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1381 CloseHandle(fh); |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1382 fh = NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1383 fmh = NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1384 return NULL; |
de14f1eee390
6954420: 2/4 jps shows "process information unavailable" sometimes
dcubed
parents:
1972
diff
changeset
|
1385 } |
0 | 1386 } |
1387 | |
1388 // the file has been successfully created and the file mapping | |
1389 // object has been created. | |
1390 sharedmem_fileHandle = fh; | |
1391 sharedmem_fileName = strdup(filename); | |
1392 | |
1393 return fmh; | |
1394 } | |
1395 | |
1396 // open the shared memory object for the given vmid. | |
1397 // | |
1398 static HANDLE open_sharedmem_object(const char* objectname, DWORD ofm_access, TRAPS) { | |
1399 | |
1400 HANDLE fmh; | |
1401 | |
1402 // open the file mapping with the requested mode | |
1403 fmh = OpenFileMapping( | |
1404 ofm_access, /* DWORD access mode */ | |
1405 FALSE, /* BOOL inherit flag - Do not allow inherit */ | |
1406 objectname); /* name for object */ | |
1407 | |
1408 if (fmh == NULL) { | |
1409 if (PrintMiscellaneous && Verbose) { | |
1410 warning("OpenFileMapping failed for shared memory object %s:" | |
1411 " lasterror = %d\n", objectname, GetLastError()); | |
1412 } | |
1413 THROW_MSG_(vmSymbols::java_lang_Exception(), | |
1414 "Could not open PerfMemory", INVALID_HANDLE_VALUE); | |
1415 } | |
1416 | |
1417 return fmh;; | |
1418 } | |
1419 | |
1420 // create a named shared memory region | |
1421 // | |
1422 // On Win32, a named shared memory object has a name space that | |
1423 // is independent of the file system name space. Shared memory object, | |
1424 // or more precisely, file mapping objects, provide no mechanism to | |
1425 // inquire the size of the memory region. There is also no api to | |
1426 // enumerate the memory regions for various processes. | |
1427 // | |
1428 // This implementation utilizes the shared memory name space in parallel | |
1429 // with the file system name space. This allows us to determine the | |
1430 // size of the shared memory region from the size of the file and it | |
1431 // allows us to provide a common, file system based name space for | |
1432 // shared memory across platforms. | |
1433 // | |
1434 static char* mapping_create_shared(size_t size) { | |
1435 | |
1436 void *mapAddress; | |
1437 int vmid = os::current_process_id(); | |
1438 | |
1439 // get the name of the user associated with this process | |
1440 char* user = get_user_name(); | |
1441 | |
1442 if (user == NULL) { | |
1443 return NULL; | |
1444 } | |
1445 | |
1446 // construct the name of the user specific temporary directory | |
1447 char* dirname = get_user_tmp_dir(user); | |
1448 | |
1449 // check that the file system is secure - i.e. it supports ACLs. | |
1450 if (!is_filesystem_secure(dirname)) { | |
1451 return NULL; | |
1452 } | |
1453 | |
1454 // create the names of the backing store files and for the | |
1455 // share memory object. | |
1456 // | |
1457 char* filename = get_sharedmem_filename(dirname, vmid); | |
1458 char* objectname = get_sharedmem_objectname(user, vmid); | |
1459 | |
1460 // cleanup any stale shared memory resources | |
1461 cleanup_sharedmem_resources(dirname); | |
1462 | |
1463 assert(((size != 0) && (size % os::vm_page_size() == 0)), | |
1464 "unexpected PerfMemry region size"); | |
1465 | |
6197 | 1466 FREE_C_HEAP_ARRAY(char, user, mtInternal); |
0 | 1467 |
1468 // create the shared memory resources | |
1469 sharedmem_fileMapHandle = | |
1470 create_sharedmem_resources(dirname, filename, objectname, size); | |
1471 | |
6197 | 1472 FREE_C_HEAP_ARRAY(char, filename, mtInternal); |
1473 FREE_C_HEAP_ARRAY(char, objectname, mtInternal); | |
1474 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | |
0 | 1475 |
1476 if (sharedmem_fileMapHandle == NULL) { | |
1477 return NULL; | |
1478 } | |
1479 | |
1480 // map the file into the address space | |
1481 mapAddress = MapViewOfFile( | |
1482 sharedmem_fileMapHandle, /* HANDLE = file mapping object */ | |
1483 FILE_MAP_ALL_ACCESS, /* DWORD access flags */ | |
1484 0, /* DWORD High word of offset */ | |
1485 0, /* DWORD Low word of offset */ | |
1486 (DWORD)size); /* DWORD Number of bytes to map */ | |
1487 | |
1488 if (mapAddress == NULL) { | |
1489 if (PrintMiscellaneous && Verbose) { | |
1490 warning("MapViewOfFile failed, lasterror = %d\n", GetLastError()); | |
1491 } | |
1492 CloseHandle(sharedmem_fileMapHandle); | |
1493 sharedmem_fileMapHandle = NULL; | |
1494 return NULL; | |
1495 } | |
1496 | |
1497 // clear the shared memory region | |
1498 (void)memset(mapAddress, '\0', size); | |
1499 | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1500 // it does not go through os api, the operation has to record from here |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
1501 MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1502 |
0 | 1503 return (char*) mapAddress; |
1504 } | |
1505 | |
1506 // this method deletes the file mapping object. | |
1507 // | |
1508 static void delete_file_mapping(char* addr, size_t size) { | |
1509 | |
1510 // cleanup the persistent shared memory resources. since DestroyJavaVM does | |
1511 // not support unloading of the JVM, unmapping of the memory resource is not | |
1512 // performed. The memory will be reclaimed by the OS upon termination of all | |
1513 // processes mapping the resource. The file mapping handle and the file | |
1514 // handle are closed here to expedite the remove of the file by the OS. The | |
1515 // file is not removed directly because it was created with | |
1516 // FILE_FLAG_DELETE_ON_CLOSE semantics and any attempt to remove it would | |
1517 // be unsuccessful. | |
1518 | |
1519 // close the fileMapHandle. the file mapping will still be retained | |
1520 // by the OS as long as any other JVM processes has an open file mapping | |
1521 // handle or a mapped view of the file. | |
1522 // | |
1523 if (sharedmem_fileMapHandle != NULL) { | |
1524 CloseHandle(sharedmem_fileMapHandle); | |
1525 sharedmem_fileMapHandle = NULL; | |
1526 } | |
1527 | |
1528 // close the file handle. This will decrement the reference count on the | |
1529 // backing store file. When the reference count decrements to 0, the OS | |
1530 // will delete the file. These semantics apply because the file was | |
1531 // created with the FILE_FLAG_DELETE_ON_CLOSE flag. | |
1532 // | |
1533 if (sharedmem_fileHandle != INVALID_HANDLE_VALUE) { | |
1534 CloseHandle(sharedmem_fileHandle); | |
1535 sharedmem_fileHandle = INVALID_HANDLE_VALUE; | |
1536 } | |
1537 } | |
1538 | |
1539 // this method determines the size of the shared memory file | |
1540 // | |
1541 static size_t sharedmem_filesize(const char* filename, TRAPS) { | |
1542 | |
1543 struct stat statbuf; | |
1544 | |
1545 // get the file size | |
1546 // | |
1547 // on win95/98/me, _stat returns a file size of 0 bytes, but on | |
1548 // winnt/2k the appropriate file size is returned. support for | |
1549 // the sharable aspects of performance counters was abandonded | |
1550 // on the non-nt win32 platforms due to this and other api | |
1551 // inconsistencies | |
1552 // | |
1553 if (::stat(filename, &statbuf) == OS_ERR) { | |
1554 if (PrintMiscellaneous && Verbose) { | |
1555 warning("stat %s failed: %s\n", filename, strerror(errno)); | |
1556 } | |
1557 THROW_MSG_0(vmSymbols::java_io_IOException(), | |
1558 "Could not determine PerfMemory size"); | |
1559 } | |
1560 | |
1561 if ((statbuf.st_size == 0) || (statbuf.st_size % os::vm_page_size() != 0)) { | |
1562 if (PrintMiscellaneous && Verbose) { | |
1563 warning("unexpected file size: size = " SIZE_FORMAT "\n", | |
1564 statbuf.st_size); | |
1565 } | |
1566 THROW_MSG_0(vmSymbols::java_lang_Exception(), | |
1567 "Invalid PerfMemory size"); | |
1568 } | |
1569 | |
1570 return statbuf.st_size; | |
1571 } | |
1572 | |
1573 // this method opens a file mapping object and maps the object | |
1574 // into the address space of the process | |
1575 // | |
1576 static void open_file_mapping(const char* user, int vmid, | |
1577 PerfMemory::PerfMemoryMode mode, | |
1578 char** addrp, size_t* sizep, TRAPS) { | |
1579 | |
1580 ResourceMark rm; | |
1581 | |
1582 void *mapAddress = 0; | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
1583 size_t size = 0; |
0 | 1584 HANDLE fmh; |
1585 DWORD ofm_access; | |
1586 DWORD mv_access; | |
1587 const char* luser = NULL; | |
1588 | |
1589 if (mode == PerfMemory::PERF_MODE_RO) { | |
1590 ofm_access = FILE_MAP_READ; | |
1591 mv_access = FILE_MAP_READ; | |
1592 } | |
1593 else if (mode == PerfMemory::PERF_MODE_RW) { | |
1594 #ifdef LATER | |
1595 ofm_access = FILE_MAP_READ | FILE_MAP_WRITE; | |
1596 mv_access = FILE_MAP_READ | FILE_MAP_WRITE; | |
1597 #else | |
1598 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
1599 "Unsupported access mode"); | |
1600 #endif | |
1601 } | |
1602 else { | |
1603 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
1604 "Illegal access mode"); | |
1605 } | |
1606 | |
1607 // if a user name wasn't specified, then find the user name for | |
1608 // the owner of the target vm. | |
1609 if (user == NULL || strlen(user) == 0) { | |
1610 luser = get_user_name(vmid); | |
1611 } | |
1612 else { | |
1613 luser = user; | |
1614 } | |
1615 | |
1616 if (luser == NULL) { | |
1617 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), | |
1618 "Could not map vmid to user name"); | |
1619 } | |
1620 | |
1621 // get the names for the resources for the target vm | |
1622 char* dirname = get_user_tmp_dir(luser); | |
1623 | |
1624 // since we don't follow symbolic links when creating the backing | |
1625 // store file, we also don't following them when attaching | |
1626 // | |
1627 if (!is_directory_secure(dirname)) { | |
6197 | 1628 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); |
0 | 1629 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), |
1630 "Process not found"); | |
1631 } | |
1632 | |
1633 char* filename = get_sharedmem_filename(dirname, vmid); | |
1634 char* objectname = get_sharedmem_objectname(luser, vmid); | |
1635 | |
1636 // copy heap memory to resource memory. the objectname and | |
1637 // filename are passed to methods that may throw exceptions. | |
1638 // using resource arrays for these names prevents the leaks | |
1639 // that would otherwise occur. | |
1640 // | |
1641 char* rfilename = NEW_RESOURCE_ARRAY(char, strlen(filename) + 1); | |
1642 char* robjectname = NEW_RESOURCE_ARRAY(char, strlen(objectname) + 1); | |
1643 strcpy(rfilename, filename); | |
1644 strcpy(robjectname, objectname); | |
1645 | |
1646 // free the c heap resources that are no longer needed | |
6197 | 1647 if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal); |
1648 FREE_C_HEAP_ARRAY(char, dirname, mtInternal); | |
1649 FREE_C_HEAP_ARRAY(char, filename, mtInternal); | |
1650 FREE_C_HEAP_ARRAY(char, objectname, mtInternal); | |
0 | 1651 |
1652 if (*sizep == 0) { | |
1653 size = sharedmem_filesize(rfilename, CHECK); | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
1654 } else { |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
1655 size = *sizep; |
0 | 1656 } |
1657 | |
9064
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
1658 assert(size > 0, "unexpected size <= 0"); |
4b7cf00ccb08
8006001: [parfait] Possible file leak in hotspot/src/os/linux/vm/perfMemory_linux.cpp
ccheung
parents:
6882
diff
changeset
|
1659 |
0 | 1660 // Open the file mapping object with the given name |
1661 fmh = open_sharedmem_object(robjectname, ofm_access, CHECK); | |
1662 | |
1663 assert(fmh != INVALID_HANDLE_VALUE, "unexpected handle value"); | |
1664 | |
1665 // map the entire file into the address space | |
1666 mapAddress = MapViewOfFile( | |
1667 fmh, /* HANDLE Handle of file mapping object */ | |
1668 mv_access, /* DWORD access flags */ | |
1669 0, /* DWORD High word of offset */ | |
1670 0, /* DWORD Low word of offset */ | |
1671 size); /* DWORD Number of bytes to map */ | |
1672 | |
1673 if (mapAddress == NULL) { | |
1674 if (PrintMiscellaneous && Verbose) { | |
1675 warning("MapViewOfFile failed, lasterror = %d\n", GetLastError()); | |
1676 } | |
1677 CloseHandle(fmh); | |
1678 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), | |
1679 "Could not map PerfMemory"); | |
1680 } | |
1681 | |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1682 // it does not go through os api, the operation has to record from here |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
1683 MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1684 |
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1685 |
0 | 1686 *addrp = (char*)mapAddress; |
1687 *sizep = size; | |
1688 | |
1689 // File mapping object can be closed at this time without | |
1690 // invalidating the mapped view of the file | |
1691 CloseHandle(fmh); | |
1692 | |
1693 if (PerfTraceMemOps) { | |
1694 tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " | |
1695 INTPTR_FORMAT "\n", size, vmid, mapAddress); | |
1696 } | |
1697 } | |
1698 | |
1699 // this method unmaps the the mapped view of the the | |
1700 // file mapping object. | |
1701 // | |
1702 static void remove_file_mapping(char* addr) { | |
1703 | |
1704 // the file mapping object was closed in open_file_mapping() | |
1705 // after the file map view was created. We only need to | |
1706 // unmap the file view here. | |
1707 UnmapViewOfFile(addr); | |
1708 } | |
1709 | |
1710 // create the PerfData memory region in shared memory. | |
1711 static char* create_shared_memory(size_t size) { | |
1712 | |
1713 return mapping_create_shared(size); | |
1714 } | |
1715 | |
1716 // release a named, shared memory region | |
1717 // | |
1718 void delete_shared_memory(char* addr, size_t size) { | |
1719 | |
1720 delete_file_mapping(addr, size); | |
1721 } | |
1722 | |
1723 | |
1724 | |
1725 | |
1726 // create the PerfData memory region | |
1727 // | |
1728 // This method creates the memory region used to store performance | |
1729 // data for the JVM. The memory may be created in standard or | |
1730 // shared memory. | |
1731 // | |
1732 void PerfMemory::create_memory_region(size_t size) { | |
1733 | |
1734 if (PerfDisableSharedMem || !os::win32::is_nt()) { | |
1735 // do not share the memory for the performance data. | |
1736 PerfDisableSharedMem = true; | |
1737 _start = create_standard_memory(size); | |
1738 } | |
1739 else { | |
1740 _start = create_shared_memory(size); | |
1741 if (_start == NULL) { | |
1742 | |
1743 // creation of the shared memory region failed, attempt | |
1744 // to create a contiguous, non-shared memory region instead. | |
1745 // | |
1746 if (PrintMiscellaneous && Verbose) { | |
1747 warning("Reverting to non-shared PerfMemory region.\n"); | |
1748 } | |
1749 PerfDisableSharedMem = true; | |
1750 _start = create_standard_memory(size); | |
1751 } | |
1752 } | |
1753 | |
1754 if (_start != NULL) _capacity = size; | |
1755 | |
1756 } | |
1757 | |
1758 // delete the PerfData memory region | |
1759 // | |
1760 // This method deletes the memory region used to store performance | |
1761 // data for the JVM. The memory region indicated by the <address, size> | |
1762 // tuple will be inaccessible after a call to this method. | |
1763 // | |
1764 void PerfMemory::delete_memory_region() { | |
1765 | |
1766 assert((start() != NULL && capacity() > 0), "verify proper state"); | |
1767 | |
1768 // If user specifies PerfDataSaveFile, it will save the performance data | |
1769 // to the specified file name no matter whether PerfDataSaveToFile is specified | |
1770 // or not. In other word, -XX:PerfDataSaveFile=.. overrides flag | |
1771 // -XX:+PerfDataSaveToFile. | |
1772 if (PerfDataSaveToFile || PerfDataSaveFile != NULL) { | |
1773 save_memory_to_file(start(), capacity()); | |
1774 } | |
1775 | |
1776 if (PerfDisableSharedMem) { | |
1777 delete_standard_memory(start(), capacity()); | |
1778 } | |
1779 else { | |
1780 delete_shared_memory(start(), capacity()); | |
1781 } | |
1782 } | |
1783 | |
1784 // attach to the PerfData memory region for another JVM | |
1785 // | |
1786 // This method returns an <address, size> tuple that points to | |
1787 // a memory buffer that is kept reasonably synchronized with | |
1788 // the PerfData memory region for the indicated JVM. This | |
1789 // buffer may be kept in synchronization via shared memory | |
1790 // or some other mechanism that keeps the buffer updated. | |
1791 // | |
1792 // If the JVM chooses not to support the attachability feature, | |
1793 // this method should throw an UnsupportedOperation exception. | |
1794 // | |
1795 // This implementation utilizes named shared memory to map | |
1796 // the indicated process's PerfData memory region into this JVMs | |
1797 // address space. | |
1798 // | |
1799 void PerfMemory::attach(const char* user, int vmid, PerfMemoryMode mode, | |
1800 char** addrp, size_t* sizep, TRAPS) { | |
1801 | |
1802 if (vmid == 0 || vmid == os::current_process_id()) { | |
1803 *addrp = start(); | |
1804 *sizep = capacity(); | |
1805 return; | |
1806 } | |
1807 | |
1808 open_file_mapping(user, vmid, mode, addrp, sizep, CHECK); | |
1809 } | |
1810 | |
1811 // detach from the PerfData memory region of another JVM | |
1812 // | |
1813 // This method detaches the PerfData memory region of another | |
1814 // JVM, specified as an <address, size> tuple of a buffer | |
1815 // in this process's address space. This method may perform | |
1816 // arbitrary actions to accomplish the detachment. The memory | |
1817 // region specified by <address, size> will be inaccessible after | |
1818 // a call to this method. | |
1819 // | |
1820 // If the JVM chooses not to support the attachability feature, | |
1821 // this method should throw an UnsupportedOperation exception. | |
1822 // | |
1823 // This implementation utilizes named shared memory to detach | |
1824 // the indicated process's PerfData memory region from this | |
1825 // process's address space. | |
1826 // | |
1827 void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { | |
1828 | |
1829 assert(addr != 0, "address sanity check"); | |
1830 assert(bytes > 0, "capacity sanity check"); | |
1831 | |
1832 if (PerfMemory::contains(addr) || PerfMemory::contains(addr + bytes - 1)) { | |
1833 // prevent accidental detachment of this process's PerfMemory region | |
1834 return; | |
1835 } | |
1836 | |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
1837 MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); |
0 | 1838 remove_file_mapping(addr); |
6882
716c64bda5ba
7199092: NMT: NMT needs to deal overlapped virtual memory ranges
zgu
parents:
6842
diff
changeset
|
1839 // it does not go through os api, the operation has to record from here |
10986
1f4355cee9a2
8013651: NMT: reserve/release sequence id's in incorrect order due to race
zgu
parents:
10969
diff
changeset
|
1840 tkr.record((address)addr, bytes); |
0 | 1841 } |
1842 | |
1843 char* PerfMemory::backing_store_filename() { | |
1844 return sharedmem_fileName; | |
1845 } |