1 /*
2    Run a child process and collect the output
3 
4    Copyright (C) Amitay Isaacs  2016
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "replace.h"
21 #include "system/filesys.h"
22 #include "system/wait.h"
23 
24 #include <talloc.h>
25 #include <tevent.h>
26 
27 #include "lib/util/tevent_unix.h"
28 #include "lib/util/sys_rw.h"
29 #include "lib/util/blocking.h"
30 #include "lib/util/dlinklist.h"
31 
32 #include "common/run_proc.h"
33 
34 /*
35  * Process abstraction
36  */
37 
38 struct run_proc_context;
39 
40 struct proc_context {
41 	struct proc_context *prev, *next;
42 
43 	pid_t pid;
44 
45 	int fd;
46 	struct tevent_fd *fde;
47 
48 	char *output;
49 	struct run_proc_result result;
50 
51 	struct tevent_req *req;
52 };
53 
54 static int proc_destructor(struct proc_context *proc);
55 
56 static struct proc_context *proc_new(TALLOC_CTX *mem_ctx,
57 				     struct run_proc_context *run_ctx)
58 {
59 	struct proc_context *proc;
60 
61 	proc = talloc_zero(mem_ctx, struct proc_context);
62 	if (proc == NULL) {
63 		return NULL;
64 	}
65 
66 	proc->pid = -1;
67 	proc->fd = -1;
68 
69 	talloc_set_destructor(proc, proc_destructor);
70 
71 	return proc;
72 }
73 
74 static void run_proc_kill(struct tevent_req *req);
75 
76 static int proc_destructor(struct proc_context *proc)
77 {
78 	if (proc->req != NULL) {
79 		run_proc_kill(proc->req);
80 	}
81 
82 	talloc_free(proc->fde);
83 	if (proc->pid != -1) {
84 		kill(-proc->pid, SIGKILL);
85 	}
86 
87 	return 0;
88 }
89 
90 static void proc_read_handler(struct tevent_context *ev,
91 			      struct tevent_fd *fde, uint16_t flags,
92 			      void *private_data);
93 
94 static int proc_start(struct proc_context *proc, struct tevent_context *ev,
95 		      const char *path, const char **argv, int stdin_fd)
96 {
97 	int fd[2];
98 	int ret;
99 
100 	ret = pipe(fd);
101 	if (ret != 0) {
102 		return ret;
103 	}
104 
105 	proc->pid = fork();
106 	if (proc->pid == -1) {
107 		ret = errno;
108 		close(fd[0]);
109 		close(fd[1]);
110 		return ret;
111 	}
112 
113 	if (proc->pid == 0) {
114 		close(fd[0]);
115 
116 		ret = dup2(fd[1], STDOUT_FILENO);
117 		if (ret == -1) {
118 			exit(64 + errno);
119 		}
120 		ret = dup2(fd[1], STDERR_FILENO);
121 		if (ret == -1) {
122 			exit(64 + errno);
123 		}
124 
125 		close(fd[1]);
126 
127 		if (stdin_fd != -1) {
128 			ret = dup2(stdin_fd, STDIN_FILENO);
129 			if (ret == -1) {
130 				exit(64 + errno);
131 			}
132 		}
133 
134 		ret = setpgid(0, 0);
135 		if (ret != 0) {
136 			exit(64 + errno);
137 		}
138 
139 		ret = execv(path, discard_const(argv));
140 		if (ret != 0) {
141 			exit(64 + errno);
142 		}
143 
144 		exit(64 + ENOEXEC);
145 	}
146 
147 	close(fd[1]);
148 
149 	proc->fd = fd[0];
150 	proc->fde = tevent_add_fd(ev, proc, fd[0], TEVENT_FD_READ,
151 				  proc_read_handler, proc);
152 	if (proc->fde == NULL) {
153 		close(fd[0]);
154 		return ENOMEM;
155 	}
156 
157 	tevent_fd_set_auto_close(proc->fde);
158 
159 	return 0;
160 }
161 
162 static void proc_read_handler(struct tevent_context *ev,
163 			      struct tevent_fd *fde, uint16_t flags,
164 			      void *private_data)
165 {
166 	struct proc_context *proc = talloc_get_type_abort(
167 		private_data, struct proc_context);
168 	size_t offset;
169 	ssize_t nread;
170 	int len = 0;
171 	int ret;
172 
173 	ret = ioctl(proc->fd, FIONREAD, &len);
174 	if (ret != 0) {
175 		goto fail;
176 	}
177 
178 	if (len == 0) {
179 		/* pipe closed */
180 		goto close;
181 	}
182 
183 	offset = (proc->output == NULL) ? 0 : strlen(proc->output);
184 
185 	proc->output = talloc_realloc(proc, proc->output, char, offset+len+1);
186 	if (proc->output == NULL) {
187 		goto fail;
188 	}
189 
190 	nread = sys_read(proc->fd, proc->output + offset, len);
191 	if (nread == -1) {
192 		goto fail;
193 	}
194 	proc->output[offset+nread] = '\0';
195 	return;
196 
197 fail:
198 	if (proc->pid != -1) {
199 		kill(-proc->pid, SIGKILL);
200 		proc->pid = -1;
201 	}
202 close:
203 	TALLOC_FREE(proc->fde);
204 	proc->fd = -1;
205 }
206 
207 
208 /*
209  * Run proc abstraction
210  */
211 
212 struct run_proc_context {
213 	struct tevent_context *ev;
214 	struct tevent_signal *se;
215 	struct proc_context *plist;
216 };
217 
218 static void run_proc_signal_handler(struct tevent_context *ev,
219 				    struct tevent_signal *se,
220 				    int signum, int count, void *siginfo,
221 				    void *private_data);
222 static int run_proc_context_destructor(struct run_proc_context *run_ctx);
223 static void run_proc_done(struct tevent_req *req);
224 
225 int run_proc_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
226 		  struct run_proc_context **result)
227 {
228 	struct run_proc_context *run_ctx;
229 
230 	run_ctx = talloc_zero(mem_ctx, struct run_proc_context);
231 	if (run_ctx == NULL) {
232 		return ENOMEM;
233 	}
234 
235 	run_ctx->ev = ev;
236 	run_ctx->se = tevent_add_signal(ev, run_ctx, SIGCHLD, 0,
237 				       run_proc_signal_handler, run_ctx);
238 	if (run_ctx->se == NULL) {
239 		talloc_free(run_ctx);
240 		return ENOMEM;
241 	}
242 
243 	talloc_set_destructor(run_ctx, run_proc_context_destructor);
244 
245 	*result = run_ctx;
246 	return 0;
247 }
248 
249 static void run_proc_signal_handler(struct tevent_context *ev,
250 				    struct tevent_signal *se,
251 				    int signum, int count, void *siginfo,
252 				    void *private_data)
253 {
254 	struct run_proc_context *run_ctx = talloc_get_type_abort(
255 		private_data, struct run_proc_context);
256 	struct proc_context *proc;
257 	pid_t pid = -1;
258 	int status;
259 
260 again:
261 	pid = waitpid(-1, &status, WNOHANG);
262 	if (pid == -1) {
263 		return;
264 	}
265 
266 	if (pid == 0) {
267 		return;
268 	}
269 
270 	for (proc = run_ctx->plist; proc != NULL; proc = proc->next) {
271 		if (proc->pid == pid) {
272 			break;
273 		}
274 	}
275 
276 	if (proc == NULL) {
277 		/* unknown process */
278 		goto again;
279 	}
280 
281 	/* Mark the process as terminated */
282 	proc->pid = -1;
283 
284 	/* Update process status */
285 	if (WIFEXITED(status)) {
286 		int pstatus = WEXITSTATUS(status);
287 		if (WIFSIGNALED(status)) {
288 			proc->result.sig = WTERMSIG(status);
289 		} else if (pstatus >= 64 && pstatus < 255) {
290 			proc->result.err = pstatus-64;
291 		} else {
292 			proc->result.status = pstatus;
293 		}
294 	} else if (WIFSIGNALED(status)) {
295 		proc->result.sig = WTERMSIG(status);
296 	}
297 
298 	/* Confirm that all data has been read from the pipe */
299 	if (proc->fd != -1) {
300 		proc_read_handler(ev, proc->fde, 0, proc);
301 		TALLOC_FREE(proc->fde);
302 		proc->fd = -1;
303 	}
304 
305 	DLIST_REMOVE(run_ctx->plist, proc);
306 
307 	/* Active run_proc request */
308 	if (proc->req != NULL) {
309 		run_proc_done(proc->req);
310 	} else {
311 		talloc_free(proc);
312 	}
313 
314 	goto again;
315 }
316 
317 static int run_proc_context_destructor(struct run_proc_context *run_ctx)
318 {
319 	struct proc_context *proc;
320 
321 	/* Get rid of signal handler */
322 	TALLOC_FREE(run_ctx->se);
323 
324 	/* Kill any pending processes */
325 	while ((proc = run_ctx->plist) != NULL) {
326 		DLIST_REMOVE(run_ctx->plist, proc);
327 		talloc_free(proc);
328 	}
329 
330 	return 0;
331 }
332 
333 struct run_proc_state {
334 	struct tevent_context *ev;
335 	struct run_proc_context *run_ctx;
336 	struct proc_context *proc;
337 
338 	struct run_proc_result result;
339 	char *output;
340 	pid_t pid;
341 };
342 
343 static int run_proc_state_destructor(struct run_proc_state *state);
344 static void run_proc_timedout(struct tevent_req *subreq);
345 
346 struct tevent_req *run_proc_send(TALLOC_CTX *mem_ctx,
347 				 struct tevent_context *ev,
348 				 struct run_proc_context *run_ctx,
349 				 const char *path, const char **argv,
350 				 int stdin_fd, struct timeval timeout)
351 {
352 	struct tevent_req *req;
353 	struct run_proc_state *state;
354 	struct stat st;
355 	int ret;
356 
357 	req = tevent_req_create(mem_ctx, &state, struct run_proc_state);
358 	if (req == NULL) {
359 		return NULL;
360 	}
361 
362 	state->ev = ev;
363 	state->run_ctx = run_ctx;
364 	state->pid = -1;
365 
366 	ret = stat(path, &st);
367 	if (ret != 0) {
368 		state->result.err = errno;
369 		tevent_req_done(req);
370 		return tevent_req_post(req, ev);
371 	}
372 
373 	if (! (st.st_mode & S_IXUSR)) {
374 		state->result.err = EACCES;
375 		tevent_req_done(req);
376 		return tevent_req_post(req, ev);
377 	}
378 
379 	state->proc = proc_new(run_ctx, run_ctx);
380 	if (tevent_req_nomem(state->proc, req)) {
381 		return tevent_req_post(req, ev);
382 	}
383 
384 	state->proc->req = req;
385 	DLIST_ADD(run_ctx->plist, state->proc);
386 
387 	ret = proc_start(state->proc, ev, path, argv, stdin_fd);
388 	if (ret != 0) {
389 		tevent_req_error(req, ret);
390 		return tevent_req_post(req, ev);
391 	}
392 
393 	talloc_set_destructor(state, run_proc_state_destructor);
394 
395 	if (! tevent_timeval_is_zero(&timeout)) {
396 		struct tevent_req *subreq;
397 
398 		subreq = tevent_wakeup_send(state, ev, timeout);
399 		if (tevent_req_nomem(subreq, req)) {
400 			return tevent_req_post(req, ev);
401 		}
402 		tevent_req_set_callback(subreq, run_proc_timedout, req);
403 	}
404 
405 	return req;
406 }
407 
408 static int run_proc_state_destructor(struct run_proc_state *state)
409 {
410 	/* Do not get rid of the child process if timeout has occurred */
411 	if (state->proc->req != NULL) {
412 		state->proc->req = NULL;
413 		DLIST_REMOVE(state->run_ctx->plist, state->proc);
414 		talloc_free(state->proc);
415 	}
416 
417 	return 0;
418 }
419 
420 static void run_proc_done(struct tevent_req *req)
421 {
422 	struct run_proc_state *state = tevent_req_data(
423 		req, struct run_proc_state);
424 
425 	state->proc->req = NULL;
426 
427 	state->result = state->proc->result;
428 	if (state->proc->output != NULL) {
429 		state->output = talloc_steal(state, state->proc->output);
430 	}
431 	talloc_steal(state, state->proc);
432 
433 	tevent_req_done(req);
434 }
435 
436 static void run_proc_kill(struct tevent_req *req)
437 {
438 	struct run_proc_state *state = tevent_req_data(
439 		req, struct run_proc_state);
440 
441 	state->proc->req = NULL;
442 
443 	state->result.sig = SIGKILL;
444 
445 	tevent_req_done(req);
446 }
447 
448 static void run_proc_timedout(struct tevent_req *subreq)
449 {
450 	struct tevent_req *req = tevent_req_callback_data(
451 		subreq, struct tevent_req);
452 	struct run_proc_state *state = tevent_req_data(
453 		req, struct run_proc_state);
454 	bool status;
455 
456 	state->proc->req = NULL;
457 
458 	status = tevent_wakeup_recv(subreq);
459 	TALLOC_FREE(subreq);
460 	if (! status) {
461 		tevent_req_error(req, EIO);
462 		return;
463 	}
464 
465 	state->result.err = ETIMEDOUT;
466 	if (state->proc->output != NULL) {
467 		state->output = talloc_steal(state, state->proc->output);
468 	}
469 	state->pid = state->proc->pid;
470 
471 	tevent_req_done(req);
472 }
473 
474 bool run_proc_recv(struct tevent_req *req, int *perr,
475 		   struct run_proc_result *result, pid_t *pid,
476 		   TALLOC_CTX *mem_ctx, char **output)
477 {
478 	struct run_proc_state *state = tevent_req_data(
479 		req, struct run_proc_state);
480 	int ret;
481 
482 	if (tevent_req_is_unix_error(req, &ret)) {
483 		if (perr != NULL) {
484 			*perr = ret;
485 		}
486 		return false;
487 	}
488 
489 	if (result != NULL) {
490 		*result = state->result;
491 	}
492 
493 	if (pid != NULL) {
494 		*pid = state->pid;
495 	}
496 
497 	if (output != NULL) {
498 		*output = talloc_steal(mem_ctx, state->output);
499 	}
500 
501 	return true;
502 }
503