@@ -454,7 +454,7 @@ static void commonChildInit(int stderrFd)
454
454
throw SysError (format (" creating a new session" ));
455
455
456
456
/* Dup the write side of the logger pipe into stderr. */
457
- if (dup2 (stderrFd, STDERR_FILENO) == -1 )
457
+ if (stderrFd != - 1 && dup2 (stderrFd, STDERR_FILENO) == -1 )
458
458
throw SysError (" cannot pipe standard error into log file" );
459
459
460
460
/* Dup stderr to stdout. */
@@ -2264,6 +2264,27 @@ void DerivationGoal::startBuilder()
2264
2264
if (unlockpt (builderOut.get ()))
2265
2265
throw SysError (" unlocking pseudoterminal" );
2266
2266
2267
+ /* Open the slave side of the pseudoterminal and use it as stderr. */
2268
+ auto openSlave = [&]()
2269
+ {
2270
+ AutoCloseFD builderOut = open (slaveName.c_str (), O_RDWR | O_NOCTTY);
2271
+ if (!builderOut)
2272
+ throw SysError (" opening pseudoterminal slave" );
2273
+
2274
+ // Put the pt into raw mode to prevent \n -> \r\n translation.
2275
+ struct termios term;
2276
+ if (tcgetattr (builderOut.get (), &term))
2277
+ throw SysError (" getting pseudoterminal attributes" );
2278
+
2279
+ cfmakeraw (&term);
2280
+
2281
+ if (tcsetattr (builderOut.get (), TCSANOW, &term))
2282
+ throw SysError (" putting pseudoterminal into raw mode" );
2283
+
2284
+ if (dup2 (builderOut.get (), STDERR_FILENO) == -1 )
2285
+ throw SysError (" cannot pipe standard error into log file" );
2286
+ };
2287
+
2267
2288
result.startTime = time (0 );
2268
2289
2269
2290
/* Fork a child to build the package. */
@@ -2318,6 +2339,11 @@ void DerivationGoal::startBuilder()
2318
2339
Pid helper = startProcess ([&]() {
2319
2340
sendPid.readSide .close ();
2320
2341
2342
+ /* We need to open the slave early, before
2343
+ CLONE_NEWUSER. Otherwise we get EPERM when running as
2344
+ root. */
2345
+ openSlave ();
2346
+
2321
2347
/* Drop additional groups here because we can't do it
2322
2348
after we've created the new user namespace. FIXME:
2323
2349
this means that if we're not root in the parent
@@ -2410,6 +2436,7 @@ void DerivationGoal::startBuilder()
2410
2436
fallback:
2411
2437
options.allowVfork = !buildUser && !drv->isBuiltin ();
2412
2438
pid = startProcess ([&]() {
2439
+ openSlave ();
2413
2440
runChild ();
2414
2441
}, options);
2415
2442
}
@@ -2723,22 +2750,7 @@ void DerivationGoal::runChild()
2723
2750
2724
2751
try { /* child */
2725
2752
2726
- /* Open the slave side of the pseudoterminal. */
2727
- AutoCloseFD builderOut = open (slaveName.c_str (), O_RDWR | O_NOCTTY);
2728
- if (!builderOut)
2729
- throw SysError (" opening pseudoterminal slave" );
2730
-
2731
- // Put the pt into raw mode to prevent \n -> \r\n translation.
2732
- struct termios term;
2733
- if (tcgetattr (builderOut.get (), &term))
2734
- throw SysError (" getting pseudoterminal attributes" );
2735
-
2736
- cfmakeraw (&term);
2737
-
2738
- if (tcsetattr (builderOut.get (), TCSANOW, &term))
2739
- throw SysError (" putting pseudoterminal into raw mode" );
2740
-
2741
- commonChildInit (builderOut.get ());
2753
+ commonChildInit (-1 );
2742
2754
2743
2755
try {
2744
2756
setupSeccomp ();
0 commit comments