@@ -282,6 +282,27 @@ static bool PathInNamespace(char* realpath,
282282 return true ;
283283}
284284
285+ // Linux 5.9, glibc 2.34.
286+ extern " C" int close_range (unsigned int first, unsigned int last, int flags)
287+ __attribute__((weak));
288+
289+ void CloseAllButStdioAndExecControl (int exec_control_fd) {
290+ if (&close_range != nullptr ) {
291+ close_range (3 , exec_control_fd - 1 , 0 );
292+ close_range (exec_control_fd + 1 , ~0u , 0 );
293+ } else {
294+ int max_fds = sysconf (_SC_OPEN_MAX);
295+ if (max_fds == -1 ) {
296+ max_fds = _POSIX_OPEN_MAX;
297+ }
298+ for (int fd = 3 ; fd < max_fds; fd++) {
299+ if (fd != exec_control_fd) {
300+ close (fd);
301+ }
302+ }
303+ }
304+ }
305+
285306class ProcessStarter {
286307 public:
287308 ProcessStarter (Namespace* namespc,
@@ -644,63 +665,33 @@ class ProcessStarter {
644665 void SetupDetached () {
645666 ASSERT (mode_ == kDetached );
646667
647- // Close all open file descriptors except for exec_control_[1].
648- int max_fds = sysconf (_SC_OPEN_MAX);
649- if (max_fds == -1 ) {
650- max_fds = _POSIX_OPEN_MAX;
651- }
652- for (int fd = 0 ; fd < max_fds; fd++) {
653- if (fd != exec_control_[1 ]) {
654- close (fd);
655- }
656- }
657-
658- // Re-open stdin, stdout and stderr and connect them to /dev/null.
659- // The loop above should already have closed all of them, so
660- // creating new file descriptors should start at STDIN_FILENO.
668+ // Connect stdin, stdout and stderr to /dev/null.
661669 int fd = TEMP_FAILURE_RETRY (open (" /dev/null" , O_RDWR));
662- if (fd != STDIN_FILENO) {
670+ if (TEMP_FAILURE_RETRY ( dup2 (fd, STDIN_FILENO)) != STDIN_FILENO) {
663671 ReportChildError ();
664672 }
665- if (TEMP_FAILURE_RETRY (dup2 (STDIN_FILENO, STDOUT_FILENO)) !=
666- STDOUT_FILENO) {
673+ if (TEMP_FAILURE_RETRY (dup2 (fd, STDOUT_FILENO)) != STDOUT_FILENO) {
667674 ReportChildError ();
668675 }
669- if (TEMP_FAILURE_RETRY (dup2 (STDIN_FILENO, STDERR_FILENO)) !=
670- STDERR_FILENO) {
676+ if (TEMP_FAILURE_RETRY (dup2 (fd, STDERR_FILENO)) != STDERR_FILENO) {
671677 ReportChildError ();
672678 }
679+
680+ CloseAllButStdioAndExecControl (exec_control_[1 ]);
673681 }
674682
675683 void SetupDetachedWithStdio () {
676- // Close all open file descriptors except for
677- // exec_control_[1], write_out_[0], read_in_[1] and
678- // read_err_[1].
679- int max_fds = sysconf (_SC_OPEN_MAX);
680- if (max_fds == -1 ) {
681- max_fds = _POSIX_OPEN_MAX;
682- }
683- for (int fd = 0 ; fd < max_fds; fd++) {
684- if ((fd != exec_control_[1 ]) && (fd != write_out_[0 ]) &&
685- (fd != read_in_[1 ]) && (fd != read_err_[1 ])) {
686- close (fd);
687- }
688- }
689-
690684 if (TEMP_FAILURE_RETRY (dup2 (write_out_[0 ], STDIN_FILENO)) == -1 ) {
691685 ReportChildError ();
692686 }
693- close (write_out_[0 ]);
694-
695687 if (TEMP_FAILURE_RETRY (dup2 (read_in_[1 ], STDOUT_FILENO)) == -1 ) {
696688 ReportChildError ();
697689 }
698- close (read_in_[1 ]);
699-
700690 if (TEMP_FAILURE_RETRY (dup2 (read_err_[1 ], STDERR_FILENO)) == -1 ) {
701691 ReportChildError ();
702692 }
703- close (read_err_[1 ]);
693+
694+ CloseAllButStdioAndExecControl (exec_control_[1 ]);
704695 }
705696
706697 int CleanupAndReturnError () {
0 commit comments