Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c
32288 views
1
/*
2
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
#include <sys/types.h>
26
#include <sys/stat.h>
27
#include <door.h>
28
#include <stdlib.h>
29
#include <unistd.h>
30
#include <signal.h>
31
#include <string.h>
32
#include <fcntl.h>
33
#include <errno.h>
34
#include <limits.h>
35
36
#include "jni.h"
37
#include "jni_util.h"
38
#include "jvm.h"
39
40
#include "sun_tools_attach_SolarisVirtualMachine.h"
41
42
#define RESTARTABLE(_cmd, _result) do { \
43
do { \
44
_result = _cmd; \
45
} while((_result == -1) && (errno == EINTR)); \
46
} while(0)
47
48
/*
49
* Class: sun_tools_attach_SolarisVirtualMachine
50
* Method: open
51
* Signature: (Ljava/lang/String;)I
52
*/
53
JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_open
54
(JNIEnv *env, jclass cls, jstring path)
55
{
56
jboolean isCopy;
57
const char* p = GetStringPlatformChars(env, path, &isCopy);
58
if (p == NULL) {
59
return 0;
60
} else {
61
int fd;
62
int err = 0;
63
64
fd = open(p, O_RDWR);
65
if (fd == -1) {
66
err = errno;
67
}
68
69
if (isCopy) {
70
JNU_ReleaseStringPlatformChars(env, path, p);
71
}
72
73
if (fd == -1) {
74
if (err == ENOENT) {
75
JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
76
} else {
77
char* msg = strdup(strerror(err));
78
JNU_ThrowIOException(env, msg);
79
if (msg != NULL) {
80
free(msg);
81
}
82
}
83
}
84
return fd;
85
}
86
}
87
88
/*
89
* Class: sun_tools_attach_SolarisVirtualMachine
90
* Method: checkPermissions
91
* Signature: (Ljava/lang/String;)V
92
*/
93
JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_checkPermissions
94
(JNIEnv *env, jclass cls, jstring path)
95
{
96
jboolean isCopy;
97
const char* p = GetStringPlatformChars(env, path, &isCopy);
98
if (p != NULL) {
99
struct stat64 sb;
100
uid_t uid, gid;
101
int res;
102
103
/*
104
* Check that the path is owned by the effective uid/gid of this
105
* process. Also check that group/other access is not allowed.
106
*/
107
uid = geteuid();
108
gid = getegid();
109
110
res = stat64(p, &sb);
111
if (res != 0) {
112
/* save errno */
113
res = errno;
114
}
115
116
if (res == 0) {
117
char msg[100];
118
jboolean isError = JNI_FALSE;
119
if (sb.st_uid != uid) {
120
jio_snprintf(msg, sizeof(msg)-1,
121
"file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
122
isError = JNI_TRUE;
123
} else if (sb.st_gid != gid) {
124
jio_snprintf(msg, sizeof(msg)-1,
125
"file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
126
isError = JNI_TRUE;
127
} else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
128
jio_snprintf(msg, sizeof(msg)-1,
129
"file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
130
isError = JNI_TRUE;
131
}
132
if (isError) {
133
char buf[256];
134
jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
135
JNU_ThrowIOException(env, buf);
136
}
137
} else {
138
char* msg = strdup(strerror(res));
139
JNU_ThrowIOException(env, msg);
140
if (msg != NULL) {
141
free(msg);
142
}
143
}
144
145
if (isCopy) {
146
JNU_ReleaseStringPlatformChars(env, path, p);
147
}
148
}
149
}
150
151
/*
152
* Class: sun_tools_attach_SolarisVirtualMachine
153
* Method: close
154
* Signature: (I)V
155
*/
156
JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_close
157
(JNIEnv *env, jclass cls, jint fd)
158
{
159
int ret;
160
RESTARTABLE(close(fd), ret);
161
}
162
163
/*
164
* Class: sun_tools_attach_SolarisVirtualMachine
165
* Method: read
166
* Signature: (I[BI)I
167
*/
168
JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_read
169
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
170
{
171
unsigned char buf[128];
172
size_t len = sizeof(buf);
173
ssize_t n;
174
175
size_t remaining = (size_t)(baLen - off);
176
if (len > remaining) {
177
len = remaining;
178
}
179
180
RESTARTABLE(read(fd, buf, len), n);
181
if (n == -1) {
182
JNU_ThrowIOExceptionWithLastError(env, "read");
183
} else {
184
if (n == 0) {
185
n = -1; // EOF
186
} else {
187
(*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
188
}
189
}
190
return n;
191
}
192
193
/*
194
* Class: sun_tools_attach_SolarisVirtualMachine
195
* Method: sigquit
196
* Signature: (I)V
197
*/
198
JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_sigquit
199
(JNIEnv *env, jclass cls, jint pid)
200
{
201
if (kill((pid_t)pid, SIGQUIT) == -1) {
202
JNU_ThrowIOExceptionWithLastError(env, "kill");
203
}
204
}
205
206
/*
207
* A simple table to translate some known errors into reasonable
208
* error messages
209
*/
210
static struct {
211
jint err;
212
const char* msg;
213
} const error_messages[] = {
214
{ 100, "Bad request" },
215
{ 101, "Protocol mismatch" },
216
{ 102, "Resource failure" },
217
{ 103, "Internal error" },
218
{ 104, "Permission denied" },
219
};
220
221
/*
222
* Lookup the given error code and return the appropriate
223
* message. If not found return NULL.
224
*/
225
static const char* translate_error(jint err) {
226
int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
227
int i;
228
229
for (i=0; i<table_size; i++) {
230
if (err == error_messages[i].err) {
231
return error_messages[i].msg;
232
}
233
}
234
return NULL;
235
}
236
237
/*
238
* Current protocol version
239
*/
240
static const char* PROTOCOL_VERSION = "1";
241
242
/*
243
* Class: sun_tools_attach_SolarisVirtualMachine
244
* Method: enqueue
245
* Signature: (JILjava/lang/String;[Ljava/lang/Object;)V
246
*/
247
JNIEXPORT jint JNICALL Java_sun_tools_attach_SolarisVirtualMachine_enqueue
248
(JNIEnv *env, jclass cls, jint fd, jstring cmd, jobjectArray args)
249
{
250
jint arg_count, i;
251
size_t size;
252
jboolean isCopy;
253
door_arg_t door_args;
254
char res_buffer[128];
255
jint result = -1;
256
int rc;
257
const char* cstr;
258
char* buf;
259
260
/*
261
* First we get the command string and create the start of the
262
* argument string to send to the target VM:
263
* <ver>\0<cmd>\0
264
*/
265
cstr = JNU_GetStringPlatformChars(env, cmd, &isCopy);
266
if (cstr == NULL) {
267
return -1; /* pending exception */
268
}
269
size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
270
buf = (char*)malloc(size);
271
if (buf != NULL) {
272
char* pos = buf;
273
strcpy(buf, PROTOCOL_VERSION);
274
pos += strlen(PROTOCOL_VERSION)+1;
275
strcpy(pos, cstr);
276
}
277
if (isCopy) {
278
JNU_ReleaseStringPlatformChars(env, cmd, cstr);
279
}
280
if (buf == NULL) {
281
JNU_ThrowOutOfMemoryError(env, "malloc failed");
282
return -1;
283
}
284
285
/*
286
* Next we iterate over the arguments and extend the buffer
287
* to include them.
288
*/
289
arg_count = (*env)->GetArrayLength(env, args);
290
291
for (i=0; i<arg_count; i++) {
292
jobject obj = (*env)->GetObjectArrayElement(env, args, i);
293
if (obj != NULL) {
294
cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
295
if (cstr != NULL) {
296
size_t len = strlen(cstr);
297
char* newbuf = (char*)realloc(buf, size+len+1);
298
if (newbuf != NULL) {
299
buf = newbuf;
300
strcpy(buf+size, cstr);
301
size += len+1;
302
}
303
if (isCopy) {
304
JNU_ReleaseStringPlatformChars(env, obj, cstr);
305
}
306
if (newbuf == NULL) {
307
free(buf);
308
JNU_ThrowOutOfMemoryError(env, "realloc failed");
309
return -1;
310
}
311
}
312
}
313
if ((*env)->ExceptionOccurred(env)) {
314
free(buf);
315
return -1;
316
}
317
}
318
319
/*
320
* The arguments to the door function are in 'buf' so we now
321
* do the door call
322
*/
323
door_args.data_ptr = buf;
324
door_args.data_size = size;
325
door_args.desc_ptr = NULL;
326
door_args.desc_num = 0;
327
door_args.rbuf = (char*)&res_buffer;
328
door_args.rsize = sizeof(res_buffer);
329
330
RESTARTABLE(door_call(fd, &door_args), rc);
331
332
/*
333
* door_call failed
334
*/
335
if (rc == -1) {
336
JNU_ThrowIOExceptionWithLastError(env, "door_call");
337
} else {
338
/*
339
* door_call succeeded but the call didn't return the the expected jint.
340
*/
341
if (door_args.data_size < sizeof(jint)) {
342
JNU_ThrowIOException(env, "Enqueue error - reason unknown as result is truncated!");
343
} else {
344
jint* res = (jint*)(door_args.data_ptr);
345
if (*res != JNI_OK) {
346
const char* msg = translate_error(*res);
347
char buf[255];
348
if (msg == NULL) {
349
sprintf(buf, "Unable to enqueue command to target VM: %d", *res);
350
} else {
351
sprintf(buf, "Unable to enqueue command to target VM: %s", msg);
352
}
353
JNU_ThrowIOException(env, buf);
354
} else {
355
/*
356
* The door call should return a file descriptor to one end of
357
* a socket pair
358
*/
359
if ((door_args.desc_ptr != NULL) &&
360
(door_args.desc_num == 1) &&
361
(door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
362
result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
363
} else {
364
JNU_ThrowIOException(env, "Reply from enqueue missing descriptor!");
365
}
366
}
367
}
368
}
369
370
free(buf);
371
return result;
372
}
373
374