Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/src/exec_monitor.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2009-2024 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <sys/types.h>
22
#include <sys/socket.h>
23
#include <sys/wait.h>
24
#include <sys/ioctl.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <unistd.h>
29
#include <time.h>
30
#include <errno.h>
31
#include <fcntl.h>
32
#include <signal.h>
33
34
#include <sudo.h>
35
#include <sudo_exec.h>
36
#include <sudo_plugin.h>
37
#include <sudo_plugin_int.h>
38
39
struct monitor_closure {
40
const struct command_details *details;
41
struct sudo_event_base *evbase;
42
struct sudo_event *errsock_event;
43
struct sudo_event *backchannel_event;
44
struct sudo_event *sigint_event;
45
struct sudo_event *sigquit_event;
46
struct sudo_event *sigtstp_event;
47
struct sudo_event *sigterm_event;
48
struct sudo_event *sighup_event;
49
struct sudo_event *sigusr1_event;
50
struct sudo_event *sigusr2_event;
51
struct sudo_event *sigchld_event;
52
struct command_status *cstat;
53
pid_t cmnd_pid;
54
pid_t cmnd_pgrp;
55
pid_t mon_pgrp;
56
int backchannel;
57
};
58
59
/*
60
* Deliver a signal to the running command.
61
* The signal was either forwarded to us by the parent sudo process
62
* or was received by the monitor itself.
63
*
64
* There are two "special" signals, SIGCONT_FG and SIGCONT_BG that
65
* also specify whether the command should have the controlling tty.
66
*/
67
static void
68
deliver_signal(struct monitor_closure *mc, int signo, bool from_parent)
69
{
70
debug_decl(deliver_signal, SUDO_DEBUG_EXEC);
71
72
/* Avoid killing more than a single process or process group. */
73
if (mc->cmnd_pid <= 0)
74
debug_return;
75
76
if (sudo_debug_needed(SUDO_DEBUG_INFO)) {
77
char signame[SIG2STR_MAX];
78
if (signo == SIGCONT_FG)
79
(void)strlcpy(signame, "CONT_FG", sizeof(signame));
80
else if (signo == SIGCONT_BG)
81
(void)strlcpy(signame, "CONT_BG", sizeof(signame));
82
else if (sig2str(signo, signame) == -1)
83
(void)snprintf(signame, sizeof(signame), "%d", signo);
84
sudo_debug_printf(SUDO_DEBUG_INFO, "received SIG%s%s",
85
signame, from_parent ? " from parent" : "");
86
}
87
88
/* Handle signal from parent or monitor. */
89
switch (signo) {
90
case SIGALRM:
91
terminate_command(mc->cmnd_pid, true);
92
break;
93
case SIGCONT_FG:
94
/* Continue in foreground, grant it controlling tty. */
95
if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc->cmnd_pgrp) == -1) {
96
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
97
"%s: unable to set foreground pgrp to %d (command)",
98
__func__, (int)mc->cmnd_pgrp);
99
}
100
killpg(mc->cmnd_pid, SIGCONT);
101
break;
102
case SIGCONT_BG:
103
/* Continue in background, I take controlling tty. */
104
if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc->mon_pgrp) == -1) {
105
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
106
"%s: unable to set foreground pgrp to %d (monitor)",
107
__func__, (int)mc->mon_pgrp);
108
}
109
killpg(mc->cmnd_pid, SIGCONT);
110
break;
111
case SIGKILL:
112
_exit(EXIT_FAILURE); /* XXX */
113
/* NOTREACHED */
114
default:
115
/* Relay signal to command. */
116
sudo_debug_printf(SUDO_DEBUG_NOTICE, "%s: killpg(%d, %d)",
117
__func__, (int)mc->cmnd_pid, signo);
118
killpg(mc->cmnd_pid, signo);
119
break;
120
}
121
debug_return;
122
}
123
124
/*
125
* Send status to parent over socketpair.
126
* Return value is the same as send(2).
127
*/
128
static ssize_t
129
send_status(int fd, struct command_status *cstat)
130
{
131
ssize_t n = -1;
132
debug_decl(send_status, SUDO_DEBUG_EXEC);
133
134
if (cstat->type != CMD_INVALID) {
135
sudo_debug_printf(SUDO_DEBUG_INFO,
136
"sending status message to parent: [%d, %d]",
137
cstat->type, cstat->val);
138
n = send(fd, cstat, sizeof(*cstat), 0);
139
if (n != ssizeof(*cstat)) {
140
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
141
"%s: unable to send status to parent", __func__);
142
}
143
cstat->type = CMD_INVALID; /* prevent re-sending */
144
}
145
debug_return_ssize_t(n);
146
}
147
148
/*
149
* Wait for command status after receiving SIGCHLD.
150
* If the command was stopped, the status is sent back to the parent.
151
* Otherwise, cstat is filled in but not sent.
152
*/
153
static void
154
mon_handle_sigchld(struct monitor_closure *mc)
155
{
156
char signame[SIG2STR_MAX];
157
int status;
158
pid_t pid;
159
debug_decl(mon_handle_sigchld, SUDO_DEBUG_EXEC);
160
161
/* Read command status. */
162
do {
163
pid = waitpid(mc->cmnd_pid, &status, WUNTRACED|WNOHANG);
164
} while (pid == -1 && errno == EINTR);
165
switch (pid) {
166
case -1:
167
if (errno != ECHILD) {
168
sudo_warn(U_("%s: %s"), __func__, "waitpid");
169
debug_return;
170
}
171
FALLTHROUGH;
172
case 0:
173
/* Nothing to wait for. */
174
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no process to wait for",
175
__func__);
176
debug_return;
177
}
178
179
if (WIFSTOPPED(status)) {
180
if (sig2str(WSTOPSIG(status), signame) == -1)
181
(void)snprintf(signame, sizeof(signame), "%d", WSTOPSIG(status));
182
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) stopped, SIG%s",
183
__func__, (int)mc->cmnd_pid, signame);
184
} else if (WIFSIGNALED(status)) {
185
if (sig2str(WTERMSIG(status), signame) == -1)
186
(void)snprintf(signame, sizeof(signame), "%d", WTERMSIG(status));
187
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) killed, SIG%s",
188
__func__, (int)mc->cmnd_pid, signame);
189
mc->cmnd_pid = -1;
190
} else if (WIFEXITED(status)) {
191
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: command (%d) exited: %d",
192
__func__, (int)mc->cmnd_pid, WEXITSTATUS(status));
193
mc->cmnd_pid = -1;
194
} else {
195
sudo_debug_printf(SUDO_DEBUG_WARN,
196
"%s: unexpected wait status 0x%x for command (%d)",
197
__func__, status, (int)mc->cmnd_pid);
198
}
199
200
/* Don't overwrite execve() failure with child exit status. */
201
if (mc->cstat->type == CMD_INVALID) {
202
/*
203
* Store wait status in cstat and forward to parent if stopped.
204
*/
205
mc->cstat->type = CMD_WSTATUS;
206
mc->cstat->val = status;
207
if (WIFSTOPPED(status)) {
208
/* Save the foreground pgid so we can restore it later. */
209
pid = tcgetpgrp(io_fds[SFD_FOLLOWER]);
210
if (pid != mc->mon_pgrp)
211
mc->cmnd_pgrp = pid;
212
send_status(mc->backchannel, mc->cstat);
213
}
214
} else {
215
sudo_debug_printf(SUDO_DEBUG_WARN,
216
"%s: not overwriting command status %d,%d with %d,%d",
217
__func__, mc->cstat->type, mc->cstat->val, CMD_WSTATUS, status);
218
}
219
220
debug_return;
221
}
222
223
static void
224
mon_signal_cb(int signo, int what, void *v)
225
{
226
struct sudo_ev_siginfo_container *sc = v;
227
struct monitor_closure *mc = sc->closure;
228
debug_decl(mon_signal_cb, SUDO_DEBUG_EXEC);
229
230
/*
231
* Handle SIGCHLD specially and deliver other signals
232
* directly to the command.
233
*/
234
if (signo == SIGCHLD) {
235
mon_handle_sigchld(mc);
236
if (mc->cmnd_pid == -1) {
237
/* Command exited or was killed, exit event loop. */
238
sudo_ev_loopexit(mc->evbase);
239
}
240
} else {
241
/*
242
* If the signal came from the process group of the command we ran,
243
* do not forward it as we don't want the child to indirectly kill
244
* itself. This can happen with, e.g., BSD-derived versions of
245
* reboot that call kill(-1, SIGTERM) to kill all other processes.
246
*/
247
if (USER_SIGNALED(sc->siginfo) && sc->siginfo->si_pid != 0) {
248
pid_t si_pgrp;
249
250
if (sc->siginfo->si_pid == mc->cmnd_pid)
251
debug_return;
252
si_pgrp = getpgid(sc->siginfo->si_pid);
253
if (si_pgrp != -1) {
254
if (si_pgrp == mc->cmnd_pgrp)
255
debug_return;
256
}
257
}
258
deliver_signal(mc, signo, false);
259
}
260
debug_return;
261
}
262
263
/* This is essentially the same as errpipe_cb() in exec_nopty.c */
264
static void
265
mon_errsock_cb(int fd, int what, void *v)
266
{
267
struct monitor_closure *mc = v;
268
ssize_t nread;
269
int errval;
270
debug_decl(mon_errsock_cb, SUDO_DEBUG_EXEC);
271
272
/*
273
* Read errno from child or EOF when command is executed.
274
* Note that the error socket is *blocking*.
275
*/
276
nread = read(fd, &errval, sizeof(errval));
277
if (nread < 0) {
278
if (errno != EAGAIN && errno != EINTR) {
279
if (mc->cstat->val == CMD_INVALID) {
280
/* XXX - need a way to distinguish non-exec error. */
281
mc->cstat->type = CMD_ERRNO;
282
mc->cstat->val = errno;
283
}
284
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
285
"%s: failed to read error socket", __func__);
286
sudo_ev_loopbreak(mc->evbase);
287
}
288
debug_return;
289
}
290
291
if (nread == 0) {
292
/* The error socket closes when the command is executed. */
293
sudo_debug_printf(SUDO_DEBUG_INFO, "EOF on error socket");
294
} else {
295
/* Errno value when child is unable to execute command. */
296
sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
297
strerror(errval));
298
mc->cstat->type = CMD_ERRNO;
299
mc->cstat->val = errval;
300
}
301
sudo_ev_del(mc->evbase, mc->errsock_event);
302
close(fd);
303
304
debug_return;
305
}
306
307
static void
308
mon_backchannel_cb(int fd, int what, void *v)
309
{
310
struct monitor_closure *mc = v;
311
struct command_status cstmp;
312
ssize_t n;
313
debug_decl(mon_backchannel_cb, SUDO_DEBUG_EXEC);
314
315
/*
316
* Read command from backchannel, should be a signal.
317
* Note that the backchannel is a *blocking* socket.
318
*/
319
n = recv(fd, &cstmp, sizeof(cstmp), MSG_WAITALL);
320
if (n != ssizeof(cstmp)) {
321
if (n == -1) {
322
if (errno == EINTR || errno == EAGAIN)
323
debug_return;
324
sudo_warn("%s", U_("error reading from socketpair"));
325
} else {
326
/* short read or EOF, parent process died? */
327
}
328
/* XXX - need a way to distinguish non-exec error. */
329
mc->cstat->type = CMD_ERRNO;
330
mc->cstat->val = n ? EIO : ECONNRESET;
331
sudo_ev_loopbreak(mc->evbase);
332
} else {
333
if (cstmp.type == CMD_SIGNO) {
334
deliver_signal(mc, cstmp.val, true);
335
} else {
336
sudo_warnx(U_("unexpected reply type on backchannel: %d"),
337
cstmp.type);
338
}
339
}
340
debug_return;
341
}
342
343
/*
344
* Sets up std{in,out,err} and executes the actual command.
345
* Returns only if execve() fails.
346
*/
347
static void
348
exec_cmnd_pty(struct command_details *details, sigset_t *mask,
349
bool foreground, int intercept_fd, int errfd)
350
{
351
volatile pid_t self = getpid();
352
debug_decl(exec_cmnd_pty, SUDO_DEBUG_EXEC);
353
354
/* Set command process group here too to avoid a race. */
355
setpgid(0, self);
356
357
/* Wire up standard fds, note that stdout/stderr may be pipes. */
358
if (dup3(io_fds[SFD_STDIN], STDIN_FILENO, 0) == -1)
359
sudo_fatal("dup3");
360
if (io_fds[SFD_STDIN] != io_fds[SFD_FOLLOWER])
361
close(io_fds[SFD_STDIN]);
362
if (dup3(io_fds[SFD_STDOUT], STDOUT_FILENO, 0) == -1)
363
sudo_fatal("dup3");
364
if (io_fds[SFD_STDOUT] != io_fds[SFD_FOLLOWER])
365
close(io_fds[SFD_STDOUT]);
366
if (dup3(io_fds[SFD_STDERR], STDERR_FILENO, 0) == -1)
367
sudo_fatal("dup3");
368
if (io_fds[SFD_STDERR] != io_fds[SFD_FOLLOWER])
369
close(io_fds[SFD_STDERR]);
370
371
/* Wait for parent to grant us the tty if we are foreground. */
372
if (foreground) {
373
char ch;
374
375
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: waiting for controlling tty",
376
__func__);
377
if (recv(errfd, &ch, sizeof(ch), 0) == -1) {
378
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
379
"%s: unable to receive message from parent", __func__);
380
debug_return;
381
}
382
if (tcgetpgrp(io_fds[SFD_FOLLOWER]) == self) {
383
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: got controlling tty",
384
__func__);
385
} else {
386
sudo_debug_printf(SUDO_DEBUG_ERROR,
387
"%s: unable to get controlling tty", __func__);
388
foreground = false;
389
}
390
}
391
392
/* Done with the pty follower, don't leak it. */
393
if (io_fds[SFD_FOLLOWER] != -1)
394
close(io_fds[SFD_FOLLOWER]);
395
396
/* Execute command; only returns on error. */
397
sudo_debug_printf(SUDO_DEBUG_INFO, "executing %s in the %s",
398
details->command, foreground ? "foreground" : "background");
399
exec_cmnd(details, mask, intercept_fd, errfd);
400
401
debug_return;
402
}
403
404
/*
405
* Fill in the non-event part of the monitor closure.
406
*/
407
static void
408
init_exec_closure_monitor(struct monitor_closure *mc,
409
const struct command_details *details, struct command_status *cstat,
410
int backchannel)
411
{
412
debug_decl(init_exec_closure_monitor, SUDO_DEBUG_EXEC);
413
414
/* Fill in the non-event part of the closure. */
415
memset(mc, 0, sizeof(*mc));
416
mc->details = details;
417
mc->cstat = cstat;
418
mc->backchannel = backchannel;
419
mc->mon_pgrp = getpgrp();
420
421
debug_return;
422
}
423
424
/*
425
* Fill in the monitor closure and setup initial events.
426
* Allocates read events for the signal pipe, error pipe and backchannel.
427
*/
428
static void
429
init_exec_events_monitor(struct monitor_closure *mc, int errfd)
430
{
431
debug_decl(init_exec_events_monitor, SUDO_DEBUG_EXEC);
432
433
/* Setup event base and events. */
434
mc->evbase = sudo_ev_base_alloc();
435
if (mc->evbase == NULL)
436
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
437
438
/* Event for command status via errfd. */
439
mc->errsock_event = sudo_ev_alloc(errfd,
440
SUDO_EV_READ|SUDO_EV_PERSIST, mon_errsock_cb, mc);
441
if (mc->errsock_event == NULL)
442
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
443
if (sudo_ev_add(mc->evbase, mc->errsock_event, NULL, false) == -1)
444
sudo_fatal("%s", U_("unable to add event to queue"));
445
446
/* Event for forwarded signals via backchannel. */
447
mc->backchannel_event = sudo_ev_alloc(mc->backchannel,
448
SUDO_EV_READ|SUDO_EV_PERSIST, mon_backchannel_cb, mc);
449
if (mc->backchannel_event == NULL)
450
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
451
if (sudo_ev_add(mc->evbase, mc->backchannel_event, NULL, false) == -1)
452
sudo_fatal("%s", U_("unable to add event to queue"));
453
454
/* Events for local signals. */
455
mc->sigint_event = sudo_ev_alloc(SIGINT,
456
SUDO_EV_SIGINFO, mon_signal_cb, mc);
457
if (mc->sigint_event == NULL)
458
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
459
if (sudo_ev_add(mc->evbase, mc->sigint_event, NULL, false) == -1)
460
sudo_fatal("%s", U_("unable to add event to queue"));
461
462
mc->sigquit_event = sudo_ev_alloc(SIGQUIT,
463
SUDO_EV_SIGINFO, mon_signal_cb, mc);
464
if (mc->sigquit_event == NULL)
465
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
466
if (sudo_ev_add(mc->evbase, mc->sigquit_event, NULL, false) == -1)
467
sudo_fatal("%s", U_("unable to add event to queue"));
468
469
mc->sigtstp_event = sudo_ev_alloc(SIGTSTP,
470
SUDO_EV_SIGINFO, mon_signal_cb, mc);
471
if (mc->sigtstp_event == NULL)
472
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
473
if (sudo_ev_add(mc->evbase, mc->sigtstp_event, NULL, false) == -1)
474
sudo_fatal("%s", U_("unable to add event to queue"));
475
476
mc->sigterm_event = sudo_ev_alloc(SIGTERM,
477
SUDO_EV_SIGINFO, mon_signal_cb, mc);
478
if (mc->sigterm_event == NULL)
479
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
480
if (sudo_ev_add(mc->evbase, mc->sigterm_event, NULL, false) == -1)
481
sudo_fatal("%s", U_("unable to add event to queue"));
482
483
mc->sighup_event = sudo_ev_alloc(SIGHUP,
484
SUDO_EV_SIGINFO, mon_signal_cb, mc);
485
if (mc->sighup_event == NULL)
486
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
487
if (sudo_ev_add(mc->evbase, mc->sighup_event, NULL, false) == -1)
488
sudo_fatal("%s", U_("unable to add event to queue"));
489
490
mc->sigusr1_event = sudo_ev_alloc(SIGUSR1,
491
SUDO_EV_SIGINFO, mon_signal_cb, mc);
492
if (mc->sigusr1_event == NULL)
493
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
494
if (sudo_ev_add(mc->evbase, mc->sigusr1_event, NULL, false) == -1)
495
sudo_fatal("%s", U_("unable to add event to queue"));
496
497
mc->sigusr2_event = sudo_ev_alloc(SIGUSR2,
498
SUDO_EV_SIGINFO, mon_signal_cb, mc);
499
if (mc->sigusr2_event == NULL)
500
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
501
if (sudo_ev_add(mc->evbase, mc->sigusr2_event, NULL, false) == -1)
502
sudo_fatal("%s", U_("unable to add event to queue"));
503
504
mc->sigchld_event = sudo_ev_alloc(SIGCHLD,
505
SUDO_EV_SIGINFO, mon_signal_cb, mc);
506
if (mc->sigchld_event == NULL)
507
sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
508
if (sudo_ev_add(mc->evbase, mc->sigchld_event, NULL, false) == -1)
509
sudo_fatal("%s", U_("unable to add event to queue"));
510
511
/* Clear the default event base. */
512
sudo_ev_base_setdef(NULL);
513
514
debug_return;
515
}
516
517
/*
518
* Make the tty follower the controlling tty.
519
*/
520
static bool
521
pty_make_controlling(const char *follower)
522
{
523
debug_decl(pty_make_controlling, SUDO_DEBUG_EXEC);
524
525
if (io_fds[SFD_FOLLOWER] != -1) {
526
#ifdef TIOCSCTTY
527
if (ioctl(io_fds[SFD_FOLLOWER], TIOCSCTTY, NULL) != 0)
528
debug_return_bool(false);
529
#else
530
/* Set controlling tty by reopening pty follower. */
531
int fd = open(follower, O_RDWR);
532
if (fd == -1)
533
debug_return_bool(false);
534
close(fd);
535
#endif
536
}
537
debug_return_bool(true);
538
}
539
540
/*
541
* Monitor process that creates a new session with the controlling tty,
542
* resets signal handlers and forks a child to call exec_cmnd_pty().
543
* Waits for status changes from the command and relays them to the
544
* parent and relays signals from the parent to the command.
545
* Must be called with signals blocked and the old signal mask in oset.
546
* Returns an error if fork(2) fails, else calls _exit(2).
547
*/
548
int
549
exec_monitor(struct command_details *details, sigset_t *oset,
550
bool foreground, int backchannel, int intercept_fd)
551
{
552
struct monitor_closure mc;
553
struct command_status cstat;
554
struct sigaction sa;
555
int errsock[2];
556
debug_decl(exec_monitor, SUDO_DEBUG_EXEC);
557
558
/* Close fds the monitor doesn't use. */
559
if (io_fds[SFD_LEADER] != -1)
560
close(io_fds[SFD_LEADER]);
561
if (io_fds[SFD_USERTTY] != -1)
562
close(io_fds[SFD_USERTTY]);
563
564
/* Ignore any SIGTTIN or SIGTTOU we receive (shouldn't be possible). */
565
memset(&sa, 0, sizeof(sa));
566
sigemptyset(&sa.sa_mask);
567
sa.sa_flags = SA_RESTART;
568
sa.sa_handler = SIG_IGN;
569
if (sudo_sigaction(SIGTTIN, &sa, NULL) != 0)
570
sudo_warn(U_("unable to set handler for signal %d"), SIGTTIN);
571
if (sudo_sigaction(SIGTTOU, &sa, NULL) != 0)
572
sudo_warn(U_("unable to set handler for signal %d"), SIGTTOU);
573
574
/*
575
* Start a new session with the parent as the session leader
576
* and the follower device as the controlling terminal.
577
* This allows us to be notified when the command has been suspended.
578
*/
579
if (setsid() == -1) {
580
sudo_warn("setsid");
581
goto bad;
582
}
583
if (!pty_make_controlling(details->tty)) {
584
sudo_warn("%s", U_("unable to set controlling tty"));
585
goto bad;
586
}
587
588
/* Fill in exec closure after creating a new session. */
589
init_exec_closure_monitor(&mc, details, &cstat, backchannel);
590
591
/*
592
* The child waits on the other end of a socketpair for the
593
* parent to set the controlling terminal. It also writes
594
* error to the socket on execve(2) failure.
595
*/
596
if (socketpair(PF_UNIX, SOCK_STREAM, 0, errsock) == -1 ||
597
fcntl(errsock[0], F_SETFD, FD_CLOEXEC) == -1 ||
598
fcntl(errsock[1], F_SETFD, FD_CLOEXEC) == -1) {
599
sudo_warn("%s", U_("unable to create sockets"));
600
goto bad;
601
}
602
603
/*
604
* Before forking, wait for the main sudo process to tell us to go.
605
* Avoids race conditions when the command exits quickly.
606
*/
607
if (recv(backchannel, &cstat, sizeof(cstat), MSG_WAITALL) == -1) {
608
sudo_warn("%s", U_("unable to receive message from parent"));
609
goto bad;
610
}
611
612
#ifdef HAVE_SELINUX
613
if (ISSET(details->flags, CD_RBAC_ENABLED)) {
614
if (selinux_relabel_tty(details->tty, io_fds[SFD_FOLLOWER]) == -1)
615
goto bad;
616
selinux_audit_role_change();
617
}
618
#endif
619
620
mc.cmnd_pid = sudo_debug_fork();
621
switch (mc.cmnd_pid) {
622
case -1:
623
sudo_warn("%s", U_("unable to fork"));
624
#ifdef HAVE_SELINUX
625
if (ISSET(details->flags, CD_RBAC_ENABLED)) {
626
if (selinux_restore_tty() != 0)
627
sudo_warnx("%s", U_("unable to restore tty label"));
628
}
629
#endif
630
goto bad;
631
case 0:
632
/* child */
633
close(backchannel);
634
close(errsock[0]);
635
/* setup tty and exec command */
636
exec_cmnd_pty(details, oset, foreground, intercept_fd, errsock[1]);
637
if (send(errsock[1], &errno, sizeof(int), 0) == -1)
638
sudo_warn(U_("unable to execute %s"), details->command);
639
_exit(EXIT_FAILURE);
640
/* NOTREACHED */
641
}
642
close(errsock[1]);
643
if (intercept_fd != -1)
644
close(intercept_fd);
645
646
/* No longer need execfd. */
647
if (details->execfd != -1) {
648
close(details->execfd);
649
details->execfd = -1;
650
}
651
652
/* Send the command's pid to main sudo process. */
653
cstat.type = CMD_PID;
654
cstat.val = mc.cmnd_pid;
655
send_status(backchannel, &cstat);
656
657
/*
658
* Create new event base and register read events for the
659
* signal pipe, error pipe, and backchannel.
660
*/
661
init_exec_events_monitor(&mc, errsock[0]);
662
663
/* Restore signal mask now that signal handlers are setup. */
664
sigprocmask(SIG_SETMASK, oset, NULL);
665
666
/* If any of stdin/stdout/stderr are pipes, close them in parent. */
667
if (io_fds[SFD_STDIN] != io_fds[SFD_FOLLOWER])
668
close(io_fds[SFD_STDIN]);
669
if (io_fds[SFD_STDOUT] != io_fds[SFD_FOLLOWER])
670
close(io_fds[SFD_STDOUT]);
671
if (io_fds[SFD_STDERR] != io_fds[SFD_FOLLOWER])
672
close(io_fds[SFD_STDERR]);
673
674
/* Put command in its own process group. */
675
mc.cmnd_pgrp = mc.cmnd_pid;
676
setpgid(mc.cmnd_pid, mc.cmnd_pgrp);
677
678
/* Make the command the foreground process for the pty follower. */
679
if (foreground) {
680
if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc.cmnd_pgrp) == -1) {
681
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
682
"%s: unable to set foreground pgrp to %d (command)",
683
__func__, (int)mc.cmnd_pgrp);
684
}
685
/* Tell the child to go ahead now that it is the foreground pgrp. */
686
if (send(errsock[0], "", 1, 0) == -1) {
687
sudo_warn(U_("unable to execute %s"), details->command);
688
terminate_command(mc.cmnd_pid, true);
689
}
690
}
691
692
/*
693
* Wait for errno on pipe, signal on backchannel or for SIGCHLD.
694
* The event loop ends when the child is no longer running and
695
* the error pipe is closed.
696
*/
697
cstat.type = CMD_INVALID;
698
cstat.val = 0;
699
(void) sudo_ev_dispatch(mc.evbase);
700
if (mc.cmnd_pid != -1) {
701
pid_t pid;
702
703
/* Command still running, did the parent die? */
704
sudo_debug_printf(SUDO_DEBUG_ERROR,
705
"Command still running after event loop exit, terminating");
706
terminate_command(mc.cmnd_pid, true);
707
do {
708
pid = waitpid(mc.cmnd_pid, NULL, 0);
709
} while (pid == -1 && errno == EINTR);
710
/* XXX - update cstat with wait status? */
711
}
712
713
/*
714
* Take the controlling tty. This prevents processes spawned by the
715
* command from receiving SIGHUP when the session leader (us) exits.
716
*/
717
if (tcsetpgrp(io_fds[SFD_FOLLOWER], mc.mon_pgrp) == -1) {
718
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
719
"%s: unable to set foreground pgrp to %d (monitor)",
720
__func__, (int)mc.mon_pgrp);
721
}
722
723
/* Send parent status. */
724
send_status(backchannel, &cstat);
725
726
#ifdef HAVE_SELINUX
727
if (ISSET(details->flags, CD_RBAC_ENABLED)) {
728
if (selinux_restore_tty() != 0)
729
sudo_warnx("%s", U_("unable to restore tty label"));
730
}
731
#endif
732
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
733
_exit(EXIT_FAILURE);
734
/* NOTREACHED */
735
736
bad:
737
debug_return_int(-1);
738
}
739
740