784f90ab40ff80020dc18f2ea12105076042b5c9
[debian/sudo] / exec.c
1 /*
2  * Copyright (c) 2009-2010 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <sys/wait.h>
25 #ifdef HAVE_TERMIOS_H
26 # include <termios.h>
27 #else
28 # include <termio.h>
29 #endif /* HAVE_TERMIOS_H */
30 #include <sys/ioctl.h>
31 #ifdef HAVE_SYS_SELECT_H
32 # include <sys/select.h>
33 #endif /* HAVE_SYS_SELECT_H */
34 #include <stdio.h>
35 #ifdef STDC_HEADERS
36 # include <stdlib.h>
37 # include <stddef.h>
38 #else
39 # ifdef HAVE_STDLIB_H
40 #  include <stdlib.h>
41 # endif
42 #endif /* STDC_HEADERS */
43 #ifdef HAVE_STRING_H
44 # include <string.h>
45 #endif /* HAVE_STRING_H */
46 #ifdef HAVE_STRINGS_H
47 # include <strings.h>
48 #endif /* HAVE_STRINGS_H */
49 #ifdef HAVE_UNISTD_H
50 # include <unistd.h>
51 #endif /* HAVE_UNISTD_H */
52 #if TIME_WITH_SYS_TIME
53 # include <time.h>
54 #endif
55 #ifdef HAVE_SETLOCALE
56 # include <locale.h>
57 #endif
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <signal.h>
61 #ifdef HAVE_SELINUX
62 # include <selinux/selinux.h>
63 #endif
64
65 #include "sudo.h"
66 #include "sudo_exec.h"
67
68 /* shared with exec_pty.c */
69 sig_atomic_t recvsig[NSIG];
70 void handler __P((int s));
71
72 /*
73  * Like execve(2) but falls back to running through /bin/sh
74  * ala execvp(3) if we get ENOEXEC.
75  */
76 int
77 my_execve(path, argv, envp)
78     const char *path;
79     char *argv[];
80     char *envp[];
81 {
82     execve(path, argv, envp);
83     if (errno == ENOEXEC) {
84         argv--;                 /* at least one extra slot... */
85         argv[0] = "sh";
86         argv[1] = (char *)path;
87         execve(_PATH_BSHELL, argv, envp);
88     }
89     return -1;
90 }
91
92 /*
93  * Fork and execute a command, returns the child's pid.
94  * Sends errno back on sv[1] if execve() fails.
95  */
96 static int fork_cmnd(path, argv, envp, sv, rbac_enabled)
97     const char *path;
98     char *argv[];
99     char *envp[];
100     int sv[2];
101     int rbac_enabled;
102 {
103     struct command_status cstat;
104     sigaction_t sa;
105     int pid;
106
107     zero_bytes(&sa, sizeof(sa));
108     sigemptyset(&sa.sa_mask);
109     sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
110     sa.sa_handler = handler;
111     sigaction(SIGCONT, &sa, NULL);
112
113     pid = fork();
114     switch (pid) {
115     case -1:
116         error(1, "fork");
117         break;
118     case 0:
119         /* child */
120         close(sv[0]);
121         fcntl(sv[1], F_SETFD, FD_CLOEXEC);
122         if (exec_setup(rbac_enabled, user_ttypath, -1) == TRUE) {
123             /* headed for execve() */
124             closefrom(def_closefrom);
125 #ifdef HAVE_SELINUX
126             if (rbac_enabled)
127                 selinux_execve(path, argv, envp);
128             else
129 #endif
130                 my_execve(path, argv, envp);
131         }
132         cstat.type = CMD_ERRNO;
133         cstat.val = errno;
134         send(sv[1], &cstat, sizeof(cstat), 0);
135         _exit(1);
136     }
137     return pid;
138 }
139
140 /*
141  * Execute a command, potentially in a pty with I/O loggging.
142  * This is a little bit tricky due to how POSIX job control works and
143  * we fact that we have two different controlling terminals to deal with.
144  */
145 int
146 sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode)
147     const char *path;
148     char *argv[];
149     char *envp[];
150     uid_t uid;
151     struct command_status *cstat;
152     int dowait;
153     int bgmode;
154 {
155     sigaction_t sa;
156     fd_set *fdsr, *fdsw;
157     int maxfd, n, nready, status, sv[2];
158     int rbac_enabled = 0;
159     int log_io;
160     pid_t child;
161
162     /* If running in background mode, fork and exit. */
163     if (bgmode) {
164         switch (fork()) {
165             case -1:
166                 cstat->type = CMD_ERRNO;
167                 cstat->val = errno;
168                 return -1;
169             case 0:
170                 /* child continues */   
171                 break;
172             default:
173                 /* parent exits */
174                 exit(0);
175         }
176     }
177
178 #ifdef _PATH_SUDO_IO_LOGDIR
179     log_io = def_log_output || def_log_input || def_use_pty;
180     if (log_io) {
181         if (!bgmode)
182             pty_setup(uid);
183         io_log_open();
184         dowait = TRUE;
185     }
186 #endif /* _PATH_SUDO_IO_LOGDIR */
187
188 #ifdef HAVE_SELINUX
189     rbac_enabled = is_selinux_enabled() > 0 && user_role != NULL;
190     if (rbac_enabled)
191         dowait = TRUE;
192 #endif
193
194     /*
195      * If we don't need to wait for the command to finish, just exec it.
196      */
197     if (!dowait) {
198         exec_setup(FALSE, NULL, -1);
199         closefrom(def_closefrom);
200         my_execve(path, argv, envp);
201         cstat->type = CMD_ERRNO;
202         cstat->val = errno;
203         return(127);
204     }
205
206     /*
207      * We communicate with the child over a bi-directional pair of sockets.
208      * Parent sends signal info to child and child sends back wait status.
209      */
210     if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) != 0)
211         error(1, "cannot create sockets");
212
213     zero_bytes(&sa, sizeof(sa));
214     sigemptyset(&sa.sa_mask);
215
216     /* Note: HP-UX select() will not be interrupted if SA_RESTART set */
217     sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
218     sa.sa_handler = handler;
219     sigaction(SIGCHLD, &sa, NULL);
220     sigaction(SIGHUP, &sa, NULL);
221     sigaction(SIGINT, &sa, NULL);
222     sigaction(SIGPIPE, &sa, NULL);
223     sigaction(SIGQUIT, &sa, NULL);
224     sigaction(SIGTERM, &sa, NULL);
225
226     /* Max fd we will be selecting on. */
227     maxfd = sv[0];
228
229     /*
230      * Child will run the command in the pty, parent will pass data
231      * to and from pty.  Adjusts maxfd as needed.
232      */
233 #ifdef _PATH_SUDO_IO_LOGDIR
234     if (log_io)
235         child = fork_pty(path, argv, envp, sv, rbac_enabled, &maxfd);
236     else
237 #endif
238         child = fork_cmnd(path, argv, envp, sv, rbac_enabled);
239     close(sv[1]);
240
241 #ifdef HAVE_SETLOCALE
242     /*
243      * I/O logging must be in the C locale for floating point numbers
244      * to be logged consistently.
245      */
246     setlocale(LC_ALL, "C");
247 #endif
248
249     /*
250      * In the event loop we pass input from user tty to master
251      * and pass output from master to stdout and IO plugin.
252      */
253     fdsr = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
254     fdsw = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
255     for (;;) {
256         if (recvsig[SIGCHLD]) {
257             pid_t pid;
258
259             /*
260              * If logging I/O, child is the intermediate process,
261              * otherwise it is the command itself.
262              */
263             recvsig[SIGCHLD] = FALSE;
264             do {
265 #ifdef sudo_waitpid
266                 pid = sudo_waitpid(child, &status, WUNTRACED|WNOHANG);
267 #else
268                 pid = wait(&status);
269 #endif
270             } while (pid == -1 && errno == EINTR);
271             if (pid == child) {
272                 /* If not logging I/O and child has exited we are done. */
273                 if (!log_io) {
274                     if (WIFSTOPPED(status)) {
275                         /* Child may not have privs to suspend us itself. */
276                         kill(getpid(), WSTOPSIG(status));
277                     } else {
278                         /* Child has exited, we are done. */
279                         cstat->type = CMD_WSTATUS;
280                         cstat->val = status;
281                         return 0;
282                     }
283                 }
284                 /* Else we get ECONNRESET on sv[0] if child dies. */
285             }
286         }
287
288         zero_bytes(fdsw, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
289         zero_bytes(fdsr, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
290
291         FD_SET(sv[0], fdsr);
292 #ifdef _PATH_SUDO_IO_LOGDIR
293         if (log_io)
294             fd_set_iobs(fdsr, fdsw); /* XXX - better name */
295 #endif
296         for (n = 0; n < NSIG; n++) {
297             if (recvsig[n] && n != SIGCHLD) {
298                 if (log_io) {
299                     FD_SET(sv[0], fdsw);
300                     break;
301                 } else {
302                     /* nothing listening on sv[0], send directly */
303                     kill(child, n);
304                 }
305             }
306         }
307
308         if (recvsig[SIGCHLD])
309             continue;
310         nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
311         if (nready == -1) {
312             if (errno == EINTR)
313                 continue;
314             error(1, "select failed");
315         }
316         if (FD_ISSET(sv[0], fdsr)) {
317             /* read child status */
318             n = recv(sv[0], cstat, sizeof(*cstat), 0);
319             if (n == -1) {
320                 if (errno == EINTR)
321                     continue;
322                 /*
323                  * If not logging I/O we will receive ECONNRESET when
324                  * the command is executed.  It is safe to ignore this.
325                  */
326                 if (log_io && errno != EAGAIN) {
327                     cstat->type = CMD_ERRNO;
328                     cstat->val = errno;
329                     break;
330                 }
331             }
332 #ifdef _PATH_SUDO_IO_LOGDIR /* XXX */
333             if (cstat->type == CMD_WSTATUS) {
334                 if (WIFSTOPPED(cstat->val)) {
335                     /* Suspend parent and tell child how to resume on return. */
336                     n = suspend_parent(WSTOPSIG(cstat->val));
337                     recvsig[n] = TRUE;
338                     continue;
339                 } else {
340                     /* Child exited or was killed, either way we are done. */
341                     break;
342                 }
343             } else
344 #endif /* _PATH_SUDO_IO_LOGDIR */
345             if (cstat->type == CMD_ERRNO) {
346                 /* Child was unable to execute command or broken pipe. */
347                 break;
348             }
349         }
350
351 #ifdef _PATH_SUDO_IO_LOGDIR
352         /* XXX - move this too */
353         if (FD_ISSET(sv[0], fdsw)) {
354             for (n = 0; n < NSIG; n++) {
355                 if (!recvsig[n])
356                     continue;
357                 recvsig[n] = FALSE;
358                 cstat->type = CMD_SIGNO;
359                 cstat->val = n;
360                 do {
361                     n = send(sv[0], cstat, sizeof(*cstat), 0);
362                 } while (n == -1 && errno == EINTR);
363                 if (n != sizeof(*cstat)) {
364                     recvsig[n] = TRUE;
365                     break;
366                 }
367             }
368         }
369         if (perform_io(fdsr, fdsw, cstat) != 0)
370             break;
371 #endif /* _PATH_SUDO_IO_LOGDIR */
372     }
373
374 #ifdef _PATH_SUDO_IO_LOGDIR
375     if (log_io) {
376         /* Flush any remaining output and free pty-related memory. */
377         pty_close(cstat);
378     }
379 #endif /* _PATH_SUDO_IO_LOGDIR */
380
381 #ifdef HAVE_SELINUX
382     if (rbac_enabled) {
383         /* This is probably not needed in log_io mode. */
384         if (selinux_restore_tty() != 0)
385             warningx("unable to restore tty label");
386     }
387 #endif
388
389     efree(fdsr);
390     efree(fdsw);
391
392     return cstat->type == CMD_ERRNO ? -1 : 0;
393 }
394
395 /*
396  * Generic handler for signals passed from parent -> child.
397  * The recvsig[] array is checked in the main event loop.
398  */
399 void
400 handler(s)
401     int s;
402 {
403     recvsig[s] = TRUE;
404 }