@@ -100,18 +100,20 @@ static const std::string cloneFlagsToStr(uintptr_t flags) {
100
100
NS_VALSTR_STRUCT(CLONE_IO),
101
101
};
102
102
103
- uintptr_t knownFlagMask = CSIGNAL ;
103
+ uintptr_t knownFlagMask = 0 ;
104
104
for (const auto & i : cloneFlags) {
105
105
if (flags & i.flag ) {
106
- res.append (i.name ).append (" |" );
106
+ if (!res.empty ()) {
107
+ res.append (" |" );
108
+ }
109
+ res.append (i.name );
107
110
}
108
111
knownFlagMask |= i.flag ;
109
112
}
110
113
111
114
if (flags & ~(knownFlagMask)) {
112
- util::StrAppend (&res, " %#tx| " , flags & ~(knownFlagMask));
115
+ util::StrAppend (&res, " | %#tx" , flags & ~(knownFlagMask));
113
116
}
114
- res.append (util::sigName (flags & CSIGNAL).c_str ());
115
117
return res;
116
118
}
117
119
@@ -444,8 +446,8 @@ pid_t runChild(nsjconf_t* nsjconf, int netfd, int fd_in, int fd_out, int fd_err)
444
446
LOG_F (" Launching new process failed" );
445
447
}
446
448
447
- flags |= SIGCHLD;
448
- LOG_D ( " Creating new process with clone flags:%s " , cloneFlagsToStr (flags).c_str ());
449
+ LOG_D ( " Creating new process with clone flags:%s and exit_signal: SIGCHLD" ,
450
+ cloneFlagsToStr (flags).c_str ());
449
451
450
452
int sv[2 ];
451
453
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0 , sv) == -1 ) {
@@ -455,7 +457,7 @@ pid_t runChild(nsjconf_t* nsjconf, int netfd, int fd_in, int fd_out, int fd_err)
455
457
int child_fd = sv[0 ];
456
458
int parent_fd = sv[1 ];
457
459
458
- pid_t pid = cloneProc (flags);
460
+ pid_t pid = cloneProc (flags, SIGCHLD );
459
461
if (pid == 0 ) {
460
462
close (parent_fd);
461
463
subprocNewProc (nsjconf, netfd, fd_in, fd_out, fd_err, child_fd);
@@ -464,21 +466,20 @@ pid_t runChild(nsjconf_t* nsjconf, int netfd, int fd_in, int fd_out, int fd_err)
464
466
}
465
467
close (child_fd);
466
468
if (pid == -1 ) {
469
+ auto saved_errno = errno;
470
+ PLOG_W (" clone(flags=%s) failed" , cloneFlagsToStr (flags).c_str ());
467
471
if (flags & CLONE_NEWCGROUP) {
468
- auto saved_errno = errno;
469
- PLOG_E (
472
+ LOG_W (
470
473
" nsjail tried to use the CLONE_NEWCGROUP clone flag, which is "
471
- " supported under kernel versions >= 4.6 only. Try disabling this flag" );
472
- errno = saved_errno;
474
+ " supported under kernel versions >= 4.6 only" );
475
+ } else if (flags & CLONE_NEWTIME) {
476
+ LOG_W (
477
+ " nsjail tried to use the CLONE_NEWTIME clone flag, which is "
478
+ " supported under kernel versions >= 5.13 only" );
473
479
}
474
- PLOG_E (
475
- " clone(flags=%s) failed. You probably need root privileges if your system "
476
- " doesn't support CLONE_NEWUSER. Alternatively, you might want to recompile "
477
- " your kernel with support for namespaces or check the current value of the "
478
- " kernel.unprivileged_userns_clone sysctl" ,
479
- cloneFlagsToStr (flags).c_str ());
480
480
close (parent_fd);
481
- return -1 ;
481
+ errno = saved_errno;
482
+ return pid;
482
483
}
483
484
addProc (nsjconf, pid, netfd);
484
485
@@ -517,9 +518,39 @@ static int cloneFunc(void* arg __attribute__((unused))) {
517
518
* update the internal PID/TID caches, what can lead to invalid values being returned by getpid()
518
519
* or incorrect PID/TIDs used in raise()/abort() functions
519
520
*/
520
- pid_t cloneProc (uintptr_t flags) {
521
+ pid_t cloneProc (uintptr_t flags, int exit_signal) {
522
+ exit_signal &= CSIGNAL;
523
+
521
524
if (flags & CLONE_VM) {
522
525
LOG_E (" Cannot use clone(flags & CLONE_VM)" );
526
+ errno = 0 ;
527
+ return -1 ;
528
+ }
529
+
530
+ #if defined(__NR_clone3)
531
+ struct clone_args ca = {
532
+ .flags = (uint64_t )flags,
533
+ .pidfd = 0 ,
534
+ .child_tid = 0 ,
535
+ .parent_tid = 0 ,
536
+ .exit_signal = (uint64_t )exit_signal,
537
+ .stack = 0 ,
538
+ .stack_size = 0 ,
539
+ .tls = 0 ,
540
+ .set_tid = 0 ,
541
+ .set_tid_size = 0 ,
542
+ .cgroup = 0 ,
543
+ };
544
+
545
+ pid_t ret = util::syscall (__NR_clone3, (uintptr_t )&ca, sizeof (ca));
546
+ if (ret != -1 || errno != ENOSYS) {
547
+ return ret;
548
+ }
549
+ #endif /* defined(__NR_clone3) */
550
+
551
+ if (flags & CLONE_NEWTIME) {
552
+ LOG_E (" CLONE_NEWTIME was requested but clone3() is not supported" );
553
+ errno = 0 ;
523
554
return -1 ;
524
555
}
525
556
@@ -532,7 +563,7 @@ pid_t cloneProc(uintptr_t flags) {
532
563
*/
533
564
void * stack = &cloneStack[sizeof (cloneStack) / 2 ];
534
565
/* Parent */
535
- return clone (cloneFunc, stack, flags, NULL , NULL , NULL );
566
+ return clone (cloneFunc, stack, flags | exit_signal , NULL , NULL , NULL );
536
567
}
537
568
/* Child */
538
569
return 0 ;
0 commit comments