1 /*
2  * Copyright (c) 1997, 2015, 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 <assert.h>
27 #include "java_lang_ProcessImpl.h"
28 
29 #include "jni.h"
30 #include "jvm.h"
31 #include "jni_util.h"
32 #include "io_util.h"
33 #include "io_util_md.h"
34 #include <windows.h>
35 #include <io.h>
36 
37 /* We try to make sure that we can read and write 4095 bytes (the
38  * fixed limit on Linux) to the pipe on all operating systems without
39  * deadlock.  Windows 2000 inexplicably appears to need an extra 24
40  * bytes of slop to avoid deadlock.
41  */
42 #define PIPE_SIZE (4096+24)
43 
44 /* We have THREE locales in action:
45  * 1. Thread default locale - dictates UNICODE-to-8bit conversion
46  * 2. System locale that defines the message localization
47  * 3. The file name locale
48  * Each locale could be an extended locale, that means that text cannot be
49  * mapped to 8bit sequence without multibyte encoding.
50  * VM is ready for that, if text is UTF-8.
51  * Here we make the work right from the beginning.
52  */
os_error_message(int errnum,WCHAR * utf16_OSErrorMsg,size_t maxMsgLength)53 size_t os_error_message(int errnum, WCHAR* utf16_OSErrorMsg, size_t maxMsgLength) {
54     size_t n = (size_t)FormatMessageW(
55             FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
56             NULL,
57             (DWORD)errnum,
58             0,
59             utf16_OSErrorMsg,
60             (DWORD)maxMsgLength,
61             NULL);
62     if (n > 3) {
63         // Drop final '.', CR, LF
64         if (utf16_OSErrorMsg[n - 1] == L'\n') --n;
65         if (utf16_OSErrorMsg[n - 1] == L'\r') --n;
66         if (utf16_OSErrorMsg[n - 1] == L'.') --n;
67         utf16_OSErrorMsg[n] = L'\0';
68     }
69     return n;
70 }
71 
72 #define MESSAGE_LENGTH (256 + 100)
73 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
74 
75 static void
win32Error(JNIEnv * env,const WCHAR * functionName)76 win32Error(JNIEnv *env, const WCHAR *functionName)
77 {
78     WCHAR utf16_OSErrorMsg[MESSAGE_LENGTH - 100];
79     WCHAR utf16_javaMessage[MESSAGE_LENGTH];
80     /*Good suggestion about 2-bytes-per-symbol in localized error reports*/
81     char  utf8_javaMessage[MESSAGE_LENGTH*2];
82     const int errnum = (int)GetLastError();
83     size_t n = os_error_message(errnum, utf16_OSErrorMsg, ARRAY_SIZE(utf16_OSErrorMsg));
84     n = (n > 0)
85         ? swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s error=%d, %s", functionName, errnum, utf16_OSErrorMsg)
86         : swprintf(utf16_javaMessage, MESSAGE_LENGTH, L"%s failed, error=%d", functionName, errnum);
87 
88     if (n > 0) /*terminate '\0' is not a part of conversion procedure*/
89         n = WideCharToMultiByte(
90             CP_UTF8,
91             0,
92             utf16_javaMessage,
93             (int)n, /*by creation n <= MESSAGE_LENGTH*/
94             utf8_javaMessage,
95             MESSAGE_LENGTH*2,
96             NULL,
97             NULL);
98 
99     /*no way to die*/
100     {
101         const char *errorMessage = "Secondary error while OS message extraction";
102         if (n > 0) {
103             utf8_javaMessage[min(MESSAGE_LENGTH*2 - 1, n)] = '\0';
104             errorMessage = utf8_javaMessage;
105         }
106         JNU_ThrowIOException(env, errorMessage);
107     }
108 }
109 
110 static void
closeSafely(HANDLE handle)111 closeSafely(HANDLE handle)
112 {
113     if (handle != INVALID_HANDLE_VALUE)
114         CloseHandle(handle);
115 }
116 
hasInheritFlag(HANDLE handle)117 static BOOL hasInheritFlag(HANDLE handle)
118 {
119     DWORD mask;
120     if (GetHandleInformation(handle, &mask)) {
121         return mask & HANDLE_FLAG_INHERIT;
122     }
123     return FALSE;
124 }
125 
126 #define HANDLE_STORAGE_SIZE 6
127 #define OFFSET_READ  0
128 #define OFFSET_WRITE 1
129 //long signed version of INVALID_HANDLE_VALUE
130 #define JAVA_INVALID_HANDLE_VALUE ((jlong) -1)
131 #define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ)
132 
133 /* Pipe holder structure */
134 typedef struct _STDHOLDER {
135     HANDLE  pipe[2];
136     int     offset;
137 } STDHOLDER;
138 
139 /* Responsible for correct initialization of the [pHolder] structure
140    (that is used for handles recycling) if needs,
141    and appropriate setup of IOE handle [phStd] for child process based
142    on created pipe or Java handle. */
initHolder(JNIEnv * env,jlong * pjhandles,STDHOLDER * pHolder,HANDLE * phStd)143 static BOOL initHolder(
144     JNIEnv *env,
145     jlong *pjhandles,   /* IN OUT - the handle form Java,
146                                     that can be a file, console or undefined */
147     STDHOLDER *pHolder, /* OUT    - initialized structure that holds pipe
148                                     handles */
149     HANDLE *phStd       /* OUT    - initialized handle for child process */
150 ) {
151     /* Here we test the value from Java against invalid
152        handle value. We are not using INVALID_HANDLE_VALUE macro
153        due to double signed/unsigned and 32/64bit ambiguity.
154        Otherwise it will be easy to get the wrong
155        value   0x00000000FFFFFFFF
156        instead 0xFFFFFFFFFFFFFFFF. */
157     if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) {
158         /* Java file or console redirection */
159         *phStd = (HANDLE) *pjhandles;
160         /* Here we set the related Java stream (Process.getXXXXStream())
161            to [ProcessBuilder.NullXXXXStream.INSTANCE] value.
162            The initial Java handle [*pjhandles] will be closed in
163            ANY case. It is not a handle leak. */
164         *pjhandles = JAVA_INVALID_HANDLE_VALUE;
165     } else {
166         /* Creation of parent-child pipe */
167         if (!CreatePipe(
168             &pHolder->pipe[OFFSET_READ],
169             &pHolder->pipe[OFFSET_WRITE],
170             NULL, /* we would like to inherit
171                      default process access,
172                      instead of 'Everybody' access */
173             PIPE_SIZE))
174         {
175             win32Error(env, L"CreatePipe");
176             return FALSE;
177         } else {
178             /* [thisProcessEnd] has no the inherit flag because
179                the [lpPipeAttributes] param of [CreatePipe]
180                had the NULL value. */
181             HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)];
182             *phStd = pHolder->pipe[pHolder->offset];
183             *pjhandles = (jlong) thisProcessEnd;
184         }
185     }
186     /* Pipe handle will be closed in the [releaseHolder] call,
187        file handle will be closed in Java.
188        The long-live handle need to restore the inherit flag,
189        we do it later in the [prepareIOEHandleState] call. */
190     SetHandleInformation(
191         *phStd,
192         HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
193     return TRUE;
194 }
195 
196 /* Smart recycling of pipe handles in [pHolder]. For the failed
197    create process attempts, both ends of pipe need to be released.
198    The [complete] has the [TRUE] value in the failed attempt. */
releaseHolder(BOOL complete,STDHOLDER * pHolder)199 static void releaseHolder(BOOL complete, STDHOLDER *pHolder) {
200     closeSafely(pHolder->pipe[pHolder->offset]);
201     if (complete) {
202         /* Error occur, close this process pipe end */
203         closeSafely(pHolder->pipe[OPPOSITE_END(pHolder->offset)]);
204     }
205 }
206 
207 /* Stores and drops the inherit flag of handles that should not
208    be shared with the child process by default, but can hold the
209    inherit flag due to MS process birth specific. */
prepareIOEHandleState(HANDLE * stdIOE,BOOL * inherit)210 static void prepareIOEHandleState(
211     HANDLE *stdIOE,
212     BOOL *inherit)
213 {
214     int i;
215     for (i = 0; i < HANDLE_STORAGE_SIZE; ++i) {
216         HANDLE hstd = stdIOE[i];
217         if (INVALID_HANDLE_VALUE != hstd && hasInheritFlag(hstd)) {
218             /* FALSE by default */
219             inherit[i] = TRUE;
220             /* Java does not need implicit inheritance for IOE handles,
221                so we drop inherit flag that probably was installed by
222                previous CreateProcess call that launched current process.
223                We will return the handle state back after CreateProcess call.
224                By clearing inherit flag we prevent "greedy grandchild" birth.
225                The explicit inheritance for child process IOE handles is
226                implemented in the [initHolder] call. */
227             SetHandleInformation(hstd, HANDLE_FLAG_INHERIT, 0);
228         }
229     }
230 }
231 
232 /* Restores the inheritance flag of handles from stored values. */
restoreIOEHandleState(const HANDLE * stdIOE,const BOOL * inherit)233 static void restoreIOEHandleState(
234     const HANDLE *stdIOE,
235     const BOOL *inherit)
236 {
237     /* The set of current process standard IOE handles and
238        the set of child process IOE handles can intersect.
239        To restore the inherit flag right, we use backward
240        array iteration. */
241     int i;
242     for (i = HANDLE_STORAGE_SIZE - 1; i >= 0; --i)
243         if (INVALID_HANDLE_VALUE != stdIOE[i]) {
244            /* Restore inherit flag for any case.
245               The handle can be changed by explicit inheritance.*/
246             SetHandleInformation(stdIOE[i],
247                 HANDLE_FLAG_INHERIT,
248                 inherit[i] ? HANDLE_FLAG_INHERIT : 0);
249         }
250 }
251 
252 /*
253  * Class:     java_lang_ProcessImpl
254  * Method:    getProcessId0
255  * Signature: (J)I
256  */
Java_java_lang_ProcessImpl_getProcessId0(JNIEnv * env,jclass clazz,jlong handle)257 JNIEXPORT jint JNICALL Java_java_lang_ProcessImpl_getProcessId0
258   (JNIEnv *env, jclass clazz, jlong handle) {
259     DWORD pid = GetProcessId((HANDLE) jlong_to_ptr(handle));
260     return (jint)pid;
261 }
262 
263 /* Please, read about the MS inheritance problem
264    http://support.microsoft.com/kb/315939
265    and critical section/synchronized block solution. */
processCreate(JNIEnv * env,const jchar * pcmd,const jchar * penvBlock,const jchar * pdir,jlong * handles,jboolean redirectErrorStream)266 static jlong processCreate(
267     JNIEnv *env,
268     const jchar *pcmd,
269     const jchar *penvBlock,
270     const jchar *pdir,
271     jlong *handles,
272     jboolean redirectErrorStream)
273 {
274     jlong ret = 0L;
275     STARTUPINFOW si = {sizeof(si)};
276 
277     /* Handles for which the inheritance flag must be restored. */
278     HANDLE stdIOE[HANDLE_STORAGE_SIZE] = {
279         /* Current process standard IOE handles: JDK-7147084 */
280         INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
281         /* Child process IOE handles: JDK-6921885 */
282         (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]};
283     BOOL inherit[HANDLE_STORAGE_SIZE] = {
284         FALSE, FALSE, FALSE,
285         FALSE, FALSE, FALSE};
286 
287     /* These three should not be closed by CloseHandle! */
288     stdIOE[0] = GetStdHandle(STD_INPUT_HANDLE);
289     stdIOE[1] = GetStdHandle(STD_OUTPUT_HANDLE);
290     stdIOE[2] = GetStdHandle(STD_ERROR_HANDLE);
291 
292     prepareIOEHandleState(stdIOE, inherit);
293     {
294         /* Input */
295         STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ};
296         if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) {
297 
298             /* Output */
299             STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
300             if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) {
301 
302                 /* Error */
303                 STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
304                 BOOL success;
305                 if (redirectErrorStream) {
306                     si.hStdError = si.hStdOutput;
307                     /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE]
308                        value. That is in accordance with Java Doc for the redirection case.
309                        The Java file for the [ handles[2] ] will be closed in ANY case. It is not
310                        a handle leak. */
311                     handles[2] = JAVA_INVALID_HANDLE_VALUE;
312                     success = TRUE;
313                 } else {
314                     success = initHolder(env, &handles[2], &holderErr, &si.hStdError);
315                 }
316 
317                 if (success) {
318                     PROCESS_INFORMATION pi;
319                     DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
320 
321                     /* If the standard I/O is inherited, CREATE_NO_WINDOW must not be used. */
322                     if (GetConsoleWindow() != NULL &&
323                         (si.hStdInput  == stdIOE[0] ||
324                          si.hStdOutput == stdIOE[1] ||
325                          si.hStdError  == (redirectErrorStream ? stdIOE[1] : stdIOE[2])))
326                     {
327                         processFlag &= ~CREATE_NO_WINDOW;
328                     }
329 
330                     si.dwFlags = STARTF_USESTDHANDLES;
331                     if (!CreateProcessW(
332                         NULL,             /* executable name */
333                         (LPWSTR)pcmd,     /* command line */
334                         NULL,             /* process security attribute */
335                         NULL,             /* thread security attribute */
336                         TRUE,             /* inherits system handles */
337                         processFlag,      /* selected based on exe type */
338                         (LPVOID)penvBlock,/* environment block */
339                         (LPCWSTR)pdir,    /* change to the new current directory */
340                         &si,              /* (in)  startup information */
341                         &pi))             /* (out) process information */
342                     {
343                         win32Error(env, L"CreateProcess");
344                     } else {
345                         closeSafely(pi.hThread);
346                         ret = (jlong)pi.hProcess;
347                     }
348                 }
349                 releaseHolder(ret == 0, &holderErr);
350                 releaseHolder(ret == 0, &holderOut);
351             }
352             releaseHolder(ret == 0, &holderIn);
353         }
354     }
355     restoreIOEHandleState(stdIOE, inherit);
356 
357     return ret;
358 }
359 
360 JNIEXPORT jlong JNICALL
Java_java_lang_ProcessImpl_create(JNIEnv * env,jclass ignored,jstring cmd,jstring envBlock,jstring dir,jlongArray stdHandles,jboolean redirectErrorStream)361 Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
362                                   jstring cmd,
363                                   jstring envBlock,
364                                   jstring dir,
365                                   jlongArray stdHandles,
366                                   jboolean redirectErrorStream)
367 {
368     jlong ret = 0;
369     if (cmd != NULL && stdHandles != NULL) {
370         const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL);
371         if (pcmd != NULL) {
372             const jchar *penvBlock = (envBlock != NULL)
373                 ? (*env)->GetStringChars(env, envBlock, NULL)
374                 : NULL;
375             if (!(*env)->ExceptionCheck(env)) {
376                 const jchar *pdir = (dir != NULL)
377                     ? (*env)->GetStringChars(env, dir, NULL)
378                     : NULL;
379                 if (!(*env)->ExceptionCheck(env)) {
380                     jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
381                     if (handles != NULL) {
382                         ret = processCreate(
383                             env,
384                             pcmd,
385                             penvBlock,
386                             pdir,
387                             handles,
388                             redirectErrorStream);
389                         (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);
390                     }
391                     if (pdir != NULL)
392                         (*env)->ReleaseStringChars(env, dir, pdir);
393                 }
394                 if (penvBlock != NULL)
395                     (*env)->ReleaseStringChars(env, envBlock, penvBlock);
396             }
397             (*env)->ReleaseStringChars(env, cmd, pcmd);
398         }
399     }
400     return ret;
401 }
402 
403 JNIEXPORT jint JNICALL
Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv * env,jclass ignored,jlong handle)404 Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
405 {
406     DWORD exit_code;
407     if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0)
408         win32Error(env, L"GetExitCodeProcess");
409     return exit_code;
410 }
411 
412 JNIEXPORT jint JNICALL
Java_java_lang_ProcessImpl_getStillActive(JNIEnv * env,jclass ignored)413 Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored)
414 {
415     return STILL_ACTIVE;
416 }
417 
418 JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv * env,jclass ignored,jlong handle)419 Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle)
420 {
421     HANDLE events[2];
422     events[0] = (HANDLE) handle;
423     events[1] = JVM_GetThreadInterruptEvent();
424 
425     if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
426                                FALSE,    /* Wait for ANY event */
427                                INFINITE)  /* Wait forever */
428         == WAIT_FAILED)
429         win32Error(env, L"WaitForMultipleObjects");
430 }
431 
432 JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv * env,jclass ignored,jlong handle,jlong timeoutMillis)433 Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
434                                                        jclass ignored,
435                                                        jlong handle,
436                                                        jlong timeoutMillis)
437 {
438     HANDLE events[2];
439     DWORD dwTimeout = (DWORD)timeoutMillis;
440     DWORD result;
441     events[0] = (HANDLE) handle;
442     events[1] = JVM_GetThreadInterruptEvent();
443     result = WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
444                                     FALSE,    /* Wait for ANY event */
445                                     dwTimeout);  /* Wait for dwTimeout */
446 
447     if (result == WAIT_FAILED)
448         win32Error(env, L"WaitForMultipleObjects");
449 }
450 
451 JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_terminateProcess(JNIEnv * env,jclass ignored,jlong handle)452 Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle)
453 {
454     TerminateProcess((HANDLE) handle, 1);
455 }
456 
457 JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv * env,jclass ignored,jlong handle)458 Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle)
459 {
460     DWORD dwExitStatus;
461     GetExitCodeProcess((HANDLE) handle, &dwExitStatus);
462     return dwExitStatus == STILL_ACTIVE;
463 }
464 
465 JNIEXPORT jboolean JNICALL
Java_java_lang_ProcessImpl_closeHandle(JNIEnv * env,jclass ignored,jlong handle)466 Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle)
467 {
468     return (jboolean) CloseHandle((HANDLE) handle);
469 }
470 
471 JNIEXPORT jlong JNICALL
Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv * env,jclass ignored,jstring path)472 Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path)
473 {
474     const DWORD access = (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA);
475     const DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
476     const DWORD disposition = OPEN_ALWAYS;
477     const DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
478     HANDLE h;
479     WCHAR *pathbuf = pathToNTPath(env, path, JNI_FALSE);
480     if (pathbuf == NULL) {
481         /* Exception already pending */
482         return -1;
483     }
484     h = CreateFileW(
485         pathbuf,            /* Wide char path name */
486         access,             /* Read and/or write permission */
487         sharing,            /* File sharing flags */
488         NULL,               /* Security attributes */
489         disposition,        /* creation disposition */
490         flagsAndAttributes, /* flags and attributes */
491         NULL);
492     free(pathbuf);
493     if (h == INVALID_HANDLE_VALUE) {
494         JNU_ThrowIOExceptionWithLastError(env, "CreateFileW");
495     }
496     return ptr_to_jlong(h);
497 }
498