1 /* $OpenBSD: ktrace.c,v 1.36 2019/06/28 13:35:01 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, KTRFAC_USER); 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 tracefile = NULL; 114 pidset = 1; 115 break; 116 case 'c': 117 clear = CLEAR; 118 break; 119 case 'd': 120 ops |= KTRFLAG_DESCEND; 121 break; 122 case 'f': 123 tracefile = optarg; 124 break; 125 case 'g': 126 pid = -rpid(optarg); 127 pidset = 1; 128 break; 129 case 'i': 130 inherit = 1; 131 break; 132 case 'p': 133 pid = rpid(optarg); 134 pidset = 1; 135 break; 136 case 't': 137 trpoints = getpoints(optarg, DEF_POINTS); 138 if (trpoints < 0) { 139 warnx("unknown facility in %s", optarg); 140 usage(); 141 } 142 break; 143 default: 144 usage(); 145 } 146 } 147 148 argv += optind; 149 argc -= optind; 150 151 if ((pidset && *argv) || (!pidset && !*argv && clear != CLEAR)) 152 usage(); 153 154 if (inherit) 155 trpoints |= KTRFAC_INHERIT; 156 157 (void)signal(SIGSYS, no_ktrace); 158 if (clear != NOTSET) { 159 if (clear == CLEARALL) { 160 ops = KTROP_CLEAR | KTRFLAG_DESCEND; 161 trpoints = ALL_POINTS; 162 pid = 1; 163 } else 164 ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; 165 166 if (ktrace(tracefile, ops, trpoints, pid) == -1) { 167 if (errno == ESRCH) 168 err(1, "%d", pid); 169 err(1, "%s", tracefile); 170 } 171 exit(0); 172 } 173 174 omask = umask(S_IRWXG|S_IRWXO); 175 if (append) { 176 if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) == -1) 177 err(1, "%s", tracefile); 178 if (fstat(fd, &sb) != 0 || sb.st_uid != getuid()) 179 errx(1, "Refuse to append to %s: not owned by you.", 180 tracefile); 181 } else { 182 if (unlink(tracefile) == -1 && errno != ENOENT) 183 err(1, "unlink %s", tracefile); 184 if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY, 185 DEFFILEMODE)) == -1) 186 err(1, "%s", tracefile); 187 } 188 (void)umask(omask); 189 (void)close(fd); 190 191 if (*argv) { 192 if (is_ltrace) { 193 if (setenv("LD_TRACE_PLT", inherit ? "i" : "", 1) < 0) 194 err(1, "setenv(LD_TRACE_PLT)"); 195 if (tracespec && 196 setenv("LD_TRACE_PLTSPEC", tracespec, 1) < 0) 197 err(1, "setenv(LD_TRACE_PLTSPEC)"); 198 } 199 if (ktrace(tracefile, ops, trpoints, getpid()) == -1) 200 err(1, "%s", tracefile); 201 execvp(argv[0], &argv[0]); 202 err(1, "exec of '%s' failed", argv[0]); 203 } 204 else if (ktrace(tracefile, ops, trpoints, pid) == -1) { 205 if (errno == ESRCH) 206 err(1, "%d", pid); 207 err(1, "%s", tracefile); 208 } 209 exit(0); 210 } 211 212 static int 213 rpid(const char *p) 214 { 215 const char *errstr; 216 static int first; 217 pid_t pid; 218 219 if (first++) { 220 warnx("only one -g or -p flag is permitted."); 221 usage(); 222 } 223 if (!*p) { 224 warnx("illegal process id."); 225 usage(); 226 } 227 pid = strtonum(p, 1, INT_MAX, &errstr); 228 if (errstr) { 229 warnx("illegal process id: %s", errstr); 230 usage(); 231 } 232 return pid; 233 } 234 235 static void 236 usage(void) 237 { 238 if (is_ltrace) 239 fprintf(stderr, "usage: %s [-ai] [-f trfile] [-t trstr]" 240 " [-u trspec] command\n", 241 __progname); 242 else 243 fprintf(stderr, "usage: %s [-aBCcdi] [-f trfile] [-g pgid]" 244 " [-p pid] [-t trstr]\n" 245 " %s [-adi] [-f trfile] [-t trstr] command\n", 246 __progname, __progname); 247 exit(1); 248 } 249 250 /* ARGSUSED */ 251 static void 252 no_ktrace(int signo) 253 { 254 dprintf(STDERR_FILENO, 255 "error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'option KTRACE'\n"); 256 _exit(1); 257 } 258