15d9e6103SBrian Somers /*- 25d9e6103SBrian Somers * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org> 35d9e6103SBrian Somers * All rights reserved. 45d9e6103SBrian Somers * 55d9e6103SBrian Somers * Redistribution and use in source and binary forms, with or without 65d9e6103SBrian Somers * modification, are permitted provided that the following conditions 75d9e6103SBrian Somers * are met: 85d9e6103SBrian Somers * 1. Redistributions of source code must retain the above copyright 95d9e6103SBrian Somers * notice, this list of conditions and the following disclaimer. 105d9e6103SBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 115d9e6103SBrian Somers * notice, this list of conditions and the following disclaimer in the 125d9e6103SBrian Somers * documentation and/or other materials provided with the distribution. 135d9e6103SBrian Somers * 145d9e6103SBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 155d9e6103SBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 165d9e6103SBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 175d9e6103SBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 185d9e6103SBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 195d9e6103SBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 205d9e6103SBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 215d9e6103SBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 225d9e6103SBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 235d9e6103SBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 245d9e6103SBrian Somers * SUCH DAMAGE. 255d9e6103SBrian Somers * 2697d92980SPeter Wemm * $FreeBSD$ 275d9e6103SBrian Somers */ 285d9e6103SBrian Somers 295d9e6103SBrian Somers #include <sys/param.h> 305d9e6103SBrian Somers #include <sys/socket.h> 315d9e6103SBrian Somers #include <sys/un.h> 325d9e6103SBrian Somers 335d9e6103SBrian Somers #include <errno.h> 345d9e6103SBrian Somers #include <fcntl.h> 355d9e6103SBrian Somers #include <stdio.h> 365d9e6103SBrian Somers #include <stdlib.h> 375d9e6103SBrian Somers #include <string.h> 385d9e6103SBrian Somers #include <sys/wait.h> 39f5a99677SBrian Somers #include <sys/uio.h> 405d9e6103SBrian Somers #include <termios.h> 415d9e6103SBrian Somers #include <unistd.h> 425d9e6103SBrian Somers 435d9e6103SBrian Somers #include "layer.h" 445d9e6103SBrian Somers #include "defs.h" 455d9e6103SBrian Somers #include "mbuf.h" 465d9e6103SBrian Somers #include "log.h" 475d9e6103SBrian Somers #include "timer.h" 485d9e6103SBrian Somers #include "lqr.h" 495d9e6103SBrian Somers #include "hdlc.h" 505d9e6103SBrian Somers #include "throughput.h" 515d9e6103SBrian Somers #include "fsm.h" 525d9e6103SBrian Somers #include "lcp.h" 535d9e6103SBrian Somers #include "ccp.h" 545d9e6103SBrian Somers #include "link.h" 555d9e6103SBrian Somers #include "async.h" 565d9e6103SBrian Somers #include "descriptor.h" 575d9e6103SBrian Somers #include "physical.h" 585d9e6103SBrian Somers #include "mp.h" 595d9e6103SBrian Somers #include "chat.h" 605d9e6103SBrian Somers #include "command.h" 615d9e6103SBrian Somers #include "auth.h" 625d9e6103SBrian Somers #include "chap.h" 635d9e6103SBrian Somers #include "cbcp.h" 645d9e6103SBrian Somers #include "datalink.h" 65e7d008b4SBrian Somers #include "id.h" 665d9e6103SBrian Somers #include "exec.h" 675d9e6103SBrian Somers 686815097bSBrian Somers static struct device execdevice = { 696815097bSBrian Somers EXEC_DEVICE, 706815097bSBrian Somers "exec", 71c8b9fb53SBrian Somers 0, 72fdc29d54SBrian Somers { CD_NOTREQUIRED, 0 }, 736815097bSBrian Somers NULL, 746815097bSBrian Somers NULL, 756815097bSBrian Somers NULL, 766815097bSBrian Somers NULL, 776815097bSBrian Somers NULL, 786815097bSBrian Somers NULL, 796815097bSBrian Somers NULL, 806815097bSBrian Somers NULL, 816815097bSBrian Somers NULL, 82eb6e5e05SBrian Somers NULL, 8387c3786eSBrian Somers NULL, 84fb11a9c2SBrian Somers NULL, 85de59e178SBrian Somers NULL, 866815097bSBrian Somers NULL 876815097bSBrian Somers }; 886815097bSBrian Somers 896815097bSBrian Somers struct device * 906815097bSBrian Somers exec_iov2device(int type, struct physical *p, struct iovec *iov, 9187c3786eSBrian Somers int *niov, int maxiov, int *auxfd, int *nauxfd) 925d9e6103SBrian Somers { 93acbd1f00SBrian Somers if (type == EXEC_DEVICE) { 94f5a99677SBrian Somers free(iov[(*niov)++].iov_base); 95a1bc3dccSBrian Somers physical_SetupStack(p, execdevice.name, PHYSICAL_NOFORCE); 966815097bSBrian Somers return &execdevice; 97acbd1f00SBrian Somers } 986815097bSBrian Somers 996815097bSBrian Somers return NULL; 1006815097bSBrian Somers } 1016815097bSBrian Somers 1026815097bSBrian Somers struct device * 1036815097bSBrian Somers exec_Create(struct physical *p) 1046815097bSBrian Somers { 1056815097bSBrian Somers if (p->fd < 0 && *p->name.full == '!') { 106d9626e94SBrian Somers int fids[2], type; 1075d9e6103SBrian Somers 10887c3786eSBrian Somers p->fd--; /* We own the device but maybe can't use it - change fd */ 109d9626e94SBrian Somers type = physical_IsSync(p) ? SOCK_DGRAM : SOCK_STREAM; 11087c3786eSBrian Somers 111d9626e94SBrian Somers if (socketpair(AF_UNIX, type, PF_UNSPEC, fids) < 0) 1125d9e6103SBrian Somers log_Printf(LogPHASE, "Unable to create pipe for line exec: %s\n", 1135d9e6103SBrian Somers strerror(errno)); 1145d9e6103SBrian Somers else { 11507e4efadSBrian Somers static int child_status; /* This variable is abused ! */ 116d9626e94SBrian Somers int stat, argc, i, ret, wret, pidpipe[2]; 1178fb106c6SBrian Somers pid_t pid, realpid; 1185d9e6103SBrian Somers char *argv[MAXARGS]; 1195d9e6103SBrian Somers 1205d9e6103SBrian Somers stat = fcntl(fids[0], F_GETFL, 0); 1215d9e6103SBrian Somers if (stat > 0) { 1225d9e6103SBrian Somers stat |= O_NONBLOCK; 1235d9e6103SBrian Somers fcntl(fids[0], F_SETFL, stat); 1245d9e6103SBrian Somers } 1258fb106c6SBrian Somers realpid = getpid(); 126d9626e94SBrian Somers if (pipe(pidpipe) == -1) { 127d9626e94SBrian Somers log_Printf(LogPHASE, "Unable to pipe for line exec: %s\n", 1285d9e6103SBrian Somers strerror(errno)); 1293ce91245SBrian Somers close(fids[1]); 130d9626e94SBrian Somers } else switch ((pid = fork())) { 131d9626e94SBrian Somers case -1: 132d9626e94SBrian Somers log_Printf(LogPHASE, "Unable to fork for line exec: %s\n", 133d9626e94SBrian Somers strerror(errno)); 134d9626e94SBrian Somers close(pidpipe[0]); 135d9626e94SBrian Somers close(pidpipe[1]); 136d9626e94SBrian Somers close(fids[1]); 1375d9e6103SBrian Somers break; 1385d9e6103SBrian Somers 1395d9e6103SBrian Somers case 0: 140d9626e94SBrian Somers close(pidpipe[0]); 1415d9e6103SBrian Somers close(fids[0]); 1425d9e6103SBrian Somers timer_TermService(); 14368602c3eSBrian Somers #ifndef NOSUID 144a19a5c02SBrian Somers setuid(ID0realuid()); 14568602c3eSBrian Somers #endif 1465d9e6103SBrian Somers 1473ce91245SBrian Somers child_status = 0; 148d9626e94SBrian Somers switch ((pid = vfork())) { 1495d9e6103SBrian Somers case 0: 150d9626e94SBrian Somers close(pidpipe[1]); 1515d9e6103SBrian Somers break; 1525d9e6103SBrian Somers 1535d9e6103SBrian Somers case -1: 1543ce91245SBrian Somers ret = errno; 155d9626e94SBrian Somers log_Printf(LogPHASE, "Unable to vfork to drop parent: %s\n", 1565d9e6103SBrian Somers strerror(errno)); 157d9626e94SBrian Somers close(pidpipe[1]); 1583ce91245SBrian Somers _exit(ret); 1593ce91245SBrian Somers 1605d9e6103SBrian Somers default: 161d9626e94SBrian Somers write(pidpipe[1], &pid, sizeof pid); 162d9626e94SBrian Somers close(pidpipe[1]); 1633ce91245SBrian Somers _exit(child_status); /* The error from exec() ! */ 1645d9e6103SBrian Somers } 1655d9e6103SBrian Somers 16644e73c12SBrian Somers log_Printf(LogDEBUG, "Exec'ing ``%s''\n", p->name.base); 16744e73c12SBrian Somers 1685b78bdf8SBrian Somers if ((argc = MakeArgs(p->name.base, argv, VECSIZE(argv), 1695b78bdf8SBrian Somers PARSE_REDUCE|PARSE_NOHASH)) < 0) { 170c39aa54eSBrian Somers log_Printf(LogWARN, "Syntax error in exec command\n"); 1713ce91245SBrian Somers _exit(ESRCH); 172c39aa54eSBrian Somers } 173c39aa54eSBrian Somers 174c39aa54eSBrian Somers command_Expand(argv, argc, (char const *const *)argv, 175c39aa54eSBrian Somers p->dl->bundle, 0, realpid); 176c39aa54eSBrian Somers 1775d9e6103SBrian Somers dup2(fids[1], STDIN_FILENO); 1785d9e6103SBrian Somers dup2(fids[1], STDOUT_FILENO); 1795d9e6103SBrian Somers dup2(fids[1], STDERR_FILENO); 18044e73c12SBrian Somers for (i = getdtablesize(); i > STDERR_FILENO; i--) 18144e73c12SBrian Somers fcntl(i, F_SETFD, 1); 1825d9e6103SBrian Somers 1835d9e6103SBrian Somers execvp(*argv, argv); 1843ce91245SBrian Somers child_status = errno; /* Only works for vfork() */ 1853ce91245SBrian Somers printf("execvp failed: %s: %s\r\n", *argv, strerror(child_status)); 1863ce91245SBrian Somers _exit(child_status); 1875d9e6103SBrian Somers break; 1885d9e6103SBrian Somers 1895d9e6103SBrian Somers default: 190d9626e94SBrian Somers close(pidpipe[1]); 1915d9e6103SBrian Somers close(fids[1]); 192d9626e94SBrian Somers if (read(pidpipe[0], &p->session_owner, sizeof p->session_owner) != 193d9626e94SBrian Somers sizeof p->session_owner) 194d9626e94SBrian Somers p->session_owner = (pid_t)-1; 195d9626e94SBrian Somers close(pidpipe[0]); 1963ce91245SBrian Somers while ((wret = waitpid(pid, &stat, 0)) == -1 && errno == EINTR) 1973ce91245SBrian Somers ; 1983ce91245SBrian Somers if (wret == -1) { 1993ce91245SBrian Somers log_Printf(LogWARN, "Waiting for child process: %s\n", 2003ce91245SBrian Somers strerror(errno)); 2013ce91245SBrian Somers close(fids[0]); 202d9626e94SBrian Somers p->session_owner = (pid_t)-1; 2033ce91245SBrian Somers break; 2043ce91245SBrian Somers } else if (WIFSIGNALED(stat)) { 2053ce91245SBrian Somers log_Printf(LogWARN, "Child process received sig %d !\n", 2063ce91245SBrian Somers WTERMSIG(stat)); 2073ce91245SBrian Somers close(fids[0]); 208d9626e94SBrian Somers p->session_owner = (pid_t)-1; 2093ce91245SBrian Somers break; 2103ce91245SBrian Somers } else if (WIFSTOPPED(stat)) { 2113ce91245SBrian Somers log_Printf(LogWARN, "Child process received stop sig %d !\n", 2123ce91245SBrian Somers WSTOPSIG(stat)); 2133ce91245SBrian Somers /* I guess that's ok.... */ 2143ce91245SBrian Somers } else if ((ret = WEXITSTATUS(stat))) { 2153ce91245SBrian Somers log_Printf(LogWARN, "Cannot exec \"%s\": %s\n", p->name.base, 2163ce91245SBrian Somers strerror(ret)); 2173ce91245SBrian Somers close(fids[0]); 218d9626e94SBrian Somers p->session_owner = (pid_t)-1; 2193ce91245SBrian Somers break; 2203ce91245SBrian Somers } 2215d9e6103SBrian Somers p->fd = fids[0]; 2228e7bd08eSBrian Somers log_Printf(LogDEBUG, "Using descriptor %d for child\n", p->fd); 223d9626e94SBrian Somers physical_SetupStack(p, execdevice.name, PHYSICAL_NOFORCE); 224fdc29d54SBrian Somers if (p->cfg.cd.necessity != CD_DEFAULT) 225fdc29d54SBrian Somers log_Printf(LogWARN, "Carrier settings ignored\n"); 2266815097bSBrian Somers return &execdevice; 2275d9e6103SBrian Somers } 2283ce91245SBrian Somers close(fids[0]); 2295d9e6103SBrian Somers } 2305d9e6103SBrian Somers } 2315d9e6103SBrian Somers 2326815097bSBrian Somers return NULL; 2335d9e6103SBrian Somers } 234