pexec.c (2517B)
1 /* 2 * Copyright (c) 2018 Dimitris Papastamos <sin@2f30.org> 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 /* 18 * execute a program from stdin 19 * 20 * example: ssh user@host pexec ls -la < /bin/ls 21 * 22 * This is true cloud computing! 23 */ 24 25 #include <sys/stat.h> 26 #include <sys/syscall.h> 27 #include <err.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include "arg.h" 32 33 char *argv0; 34 35 static ssize_t 36 xread(int fd, void *buf, size_t nbytes) 37 { 38 unsigned char *bp = buf; 39 ssize_t total = 0; 40 41 while (nbytes > 0) { 42 ssize_t n; 43 44 n = read(fd, &bp[total], nbytes); 45 if (n < 0) 46 err(1, "read"); 47 else if (n == 0) 48 return total; 49 total += n; 50 nbytes -= n; 51 } 52 return total; 53 } 54 55 static ssize_t 56 xwrite(int fd, const void *buf, size_t nbytes) 57 { 58 const unsigned char *bp = buf; 59 ssize_t total = 0; 60 61 while (nbytes > 0) { 62 ssize_t n; 63 64 n = write(fd, &bp[total], nbytes); 65 if (n < 0) 66 err(1, "write"); 67 else if (n == 0) 68 return total; 69 total += n; 70 nbytes -= n; 71 } 72 return total; 73 } 74 75 static int 76 memfd_create(const char *name, unsigned int flags) 77 { 78 return syscall(__NR_memfd_create, name, flags); 79 } 80 81 void 82 pexec(int ifd, char *argv[], char *envp[]) 83 { 84 char buf[BUFSIZ]; 85 ssize_t n; 86 int fd; 87 88 fd = memfd_create(argv[0], 0); 89 if (fd < 0) 90 err(1, "memfd_create"); 91 92 if (fchmod(fd, 0755) < 0) 93 err(1, "fchmod"); 94 95 while ((n = xread(ifd, buf, sizeof(buf))) > 0) 96 xwrite(fd, buf, n); 97 98 if (fexecve(fd, argv, envp) < 0) 99 err(1, "fexecve"); 100 } 101 102 static void 103 usage(void) 104 { 105 fprintf(stderr, "usage: pexec [-i] argv[0] [argv[1]...]\n"); 106 exit(1); 107 } 108 109 int 110 main(int argc, char *argv[]) 111 { 112 char *envp[] = { NULL }; 113 int iflag = 0; 114 115 ARGBEGIN { 116 case 'i': 117 iflag = 1; 118 break; 119 default: 120 usage(); 121 } ARGEND 122 123 if (argc == 0) 124 usage(); 125 126 extern char **environ; 127 pexec(STDIN_FILENO, argv, iflag ? envp : environ); 128 /* unreachable */ 129 }