1 /* $OpenBSD: ktrace.c,v 1.32 2015/04/18 18:28:37 deraadt Exp $ */ 2 /* $NetBSD: ktrace.c,v 1.4 1995/08/31 23:01:44 jtc Exp $ */ 3 4 /*- 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> /* MAXCOMLEN */ 34 #include <sys/signal.h> 35 #include <sys/stat.h> 36 #include <sys/time.h> 37 #include <sys/uio.h> 38 #include <sys/ktrace.h> 39 40 #include <err.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #include "ktrace.h" 49 #include "extern.h" 50 51 extern char *__progname; 52 53 static int rpid(const char *); 54 static void no_ktrace(int); 55 static void usage(void); 56 57 int is_ltrace; 58 59 int 60 main(int argc, char *argv[]) 61 { 62 enum { NOTSET, CLEAR, CLEARALL } clear; 63 int append, ch, fd, inherit, ops, pidset, trpoints; 64 pid_t pid; 65 char *tracefile, *tracespec; 66 mode_t omask; 67 struct stat sb; 68 69 is_ltrace = strcmp(__progname, "ltrace") == 0; 70 71 clear = NOTSET; 72 append = ops = pidset = inherit = pid = 0; 73 trpoints = is_ltrace ? KTRFAC_USER : DEF_POINTS; 74 tracefile = DEF_TRACEFILE; 75 tracespec = NULL; 76 77 if (is_ltrace) { 78 while ((ch = getopt(argc, argv, "af:it:u:")) != -1) 79 switch ((char)ch) { 80 case 'a': 81 append = 1; 82 break; 83 case 'f': 84 tracefile = optarg; 85 break; 86 case 'i': 87 inherit = 1; 88 break; 89 case 't': 90 trpoints = getpoints(optarg); 91 if (trpoints < 0) { 92 warnx("unknown facility in %s", optarg); 93 usage(); 94 } 95 break; 96 case 'u': 97 tracespec = optarg; 98 break; 99 default: 100 usage(); 101 } 102 } else { 103 while ((ch = getopt(argc, argv, "aBCcdf:g:ip:t:")) != -1) 104 switch ((char)ch) { 105 case 'a': 106 append = 1; 107 break; 108 case 'B': 109 putenv("LD_BIND_NOW="); 110 break; 111 case 'C': 112 clear = CLEARALL; 113 pidset = 1; 114 break; 115 case 'c': 116 clear = CLEAR; 117 break; 118 case 'd': 119 ops |= KTRFLAG_DESCEND; 120 break; 121 case 'f': 122 tracefile = optarg; 123 break; 124 case 'g': 125 pid = -rpid(optarg); 126 pidset = 1; 127 break; 128 case 'i': 129 inherit = 1; 130 break; 131 case 'p': 132 pid = rpid(optarg); 133 pidset = 1; 134 break; 135 case 't': 136 trpoints = getpoints(optarg); 137 if (trpoints < 0) { 138 warnx("unknown facility in %s", optarg); 139 usage(); 140 } 141 break; 142 default: 143 usage(); 144 } 145 } 146 147 argv += optind; 148 argc -= optind; 149 150 if ((pidset && *argv) || (!pidset && !*argv && clear != CLEAR)) 151 usage(); 152 153 if (inherit) 154 trpoints |= KTRFAC_INHERIT; 155 156 (void)signal(SIGSYS, no_ktrace); 157 if (clear != NOTSET) { 158 if (clear == CLEARALL) { 159 ops = KTROP_CLEAR | KTRFLAG_DESCEND; 160 trpoints = ALL_POINTS; 161 pid = 1; 162 } else 163 ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; 164 165 if (ktrace(tracefile, ops, trpoints, pid) < 0) { 166 if (errno == ESRCH) 167 err(1, "%d", pid); 168 err(1, "%s", tracefile); 169 } 170 exit(0); 171 } 172 173 omask = umask(S_IRWXG|S_IRWXO); 174 if (append) { 175 if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) < 0) 176 err(1, "%s", tracefile); 177 if (fstat(fd, &sb) != 0 || sb.st_uid != getuid()) 178 errx(1, "Refuse to append to %s: not owned by you.", 179 tracefile); 180 } else { 181 if (unlink(tracefile) == -1 && errno != ENOENT) 182 err(1, "unlink %s", tracefile); 183 if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY, 184 DEFFILEMODE)) < 0) 185 err(1, "%s", tracefile); 186 } 187 (void)umask(omask); 188 (void)close(fd); 189 190 if (*argv) { 191 if (is_ltrace) { 192 if (setenv("LD_TRACE_PLT", inherit ? "i" : "", 1) < 0) 193 err(1, "setenv(LD_TRACE_PLT)"); 194 if (tracespec && 195 setenv("LD_TRACE_PLTSPEC", tracespec, 1) < 0) 196 err(1, "setenv(LD_TRACE_PLTSPEC)"); 197 } 198 if (ktrace(tracefile, ops, trpoints, getpid()) < 0) 199 err(1, "%s", tracefile); 200 execvp(argv[0], &argv[0]); 201 err(1, "exec of '%s' failed", argv[0]); 202 } 203 else if (ktrace(tracefile, ops, trpoints, pid) < 0) { 204 if (errno == ESRCH) 205 err(1, "%d", pid); 206 err(1, "%s", tracefile); 207 } 208 exit(0); 209 } 210 211 static int 212 rpid(const char *p) 213 { 214 const char *errstr; 215 static int first; 216 pid_t pid; 217 218 if (first++) { 219 warnx("only one -g or -p flag is permitted."); 220 usage(); 221 } 222 if (!*p) { 223 warnx("illegal process id."); 224 usage(); 225 } 226 pid = strtonum(p, 1, INT_MAX, &errstr); 227 if (errstr) { 228 warnx("illegal process id: %s", errstr); 229 usage(); 230 } 231 return pid; 232 } 233 234 static void 235 usage(void) 236 { 237 if (is_ltrace) 238 fprintf(stderr, "usage: %s [-ai] [-f trfile] [-t trstr]" 239 " [-u trspec] command\n", 240 __progname); 241 else 242 fprintf(stderr, "usage: %s [-aBCcdi] [-f trfile] [-g pgid]" 243 " [-p pid] [-t trstr]\n" 244 " %s [-adi] [-f trfile] [-t trstr] command\n", 245 __progname, __progname); 246 exit(1); 247 } 248 249 /* ARGSUSED */ 250 static void 251 no_ktrace(int signo) 252 { 253 char buf[8192]; 254 255 snprintf(buf, sizeof(buf), 256 "error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'option KTRACE'\n"); 257 write(STDERR_FILENO, buf, strlen(buf)); 258 _exit(1); 259 } 260