30
30
#include <sys/types.h>
31
31
#include <sys/socket.h>
32
32
#include <sys/stat.h>
33
+ #include <sys/syscall.h>
33
34
#include <sys/un.h>
34
35
#include <sys/wait.h>
35
36
#include <netdb.h>
@@ -88,20 +89,27 @@ void exec_qubes_rpc_if_requested(const char *prog, char *const envp[]) {
88
89
89
90
void fix_fds (int fdin , int fdout , int fderr )
90
91
{
91
- int i ;
92
- for (i = 3 ; i < 256 ; i ++ )
93
- if (i != fdin && i != fdout && i != fderr )
94
- close (i );
92
+ if (fdin < 0 || fdout < 1 || fderr < 2 ) {
93
+ LOG (ERROR , "fix_fds: bad FD numbers: fdin %d, fdout %d, fderr %d" ,
94
+ fdin , fdout , fderr );
95
+ _exit (125 );
96
+ }
95
97
if (dup2 (fdin , 0 ) < 0 || dup2 (fdout , 1 ) < 0 || dup2 (fderr , 2 ) < 0 ) {
96
98
PERROR ("dup2" );
97
99
abort ();
98
100
}
99
-
100
- if (close (fdin ) || (fdin != fdout && close (fdout )) ||
101
- (fdin != fderr && fdout != fderr && fderr != 2 && close (fderr ))) {
102
- PERROR ("close" );
101
+ #ifdef SYS_close_range
102
+ int close_range_res = syscall (SYS_close_range , 3 , ~0U , 0 );
103
+ if (close_range_res == 0 )
104
+ return ;
105
+ assert (close_range_res == -1 );
106
+ if (errno != ENOSYS ) {
107
+ PERROR ("close_range" );
103
108
abort ();
104
109
}
110
+ #endif
111
+ for (int i = 3 ; i < 256 ; ++ i )
112
+ close (i );
105
113
}
106
114
107
115
static int do_fork_exec (const char * user ,
@@ -111,14 +119,13 @@ static int do_fork_exec(const char *user,
111
119
int * stdout_fd ,
112
120
int * stderr_fd )
113
121
{
114
- int inpipe [2 ], outpipe [2 ], errpipe [2 ], statuspipe [ 2 ], retval ;
122
+ int inpipe [2 ], outpipe [2 ], errpipe [2 ], retval ;
115
123
#ifndef SOCK_CLOEXEC
116
124
#define SOCK_CLOEXEC 0
117
125
#endif
118
- if (socketpair (AF_UNIX , SOCK_STREAM , 0 , inpipe ) ||
119
- socketpair (AF_UNIX , SOCK_STREAM , 0 , outpipe ) ||
120
- (stderr_fd && socketpair (AF_UNIX , SOCK_STREAM , 0 , errpipe )) ||
121
- socketpair (AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , statuspipe )) {
126
+ if (socketpair (AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , inpipe ) ||
127
+ socketpair (AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , outpipe ) ||
128
+ (stderr_fd && socketpair (AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC , 0 , errpipe ))) {
122
129
PERROR ("socketpair" );
123
130
/* FD leaks do not matter, we exit soon anyway */
124
131
return -2 ;
@@ -128,38 +135,19 @@ static int do_fork_exec(const char *user,
128
135
PERROR ("fork" );
129
136
/* ditto */
130
137
return -2 ;
131
- case 0 : {
132
- int status ;
138
+ case 0 :
133
139
if (signal (SIGPIPE , SIG_DFL ) == SIG_ERR )
134
140
abort ();
135
141
if (stderr_fd ) {
136
142
fix_fds (inpipe [0 ], outpipe [1 ], errpipe [1 ]);
137
143
} else
138
144
fix_fds (inpipe [0 ], outpipe [1 ], 2 );
139
145
140
- close (statuspipe [0 ]);
141
- if (SOCK_CLOEXEC == (0 )) {
142
- status = fcntl (statuspipe [1 ], F_GETFD );
143
- fcntl (statuspipe [1 ], F_SETFD , status | FD_CLOEXEC );
144
- }
145
146
if (exec_func != NULL )
146
147
exec_func (cmdline , user );
147
- else
148
- abort ();
149
- status = -1 ;
150
- while (write (statuspipe [1 ], & status , sizeof status ) <= 0 ) {}
151
- _exit (-1 );
152
- }
153
- default : {
154
- close (statuspipe [1 ]);
155
- if (read (statuspipe [0 ], & retval , sizeof retval ) == sizeof retval ) {
156
- siginfo_t siginfo ;
157
- memset (& siginfo , 0 , sizeof siginfo );
158
- waitid (P_PID , * pid , & siginfo , WEXITED ); // discard result
159
- } else {
160
- retval = 0 ;
161
- }
162
- }
148
+ abort ();
149
+ default :
150
+ retval = 0 ;
163
151
}
164
152
close (inpipe [0 ]);
165
153
close (outpipe [1 ]);
0 commit comments