23
23
#include < signal.h>
24
24
#include < stdlib.h>
25
25
#include < sys/types.h>
26
+ #include < sys/stat.h>
26
27
#include < sys/wait.h>
27
28
#include < unistd.h>
29
+ #include < fcntl.h>
28
30
29
31
#include " cutils/fs.h"
30
32
#include " cutils/multiuser.h"
@@ -401,12 +403,43 @@ static bool NeedsNoRandomizeWorkaround() {
401
403
}
402
404
#endif
403
405
406
+ // Utility to close down the Zygote socket file descriptors while
407
+ // the child is still running as root with Zygote's privileges. Each
408
+ // descriptor (if any) is closed via dup2(), replacing it with a valid
409
+ // (open) descriptor to /dev/null.
410
+
411
+ static void DetachDescriptors (JNIEnv* env, jintArray fdsToClose) {
412
+ if (!fdsToClose) {
413
+ return ;
414
+ }
415
+ jsize count = env->GetArrayLength (fdsToClose);
416
+ jint *ar = env->GetIntArrayElements (fdsToClose, 0 );
417
+ if (!ar) {
418
+ PLOG (FATAL) << " Bad fd array" ;
419
+ }
420
+ jsize i;
421
+ int devnull;
422
+ for (i = 0 ; i < count; i++) {
423
+ devnull = open (" /dev/null" , O_RDWR);
424
+ if (devnull < 0 ) {
425
+ PLOG (FATAL) << " Failed to open /dev/null" ;
426
+ continue ;
427
+ }
428
+ PLOG (VERBOSE) << " Switching descriptor " << ar[i] << " to /dev/null" ;
429
+ if (dup2 (devnull, ar[i]) < 0 ) {
430
+ PLOG (FATAL) << " Failed dup2() on descriptor " << ar[i];
431
+ }
432
+ close (devnull);
433
+ }
434
+ }
435
+
404
436
// Utility routine to fork zygote and specialize the child process.
405
437
static pid_t ForkAndSpecializeCommon (JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
406
438
jint debug_flags, jobjectArray javaRlimits,
407
439
jlong permittedCapabilities, jlong effectiveCapabilities,
408
440
jint mount_external,
409
- jstring java_se_info, jstring java_se_name, bool is_system_server) {
441
+ jstring java_se_info, jstring java_se_name,
442
+ bool is_system_server, jintArray fdsToClose) {
410
443
Runtime* runtime = Runtime::Current ();
411
444
CHECK (runtime->IsZygote ()) << " runtime instance not started with -Xzygote" ;
412
445
if (!runtime->PreZygoteFork ()) {
@@ -425,6 +458,9 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
425
458
// The child process.
426
459
gMallocLeakZygoteChild = 1 ;
427
460
461
+ // Clean up any descriptors which must be closed immediately
462
+ DetachDescriptors (env, fdsToClose);
463
+
428
464
// Keep capabilities across UID change, unless we're staying root.
429
465
if (uid != 0 ) {
430
466
EnableKeepCapabilities ();
@@ -516,10 +552,19 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
516
552
return pid;
517
553
}
518
554
555
+ static jint Zygote_nativeForkAndSpecialize_new (JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
556
+ jint debug_flags, jobjectArray rlimits,
557
+ jint mount_external, jstring se_info, jstring se_name,
558
+ jintArray fdsToClose) {
559
+ return ForkAndSpecializeCommon (env, uid, gid, gids, debug_flags, rlimits, 0 , 0 , mount_external,
560
+ se_info, se_name, false , fdsToClose);
561
+ }
562
+
519
563
static jint Zygote_nativeForkAndSpecialize (JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
520
- jint debug_flags, jobjectArray rlimits, jint mount_external,
521
- jstring se_info, jstring se_name) {
522
- return ForkAndSpecializeCommon (env, uid, gid, gids, debug_flags, rlimits, 0 , 0 , mount_external, se_info, se_name, false );
564
+ jint debug_flags, jobjectArray rlimits,
565
+ jint mount_external, jstring se_info, jstring se_name) {
566
+ return ForkAndSpecializeCommon (env, uid, gid, gids, debug_flags, rlimits, 0 , 0 , mount_external,
567
+ se_info, se_name, false , NULL );
523
568
}
524
569
525
570
static jint Zygote_nativeForkSystemServer (JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
@@ -528,7 +573,7 @@ static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t
528
573
pid_t pid = ForkAndSpecializeCommon (env, uid, gid, gids,
529
574
debug_flags, rlimits,
530
575
permittedCapabilities, effectiveCapabilities,
531
- MOUNT_EXTERNAL_NONE, NULL , NULL , true );
576
+ MOUNT_EXTERNAL_NONE, NULL , NULL , true , NULL );
532
577
if (pid > 0 ) {
533
578
// The zygote process checks whether the child process has died or not.
534
579
LOG (INFO) << " System server process " << pid << " has been created" ;
@@ -545,6 +590,7 @@ static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t
545
590
}
546
591
547
592
static JNINativeMethod gMethods [] = {
593
+ NATIVE_METHOD (Zygote, nativeForkAndSpecialize_new, " (II[II[[IILjava/lang/String;Ljava/lang/String;[I)I" ),
548
594
NATIVE_METHOD (Zygote, nativeForkAndSpecialize, " (II[II[[IILjava/lang/String;Ljava/lang/String;)I" ),
549
595
NATIVE_METHOD (Zygote, nativeForkSystemServer, " (II[II[[IJJ)I" ),
550
596
};
0 commit comments