Bug Summary

File:jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
Warning:line 462, column 9
This function call is prohibited after a successful vfork

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ProcessImpl_md.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D ARCHPROPNAME="amd64" -I /home/daniel/Projects/java/jdk/src/java.base/linux/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.base -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libfdlibm -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused -Wno-unused-result -Wno-unused-function -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
1/*
2 * Copyright (c) 1995, 2020, 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#undef _LARGEFILE64_SOURCE1
27#define _LARGEFILE64_SOURCE1 1
28
29#include "jni.h"
30#include "jvm.h"
31#include "jvm_md.h"
32#include "jni_util.h"
33#include "io_util.h"
34
35/*
36 * Platform-specific support for java.lang.Process
37 */
38#include <assert.h>
39#include <stddef.h>
40#include <stdlib.h>
41#include <sys/types.h>
42#include <ctype.h>
43#include <sys/wait.h>
44#include <signal.h>
45#include <string.h>
46
47#include <spawn.h>
48
49#include "childproc.h"
50
51/*
52 *
53 * When starting a child on Unix, we need to do three things:
54 * - fork off
55 * - in the child process, do some pre-exec work: duping/closing file
56 * descriptors to set up stdio-redirection, setting environment variables,
57 * changing paths...
58 * - then exec(2) the target binary
59 *
60 * There are three ways to fork off:
61 *
62 * A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on
63 * all Unices when invoked from a VM with a high memory footprint. On Unices
64 * with strict no-overcommit policy this problem is most visible.
65 *
66 * This is because forking the VM will first create a child process with
67 * theoretically the same memory footprint as the parent - even if you plan
68 * to follow up with exec'ing a tiny binary. In reality techniques like
69 * copy-on-write etc mitigate the problem somewhat but we still run the risk
70 * of hitting system limits.
71 *
72 * For a Linux centric description of this problem, see the documentation on
73 * /proc/sys/vm/overcommit_memory in Linux proc(5).
74 *
75 * B) vfork(2): Portable and fast but very unsafe. It bypasses the memory
76 * problems related to fork(2) by starting the child in the memory image of
77 * the parent. Things that can go wrong include:
78 * - Programming errors in the child process before the exec(2) call may
79 * trash memory in the parent process, most commonly the stack of the
80 * thread invoking vfork.
81 * - Signals received by the child before the exec(2) call may be at best
82 * misdirected to the parent, at worst immediately kill child and parent.
83 *
84 * This is mitigated by very strict rules about what one is allowed to do in
85 * the child process between vfork(2) and exec(2), which is basically nothing.
86 * However, we always broke this rule by doing the pre-exec work between
87 * vfork(2) and exec(2).
88 *
89 * Also note that vfork(2) has been deprecated by the OpenGroup, presumably
90 * because of its many dangers.
91 *
92 * C) clone(2): This is a Linux specific call which gives the caller fine
93 * grained control about how exactly the process fork is executed. It is
94 * powerful, but Linux-specific.
95 *
96 * Aside from these three possibilities there is a forth option: posix_spawn(3).
97 * Where fork/vfork/clone all fork off the process and leave pre-exec work and
98 * calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like
99 * functionality in one package, similar to CreateProcess() on Windows.
100 *
101 * It is not a system call in itself, but usually a wrapper implemented within
102 * the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it
103 * has advantages over calling the naked (fork|vfork|clone) functions depends
104 * on how posix_spawn(3) is implemented.
105 *
106 * Note that when using posix_spawn(3), we exec twice: first a tiny binary called
107 * the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a
108 * second time, this time the target binary (similar to the "exec-twice-technique"
109 * described in http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-September/055333.html).
110 *
111 * This is a JDK-specific implementation detail which just happens to be
112 * implemented for jdk.lang.Process.launchMechanism=POSIX_SPAWN.
113 *
114 * --- Linux-specific ---
115 *
116 * How does glibc implement posix_spawn?
117 * (see: sysdeps/posix/spawni.c for glibc < 2.24,
118 * sysdeps/unix/sysv/linux/spawni.c for glibc >= 2.24):
119 *
120 * 1) Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2).
121 * This would be bad for the JDK since we would risk the known memory issues with
122 * fork(2). But since this only affects glibc variants which have long been
123 * phased out by modern distributions, this is irrelevant.
124 *
125 * 2) Between glibc 2.4 and glibc 2.23, posix_spawn uses either fork(2) or
126 * vfork(2) depending on how exactly the user called posix_spawn(3):
127 *
128 * <quote>
129 * The child process is created using vfork(2) instead of fork(2) when
130 * either of the following is true:
131 *
132 * * the spawn-flags element of the attributes object pointed to by
133 * attrp contains the GNU-specific flag POSIX_SPAWN_USEVFORK; or
134 *
135 * * file_actions is NULL and the spawn-flags element of the attributes
136 * object pointed to by attrp does not contain
137 * POSIX_SPAWN_SETSIGMASK, POSIX_SPAWN_SETSIGDEF,
138 * POSIX_SPAWN_SETSCHEDPARAM, POSIX_SPAWN_SETSCHEDULER,
139 * POSIX_SPAWN_SETPGROUP, or POSIX_SPAWN_RESETIDS.
140 * </quote>
141 *
142 * Due to the way the JDK calls posix_spawn(3), it would therefore call vfork(2).
143 * So we would avoid the fork(2) memory problems. However, there still remains the
144 * risk associated with vfork(2). But it is smaller than were we to call vfork(2)
145 * directly since we use the jspawnhelper, moving all pre-exec work off to after
146 * the first exec, thereby reducing the vulnerable time window.
147 *
148 * 3) Since glibc >= 2.24, glibc uses clone+exec:
149 *
150 * new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
151 * CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
152 *
153 * This is even better than (2):
154 *
155 * CLONE_VM means we run in the parent's memory image, as with (2)
156 * CLONE_VFORK means parent waits until we exec, as with (2)
157 *
158 * However, error possibilities are further reduced since:
159 * - posix_spawn(3) passes a separate stack for the child to run on, eliminating
160 * the danger of trashing the forking thread's stack in the parent process.
161 * - posix_spawn(3) takes care to temporarily block all incoming signals to the
162 * child process until the first exec(2) has been called,
163 *
164 * TL;DR
165 * Calling posix_spawn(3) for glibc
166 * (2) < 2.24 is not perfect but still better than using plain vfork(2), since
167 * the chance of an error happening is greatly reduced
168 * (3) >= 2.24 is the best option - portable, fast and as safe as possible.
169 *
170 * ---
171 *
172 * How does muslc implement posix_spawn?
173 *
174 * They always did use the clone (.. CLONE_VM | CLONE_VFORK ...)
175 * technique. So we are safe to use posix_spawn() here regardless of muslc
176 * version.
177 *
178 * </Linux-specific>
179 *
180 *
181 * Based on the above analysis, we are currently defaulting to posix_spawn()
182 * on all Unices including Linux.
183 */
184
185static void
186setSIGCHLDHandler(JNIEnv *env)
187{
188 /* There is a subtle difference between having the signal handler
189 * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
190 * termination information for child processes if the signal
191 * handler is SIG_IGN. It must be SIG_DFL.
192 *
193 * We used to set the SIGCHLD handler only on Linux, but it's
194 * safest to set it unconditionally.
195 *
196 * Consider what happens if java's parent process sets the SIGCHLD
197 * handler to SIG_IGN. Normally signal handlers are inherited by
198 * children, but SIGCHLD is a controversial case. Solaris appears
199 * to always reset it to SIG_DFL, but this behavior may be
200 * non-standard-compliant, and we shouldn't rely on it.
201 *
202 * References:
203 * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
204 * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
205 */
206 struct sigaction sa;
207 sa.sa_handler__sigaction_handler.sa_handler = SIG_DFL((__sighandler_t) 0);
208 sigemptyset(&sa.sa_mask);
209 sa.sa_flags = SA_NOCLDSTOP1 | SA_RESTART0x10000000;
210 if (sigaction(SIGCHLD17, &sa, NULL((void*)0)) < 0)
211 JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
212}
213
214static void*
215xmalloc(JNIEnv *env, size_t size)
216{
217 void *p = malloc(size);
218 if (p == NULL((void*)0))
219 JNU_ThrowOutOfMemoryError(env, NULL((void*)0));
220 return p;
221}
222
223#define NEW(type, n)((type *) xmalloc(env, (n) * sizeof(type))) ((type *) xmalloc(env, (n) * sizeof(type)))
224
225/**
226 * If PATH is not defined, the OS provides some default value.
227 * Unfortunately, there's no portable way to get this value.
228 * Fortunately, it's only needed if the child has PATH while we do not.
229 */
230static const char*
231defaultPath(void)
232{
233 return ":/bin:/usr/bin";
234}
235
236static const char*
237effectivePath(void)
238{
239 const char *s = getenv("PATH");
240 return (s != NULL((void*)0)) ? s : defaultPath();
241}
242
243static int
244countOccurrences(const char *s, char c)
245{
246 int count;
247 for (count = 0; *s != '\0'; s++)
248 count += (*s == c);
249 return count;
250}
251
252static const char * const *
253effectivePathv(JNIEnv *env)
254{
255 char *p;
256 int i;
257 const char *path = effectivePath();
258 int count = countOccurrences(path, ':') + 1;
259 size_t pathvsize = sizeof(const char *) * (count+1);
260 size_t pathsize = strlen(path) + 1;
261 const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
262
263 if (pathv == NULL((void*)0))
264 return NULL((void*)0);
265 p = (char *) pathv + pathvsize;
266 memcpy(p, path, pathsize);
267 /* split PATH by replacing ':' with NULs; empty components => "." */
268 for (i = 0; i < count; i++) {
269 char *q = p + strcspn(p, ":");
270 pathv[i] = (p == q) ? "." : p;
271 *q = '\0';
272 p = q + 1;
273 }
274 pathv[count] = NULL((void*)0);
275 return pathv;
276}
277
278JNIEXPORT__attribute__((visibility("default"))) void JNICALL
279Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
280{
281 parentPathv = effectivePathv(env);
282 CHECK_NULL(parentPathv)do { if ((parentPathv) == ((void*)0)) { return; } } while (0);
283 setSIGCHLDHandler(env);
284}
285
286
287#ifndef WIFEXITED
288#define WIFEXITED(status)(((status) & 0x7f) == 0) (((status)&0xFF) == 0)
289#endif
290
291#ifndef WEXITSTATUS
292#define WEXITSTATUS(status)(((status) & 0xff00) >> 8) (((status)>>8)&0xFF)
293#endif
294
295#ifndef WIFSIGNALED
296#define WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
(((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
297#endif
298
299#ifndef WTERMSIG
300#define WTERMSIG(status)((status) & 0x7f) ((status)&0x7F)
301#endif
302
303static const char *
304getBytes(JNIEnv *env, jbyteArray arr)
305{
306 return arr == NULL((void*)0) ? NULL((void*)0) :
307 (const char*) (*env)->GetByteArrayElements(env, arr, NULL((void*)0));
308}
309
310static void
311releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
312{
313 if (parr != NULL((void*)0))
314 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT2);
315}
316
317#define IOE_FORMAT"error=%d, %s" "error=%d, %s"
318
319static void
320throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
321{
322 const char *detail = defaultDetail;
323 char *errmsg;
324 size_t fmtsize;
325 char tmpbuf[1024];
326 jstring s;
327
328 if (errnum != 0) {
329 int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
330 if (ret != EINVAL22)
331 detail = tmpbuf;
332 }
333 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
334 fmtsize = sizeof(IOE_FORMAT"error=%d, %s") + strlen(detail) + 3 * sizeof(errnum);
335 errmsg = NEW(char, fmtsize)((char *) xmalloc(env, (fmtsize) * sizeof(char)));
336 if (errmsg == NULL((void*)0))
337 return;
338
339 snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail)__builtin___snprintf_chk (errmsg, fmtsize, 2 - 1, __builtin_object_size
(errmsg, 2 > 1), "error=%d, %s", errnum, detail)
;
340 s = JNU_NewStringPlatform(env, errmsg);
341 if (s != NULL((void*)0)) {
342 jobject x = JNU_NewObjectByName(env, "java/io/IOException",
343 "(Ljava/lang/String;)V", s);
344 if (x != NULL((void*)0))
345 (*env)->Throw(env, x);
346 }
347 free(errmsg);
348}
349
350/**
351 * Throws an IOException with a message composed from the result of waitpid status.
352 */
353static void throwExitCause(JNIEnv *env, int pid, int status) {
354 char ebuf[128];
355 if (WIFEXITED(status)(((status) & 0x7f) == 0)) {
356 snprintf(ebuf, sizeof ebuf,__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, exit value: %d"
, pid, (((status) & 0xff00) >> 8))
357 "Failed to exec spawn helper: pid: %d, exit value: %d",__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, exit value: %d"
, pid, (((status) & 0xff00) >> 8))
358 pid, WEXITSTATUS(status))__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, exit value: %d"
, pid, (((status) & 0xff00) >> 8))
;
359 } else if (WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0
)
) {
360 snprintf(ebuf, sizeof ebuf,__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, signal: %d"
, pid, ((status) & 0x7f))
361 "Failed to exec spawn helper: pid: %d, signal: %d",__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, signal: %d"
, pid, ((status) & 0x7f))
362 pid, WTERMSIG(status))__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, signal: %d"
, pid, ((status) & 0x7f))
;
363 } else {
364 snprintf(ebuf, sizeof ebuf,__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, status: 0x%08x"
, pid, status)
365 "Failed to exec spawn helper: pid: %d, status: 0x%08x",__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, status: 0x%08x"
, pid, status)
366 pid, status)__builtin___snprintf_chk (ebuf, sizeof ebuf, 2 - 1, __builtin_object_size
(ebuf, 2 > 1), "Failed to exec spawn helper: pid: %d, status: 0x%08x"
, pid, status)
;
367 }
368 throwIOException(env, 0, ebuf);
369}
370
371#ifdef DEBUG_PROCESS
372/* Debugging process code is difficult; where to write debug output? */
373static void
374debugPrint(char *format, ...)
375{
376 FILE *tty = fopen("/dev/tty", "w");
377 va_list ap;
378 va_start(ap, format)__builtin_va_start(ap, format);
379 vfprintf(tty, format, ap);
380 va_end(ap)__builtin_va_end(ap);
381 fclose(tty);
382}
383#endif /* DEBUG_PROCESS */
384
385static void
386copyPipe(int from[2], int to[2])
387{
388 to[0] = from[0];
389 to[1] = from[1];
390}
391
392/* arg is an array of pointers to 0 terminated strings. array is terminated
393 * by a null element.
394 *
395 * *nelems and *nbytes receive the number of elements of array (incl 0)
396 * and total number of bytes (incl. 0)
397 * Note. An empty array will have one null element
398 * But if arg is null, then *nelems set to 0, and *nbytes to 0
399 */
400static void arraysize(const char * const *arg, int *nelems, int *nbytes)
401{
402 int i, bytes, count;
403 const char * const *a = arg;
404 char *p;
405 int *q;
406 if (arg == 0) {
407 *nelems = 0;
408 *nbytes = 0;
409 return;
410 }
411 /* count the array elements and number of bytes */
412 for (count=0, bytes=0; *a != 0; count++, a++) {
413 bytes += strlen(*a)+1;
414 }
415 *nbytes = bytes;
416 *nelems = count+1;
417}
418
419/* copy the strings from arg[] into buf, starting at given offset
420 * return new offset to next free byte
421 */
422static int copystrings(char *buf, int offset, const char * const *arg) {
423 char *p;
424 const char * const *a;
425 int count=0;
426
427 if (arg == 0) {
428 return offset;
429 }
430 for (p=buf+offset, a=arg; *a != 0; a++) {
431 int len = strlen(*a) +1;
432 memcpy(p, *a, len);
433 p += len;
434 count += len;
435 }
436 return offset+count;
437}
438
439/**
440 * We are unusually paranoid; use of vfork is
441 * especially likely to tickle gcc/glibc bugs.
442 */
443#ifdef __attribute_noinline____attribute__ ((__noinline__)) /* See: sys/cdefs.h */
444__attribute_noinline____attribute__ ((__noinline__))
445#endif
446
447/* vfork(2) is deprecated on Darwin */
448#ifndef __APPLE__
449static pid_t
450vforkChild(ChildStuff *c) {
451 volatile pid_t resultPid;
452
453 /*
454 * We separate the call to vfork into a separate function to make
455 * very sure to keep stack of child from corrupting stack of parent,
456 * as suggested by the scary gcc warning:
457 * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
458 */
459 resultPid = vfork();
460
461 if (resultPid
30.1
'resultPid' is equal to 0
== 0) {
31
Taking true branch
462 childProcess(c);
32
This function call is prohibited after a successful vfork
463 }
464 assert(resultPid != 0)((resultPid != 0) ? (void) (0) : __assert_fail ("resultPid != 0"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 464, __extension__ __PRETTY_FUNCTION__))
; /* childProcess never returns */
465 return resultPid;
466}
467#endif
468
469static pid_t
470forkChild(ChildStuff *c) {
471 pid_t resultPid;
472
473 /*
474 * From Solaris fork(2): In Solaris 10, a call to fork() is
475 * identical to a call to fork1(); only the calling thread is
476 * replicated in the child process. This is the POSIX-specified
477 * behavior for fork().
478 */
479 resultPid = fork();
480
481 if (resultPid == 0) {
482 childProcess(c);
483 }
484 assert(resultPid != 0)((resultPid != 0) ? (void) (0) : __assert_fail ("resultPid != 0"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 484, __extension__ __PRETTY_FUNCTION__))
; /* childProcess never returns */
485 return resultPid;
486}
487
488static pid_t
489spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
490 pid_t resultPid;
491 jboolean isCopy;
492 int i, offset, rval, bufsize, magic;
493 char *buf, buf1[16];
494 char *hlpargs[2];
495 SpawnInfo sp;
496
497 /* need to tell helper which fd is for receiving the childstuff
498 * and which fd to send response back on
499 */
500 snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1])__builtin___snprintf_chk (buf1, sizeof(buf1), 2 - 1, __builtin_object_size
(buf1, 2 > 1), "%d:%d", c->childenv[0], c->fail[1])
;
501 /* put the fd string as argument to the helper cmd */
502 hlpargs[0] = buf1;
503 hlpargs[1] = 0;
504
505 /* Following items are sent down the pipe to the helper
506 * after it is spawned.
507 * All strings are null terminated. All arrays of strings
508 * have an empty string for termination.
509 * - the ChildStuff struct
510 * - the SpawnInfo struct
511 * - the argv strings array
512 * - the envv strings array
513 * - the home directory string
514 * - the parentPath string
515 * - the parentPathv array
516 */
517 /* First calculate the sizes */
518 arraysize(c->argv, &sp.nargv, &sp.argvBytes);
519 bufsize = sp.argvBytes;
520 arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
521 bufsize += sp.envvBytes;
522 sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
523 bufsize += sp.dirlen;
524 arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
525 bufsize += sp.parentPathvBytes;
526 /* We need to clear FD_CLOEXEC if set in the fds[].
527 * Files are created FD_CLOEXEC in Java.
528 * Otherwise, they will be closed when the target gets exec'd */
529 for (i=0; i<3; i++) {
530 if (c->fds[i] != -1) {
531 int flags = fcntl(c->fds[i], F_GETFD1);
532 if (flags & FD_CLOEXEC1) {
533 fcntl(c->fds[i], F_SETFD2, flags & (~1));
534 }
535 }
536 }
537
538 rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
539
540 if (rval != 0) {
541 return -1;
542 }
543
544 /* now the lengths are known, copy the data */
545 buf = NEW(char, bufsize)((char *) xmalloc(env, (bufsize) * sizeof(char)));
546 if (buf == 0) {
547 return -1;
548 }
549 offset = copystrings(buf, 0, &c->argv[0]);
550 offset = copystrings(buf, offset, &c->envv[0]);
551 memcpy(buf+offset, c->pdir, sp.dirlen);
552 offset += sp.dirlen;
553 offset = copystrings(buf, offset, parentPathv);
554 assert(offset == bufsize)((offset == bufsize) ? (void) (0) : __assert_fail ("offset == bufsize"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 554, __extension__ __PRETTY_FUNCTION__))
;
555
556 magic = magicNumber();
557
558 /* write the two structs and the data buffer */
559 write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
560 write(c->childenv[1], (char *)c, sizeof(*c));
561 write(c->childenv[1], (char *)&sp, sizeof(sp));
562 write(c->childenv[1], buf, bufsize);
563 free(buf);
564
565 /* In this mode an external main() in invoked which calls back into
566 * childProcess() in this file, rather than directly
567 * via the statement below */
568 return resultPid;
569}
570
571/*
572 * Start a child process running function childProcess.
573 * This function only returns in the parent.
574 */
575static pid_t
576startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
577 switch (c->mode) {
29
Control jumps to 'case 3:' at line 580
578/* vfork(2) is deprecated on Darwin*/
579 #ifndef __APPLE__
580 case MODE_VFORK3:
581 return vforkChild(c);
30
Calling 'vforkChild'
582 #endif
583 case MODE_FORK1:
584 return forkChild(c);
585 case MODE_POSIX_SPAWN2:
586 return spawnChild(env, process, c, helperpath);
587 default:
588 return -1;
589 }
590}
591
592JNIEXPORT__attribute__((visibility("default"))) jint JNICALL
593Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
594 jobject process,
595 jint mode,
596 jbyteArray helperpath,
597 jbyteArray prog,
598 jbyteArray argBlock, jint argc,
599 jbyteArray envBlock, jint envc,
600 jbyteArray dir,
601 jintArray std_fds,
602 jboolean redirectErrorStream)
603{
604 int errnum;
605 int resultPid = -1;
606 int in[2], out[2], err[2], fail[2], childenv[2];
607 jint *fds = NULL((void*)0);
608 const char *phelperpath = NULL((void*)0);
609 const char *pprog = NULL((void*)0);
610 const char *pargBlock = NULL((void*)0);
611 const char *penvBlock = NULL((void*)0);
612 ChildStuff *c;
613
614 in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
615 childenv[0] = childenv[1] = -1;
616
617 if ((c = NEW(ChildStuff, 1)((ChildStuff *) xmalloc(env, (1) * sizeof(ChildStuff)))) == NULL((void*)0)) return -1;
1
Taking false branch
618 c->argv = NULL((void*)0);
619 c->envv = NULL((void*)0);
620 c->pdir = NULL((void*)0);
621
622 /* Convert prog + argBlock into a char ** argv.
623 * Add one word room for expansion of argv for use by
624 * execve_as_traditional_shell_script.
625 * This word is also used when using posix_spawn mode
626 */
627 assert(prog != NULL && argBlock != NULL)((prog != ((void*)0) && argBlock != ((void*)0)) ? (void
) (0) : __assert_fail ("prog != NULL && argBlock != NULL"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 627, __extension__ __PRETTY_FUNCTION__))
;
2
Assuming 'prog' is not equal to null
3
Assuming 'argBlock' is not equal to null
4
'?' condition is true
628 if ((phelperpath = getBytes(env, helperpath)) == NULL((void*)0)) goto Catch;
5
Assuming the condition is false
6
Taking false branch
629 if ((pprog = getBytes(env, prog)) == NULL((void*)0)) goto Catch;
7
Assuming the condition is false
8
Taking false branch
630 if ((pargBlock = getBytes(env, argBlock)) == NULL((void*)0)) goto Catch;
9
Assuming the condition is false
10
Taking false branch
631 if ((c->argv = NEW(const char *, argc + 3)((const char * *) xmalloc(env, (argc + 3) * sizeof(const char
*)))
) == NULL((void*)0)) goto Catch;
11
Taking false branch
632 c->argv[0] = pprog;
633 c->argc = argc + 2;
634 initVectorFromBlock(c->argv+1, pargBlock, argc);
635
636 if (envBlock != NULL((void*)0)) {
12
Assuming 'envBlock' is equal to NULL
13
Taking false branch
637 /* Convert envBlock into a char ** envv */
638 if ((penvBlock = getBytes(env, envBlock)) == NULL((void*)0)) goto Catch;
639 if ((c->envv = NEW(const char *, envc + 1)((const char * *) xmalloc(env, (envc + 1) * sizeof(const char
*)))
) == NULL((void*)0)) goto Catch;
640 initVectorFromBlock(c->envv, penvBlock, envc);
641 }
642
643 if (dir != NULL((void*)0)) {
14
Assuming 'dir' is equal to NULL
15
Taking false branch
644 if ((c->pdir = getBytes(env, dir)) == NULL((void*)0)) goto Catch;
645 }
646
647 assert(std_fds != NULL)((std_fds != ((void*)0)) ? (void) (0) : __assert_fail ("std_fds != NULL"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 647, __extension__ __PRETTY_FUNCTION__))
;
16
Assuming 'std_fds' is not equal to null
17
'?' condition is true
648 fds = (*env)->GetIntArrayElements(env, std_fds, NULL((void*)0));
649 if (fds == NULL((void*)0)) goto Catch;
18
Assuming 'fds' is not equal to NULL
19
Taking false branch
650
651 if ((fds[0] == -1 && pipe(in) < 0) ||
20
Assuming the condition is false
25
Taking false branch
652 (fds[1] == -1 && pipe(out) < 0) ||
21
Assuming the condition is false
653 (fds[2] == -1 && pipe(err) < 0) ||
22
Assuming the condition is false
654 (pipe(childenv) < 0) ||
23
Assuming the condition is false
655 (pipe(fail) < 0)) {
24
Assuming the condition is false
656 throwIOException(env, errno(*__errno_location ()), "Bad file descriptor");
657 goto Catch;
658 }
659 c->fds[0] = fds[0];
660 c->fds[1] = fds[1];
661 c->fds[2] = fds[2];
662
663 copyPipe(in, c->in);
664 copyPipe(out, c->out);
665 copyPipe(err, c->err);
666 copyPipe(fail, c->fail);
667 copyPipe(childenv, c->childenv);
668
669 c->redirectErrorStream = redirectErrorStream;
670 c->mode = mode;
671
672 /* In posix_spawn mode, require the child process to signal aliveness
673 * right after it comes up. This is because there are implementations of
674 * posix_spawn() which do not report failed exec()s back to the caller
675 * (e.g. glibc, see JDK-8223777). In those cases, the fork() will have
676 * worked and successfully started the child process, but the exec() will
677 * have failed. There is no way for us to distinguish this from a target
678 * binary just exiting right after start.
679 *
680 * Note that we could do this additional handshake in all modes but for
681 * prudence only do it when it is needed (in posix_spawn mode). */
682 c->sendAlivePing = (mode == MODE_POSIX_SPAWN2) ? 1 : 0;
26
Assuming 'mode' is not equal to MODE_POSIX_SPAWN
27
'?' condition is false
683
684 resultPid = startChild(env, process, c, phelperpath);
28
Calling 'startChild'
685 assert(resultPid != 0)((resultPid != 0) ? (void) (0) : __assert_fail ("resultPid != 0"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 685, __extension__ __PRETTY_FUNCTION__))
;
686
687 if (resultPid < 0) {
688 switch (c->mode) {
689 case MODE_VFORK3:
690 throwIOException(env, errno(*__errno_location ()), "vfork failed");
691 break;
692 case MODE_FORK1:
693 throwIOException(env, errno(*__errno_location ()), "fork failed");
694 break;
695 case MODE_POSIX_SPAWN2:
696 throwIOException(env, errno(*__errno_location ()), "posix_spawn failed");
697 break;
698 }
699 goto Catch;
700 }
701 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */
702
703 /* If we expect the child to ping aliveness, wait for it. */
704 if (c->sendAlivePing) {
705 switch(readFully(fail[0], &errnum, sizeof(errnum))) {
706 case 0: /* First exec failed; */
707 {
708 int tmpStatus = 0;
709 int p = waitpid(resultPid, &tmpStatus, 0);
710 throwExitCause(env, p, tmpStatus);
711 goto Catch;
712 }
713 case sizeof(errnum):
714 assert(errnum == CHILD_IS_ALIVE)((errnum == 65535) ? (void) (0) : __assert_fail ("errnum == CHILD_IS_ALIVE"
, "/home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c"
, 714, __extension__ __PRETTY_FUNCTION__))
;
715 if (errnum != CHILD_IS_ALIVE65535) {
716 /* Should never happen since the first thing the spawn
717 * helper should do is to send an alive ping to the parent,
718 * before doing any subsequent work. */
719 throwIOException(env, 0, "Bad code from spawn helper "
720 "(Failed to exec spawn helper)");
721 goto Catch;
722 }
723 break;
724 default:
725 throwIOException(env, errno(*__errno_location ()), "Read failed");
726 goto Catch;
727 }
728 }
729
730 switch (readFully(fail[0], &errnum, sizeof(errnum))) {
731 case 0: break; /* Exec succeeded */
732 case sizeof(errnum):
733 waitpid(resultPid, NULL((void*)0), 0);
734 throwIOException(env, errnum, "Exec failed");
735 goto Catch;
736 default:
737 throwIOException(env, errno(*__errno_location ()), "Read failed");
738 goto Catch;
739 }
740
741 fds[0] = (in [1] != -1) ? in [1] : -1;
742 fds[1] = (out[0] != -1) ? out[0] : -1;
743 fds[2] = (err[0] != -1) ? err[0] : -1;
744
745 Finally:
746 /* Always clean up the child's side of the pipes */
747 closeSafely(in [0]);
748 closeSafely(out[1]);
749 closeSafely(err[1]);
750
751 /* Always clean up fail and childEnv descriptors */
752 closeSafely(fail[0]);
753 closeSafely(fail[1]);
754 closeSafely(childenv[0]);
755 closeSafely(childenv[1]);
756
757 releaseBytes(env, helperpath, phelperpath);
758 releaseBytes(env, prog, pprog);
759 releaseBytes(env, argBlock, pargBlock);
760 releaseBytes(env, envBlock, penvBlock);
761 releaseBytes(env, dir, c->pdir);
762
763 free(c->argv);
764 free(c->envv);
765 free(c);
766
767 if (fds != NULL((void*)0))
768 (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
769
770 return resultPid;
771
772 Catch:
773 /* Clean up the parent's side of the pipes in case of failure only */
774 closeSafely(in [1]); in[1] = -1;
775 closeSafely(out[0]); out[0] = -1;
776 closeSafely(err[0]); err[0] = -1;
777 goto Finally;
778}
779