Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c
40941 views
1
/*
2
* Copyright (c) 2005, 2021, 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
26
#include "jni_util.h"
27
28
#include <sys/socket.h>
29
#include <sys/stat.h>
30
#include <sys/syslimits.h>
31
#include <sys/types.h>
32
#include <sys/un.h>
33
#include <errno.h>
34
#include <fcntl.h>
35
#include <signal.h>
36
#include <stdio.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
41
#include "sun_tools_attach_VirtualMachineImpl.h"
42
43
#define RESTARTABLE(_cmd, _result) do { \
44
do { \
45
_result = _cmd; \
46
} while((_result == -1) && (errno == EINTR)); \
47
} while(0)
48
49
#define ROOT_UID 0
50
51
/*
52
* Declare library specific JNI_Onload entry if static build
53
*/
54
DEF_STATIC_JNI_OnLoad
55
56
/*
57
* Class: sun_tools_attach_VirtualMachineImpl
58
* Method: socket
59
* Signature: ()I
60
*/
61
JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_socket
62
(JNIEnv *env, jclass cls)
63
{
64
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
65
if (fd == -1) {
66
JNU_ThrowIOExceptionWithLastError(env, "socket");
67
}
68
return (jint)fd;
69
}
70
71
/*
72
* Class: sun_tools_attach_VirtualMachineImpl
73
* Method: connect
74
* Signature: (ILjava/lang/String;)I
75
*/
76
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_connect
77
(JNIEnv *env, jclass cls, jint fd, jstring path)
78
{
79
jboolean isCopy;
80
const char* p = GetStringPlatformChars(env, path, &isCopy);
81
if (p != NULL) {
82
struct sockaddr_un addr;
83
int err = 0;
84
85
memset(&addr, 0, sizeof(addr));
86
addr.sun_family = AF_UNIX;
87
/* strncpy is safe because addr.sun_path was zero-initialized before. */
88
strncpy(addr.sun_path, p, sizeof(addr.sun_path) - 1);
89
90
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
91
err = errno;
92
}
93
94
if (isCopy) {
95
JNU_ReleaseStringPlatformChars(env, path, p);
96
}
97
98
/*
99
* If the connect failed then we throw the appropriate exception
100
* here (can't throw it before releasing the string as can't call
101
* JNI with pending exception)
102
*/
103
if (err != 0) {
104
if (err == ENOENT) {
105
JNU_ThrowByName(env, "java/io/FileNotFoundException", NULL);
106
} else {
107
char* msg = strdup(strerror(err));
108
JNU_ThrowIOException(env, msg);
109
if (msg != NULL) {
110
free(msg);
111
}
112
}
113
}
114
}
115
}
116
117
/*
118
* Class: sun_tools_attach_VirtualMachineImpl
119
* Method: sendQuitTo
120
* Signature: (I)V
121
*/
122
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo
123
(JNIEnv *env, jclass cls, jint pid)
124
{
125
if (kill((pid_t)pid, SIGQUIT)) {
126
JNU_ThrowIOExceptionWithLastError(env, "kill");
127
}
128
}
129
130
/*
131
* Class: sun_tools_attach_VirtualMachineImpl
132
* Method: checkPermissions
133
* Signature: (Ljava/lang/String;)V
134
*/
135
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
136
(JNIEnv *env, jclass cls, jstring path)
137
{
138
jboolean isCopy;
139
const char* p = GetStringPlatformChars(env, path, &isCopy);
140
if (p != NULL) {
141
struct stat sb;
142
uid_t uid, gid;
143
int res;
144
145
memset(&sb, 0, sizeof(struct stat));
146
147
/*
148
* Check that the path is owned by the effective uid/gid of this
149
* process. Also check that group/other access is not allowed.
150
*/
151
uid = geteuid();
152
gid = getegid();
153
154
res = stat(p, &sb);
155
if (res != 0) {
156
/* save errno */
157
res = errno;
158
}
159
160
if (res == 0) {
161
char msg[100];
162
jboolean isError = JNI_FALSE;
163
if (sb.st_uid != uid && uid != ROOT_UID) {
164
snprintf(msg, sizeof(msg),
165
"file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
166
isError = JNI_TRUE;
167
} else if (sb.st_gid != gid && uid != ROOT_UID) {
168
snprintf(msg, sizeof(msg),
169
"file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
170
isError = JNI_TRUE;
171
} else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
172
snprintf(msg, sizeof(msg),
173
"file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
174
isError = JNI_TRUE;
175
}
176
if (isError) {
177
char buf[256];
178
snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
179
JNU_ThrowIOException(env, buf);
180
}
181
} else {
182
char* msg = strdup(strerror(res));
183
JNU_ThrowIOException(env, msg);
184
if (msg != NULL) {
185
free(msg);
186
}
187
}
188
189
if (isCopy) {
190
JNU_ReleaseStringPlatformChars(env, path, p);
191
}
192
}
193
}
194
195
/*
196
* Class: sun_tools_attach_VirtualMachineImpl
197
* Method: close
198
* Signature: (I)V
199
*/
200
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_close
201
(JNIEnv *env, jclass cls, jint fd)
202
{
203
int res;
204
shutdown(fd, SHUT_RDWR);
205
RESTARTABLE(close(fd), res);
206
}
207
208
/*
209
* Class: sun_tools_attach_VirtualMachineImpl
210
* Method: read
211
* Signature: (I[BI)I
212
*/
213
JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_read
214
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint baLen)
215
{
216
unsigned char buf[128];
217
size_t len = sizeof(buf);
218
ssize_t n;
219
220
size_t remaining = (size_t)(baLen - off);
221
if (len > remaining) {
222
len = remaining;
223
}
224
225
RESTARTABLE(read(fd, buf, len), n);
226
if (n == -1) {
227
JNU_ThrowIOExceptionWithLastError(env, "read");
228
} else {
229
if (n == 0) {
230
n = -1; // EOF
231
} else {
232
(*env)->SetByteArrayRegion(env, ba, off, (jint)n, (jbyte *)(buf));
233
}
234
}
235
return n;
236
}
237
238
/*
239
* Class: sun_tools_attach_VirtualMachineImpl
240
* Method: write
241
* Signature: (I[B)V
242
*/
243
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_write
244
(JNIEnv *env, jclass cls, jint fd, jbyteArray ba, jint off, jint bufLen)
245
{
246
size_t remaining = bufLen;
247
do {
248
unsigned char buf[128];
249
size_t len = sizeof(buf);
250
int n;
251
252
if (len > remaining) {
253
len = remaining;
254
}
255
(*env)->GetByteArrayRegion(env, ba, off, len, (jbyte *)buf);
256
257
RESTARTABLE(write(fd, buf, len), n);
258
if (n > 0) {
259
off += n;
260
remaining -= n;
261
} else {
262
JNU_ThrowIOExceptionWithLastError(env, "write");
263
return;
264
}
265
266
} while (remaining > 0);
267
}
268
269
/*
270
* Class: sun_tools_attach_BSDVirtualMachine
271
* Method: createAttachFile
272
* Signature: (Ljava.lang.String;)V
273
*/
274
JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_createAttachFile0(JNIEnv *env, jclass cls, jstring path)
275
{
276
const char* _path;
277
jboolean isCopy;
278
int fd, rc;
279
280
_path = GetStringPlatformChars(env, path, &isCopy);
281
if (_path == NULL) {
282
JNU_ThrowIOException(env, "Must specify a path");
283
return;
284
}
285
286
RESTARTABLE(open(_path, O_CREAT | O_EXCL, S_IWUSR | S_IRUSR), fd);
287
if (fd == -1) {
288
/* release p here before we throw an I/O exception */
289
if (isCopy) {
290
JNU_ReleaseStringPlatformChars(env, path, _path);
291
}
292
JNU_ThrowIOExceptionWithLastError(env, "open");
293
return;
294
}
295
296
RESTARTABLE(chown(_path, geteuid(), getegid()), rc);
297
298
RESTARTABLE(close(fd), rc);
299
300
/* release p here */
301
if (isCopy) {
302
JNU_ReleaseStringPlatformChars(env, path, _path);
303
}
304
}
305
306
/*
307
* Class: sun_tools_attach_BSDVirtualMachine
308
* Method: getTempDir
309
* Signature: (V)Ljava.lang.String;
310
*/
311
JNIEXPORT jstring JNICALL Java_sun_tools_attach_VirtualMachineImpl_getTempDir(JNIEnv *env, jclass cls)
312
{
313
// This must be hard coded because it's the system's temporary
314
// directory not the java application's temp directory, ala java.io.tmpdir.
315
316
#ifdef __APPLE__
317
// macosx has a secure per-user temporary directory.
318
// Don't cache the result as this is only called once.
319
char path[PATH_MAX];
320
int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, path, PATH_MAX);
321
if (pathSize == 0 || pathSize > PATH_MAX) {
322
strlcpy(path, "/tmp", sizeof(path));
323
}
324
return JNU_NewStringPlatform(env, path);
325
#else /* __APPLE__ */
326
return (*env)->NewStringUTF(env, "/tmp");
327
#endif /* __APPLE__ */
328
}
329
330