1 /* $OpenBSD: ktrace.c,v 1.40 2023/03/08 04:43:11 guenther 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/types.h> 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 <limits.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include "ktrace.h" 50 #include "extern.h" 51 52 extern char *__progname; 53 54 static int rpid(const char *); 55 static void no_ktrace(int); 56 static void usage(void); 57 58 int is_ltrace; 59 60 int 61 main(int argc, char *argv[]) 62 { 63 enum { NOTSET, CLEAR, CLEARALL } clear; 64 int append, ch, fd, inherit, ops, pidset, trpoints; 65 pid_t pid; 66 char *tracefile, *tracespec; 67 mode_t omask; 68 struct stat sb; 69 70 is_ltrace = strcmp(__progname, "ltrace") == 0; 71 72 clear = NOTSET; 73 append = ops = pidset = inherit = pid = 0; 74 trpoints = is_ltrace ? KTRFAC_USER : DEF_POINTS; 75 tracefile = DEF_TRACEFILE; 76 tracespec = NULL; 77 78 if (is_ltrace) { 79 while ((ch = getopt(argc, argv, "af:it:u:")) != -1) 80 switch ((char)ch) { 81 case 'a': 82 append = 1; 83 break; 84 case 'f': 85 tracefile = optarg; 86 break; 87 case 'i': 88 inherit = 1; 89 break; 90 case 't': 91 trpoints = getpoints(optarg, KTRFAC_USER); 92 if (trpoints < 0) { 93 warnx("unknown facility in %s", optarg); 94 usage(); 95 } 96 break; 97 case 'u': 98 tracespec = optarg; 99 break; 100 default: 101 usage(); 102 } 103 } else { 104 while ((ch = getopt(argc, argv, "aBCcdf:g:ip:t:T")) != -1) 105 switch ((char)ch) { 106 case 'a': 107 append = 1; 108 break; 109 case 'B': 110 putenv("LD_BIND_NOW="); 111 break; 112 case 'C': 113 clear = CLEARALL; 114 tracefile = NULL; 115 pidset = 1; 116 break; 117 case 'c': 118 clear = CLEAR; 119 break; 120 case 'd': 121 ops |= KTRFLAG_DESCEND; 122 break; 123 case 'f': 124 tracefile = optarg; 125 break; 126 case 'g': 127 pid = -rpid(optarg); 128 pidset = 1; 129 break; 130 case 'i': 131 inherit = 1; 132 break; 133 case 'p': 134 pid = rpid(optarg); 135 pidset = 1; 136 break; 137 case 't': 138 trpoints = getpoints(optarg, DEF_POINTS); 139 if (trpoints < 0) { 140 warnx("unknown facility in %s", optarg); 141 usage(); 142 } 143 break; 144 case 'T': 145 putenv("LIBC_NOUSERTC="); 146 break; 147 default: 148 usage(); 149 } 150 } 151 152 argv += optind; 153 argc -= optind; 154 155 if ((pidset && *argv) || (!pidset && !*argv && clear != CLEAR)) 156 usage(); 157 158 if (inherit) 159 trpoints |= KTRFAC_INHERIT; 160 161 (void)signal(SIGSYS, no_ktrace); 162 if (clear != NOTSET) { 163 if (clear == CLEARALL) { 164 ops = KTROP_CLEAR | KTRFLAG_DESCEND; 165 trpoints = ALL_POINTS; 166 pid = 1; 167 } else 168 ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE; 169 170 if (ktrace(tracefile, ops, trpoints, pid) == -1) { 171 if (errno == ESRCH) 172 err(1, "%d", pid); 173 err(1, "%s", tracefile); 174 } 175 exit(0); 176 } 177 178 omask = umask(S_IRWXG|S_IRWXO); 179 if (append) { 180 if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) == -1) 181 err(1, "%s", tracefile); 182 if (fstat(fd, &sb) != 0 || sb.st_uid != getuid()) 183 errx(1, "Refuse to append to %s: not owned by you.", 184 tracefile); 185 } else { 186 if (unlink(tracefile) == -1 && errno != ENOENT) 187 err(1, "unlink %s", tracefile); 188 if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY, 189 DEFFILEMODE)) == -1) 190 err(1, "%s", tracefile); 191 } 192 (void)umask(omask); 193 (void)close(fd); 194 195 if (*argv) { 196 if (is_ltrace) { 197 if (setenv("LD_TRACE_PLT", inherit ? "i" : "", 1) < 0) 198 err(1, "setenv(LD_TRACE_PLT)"); 199 if (tracespec && 200 setenv("LD_TRACE_PLTSPEC", tracespec, 1) < 0) 201 err(1, "setenv(LD_TRACE_PLTSPEC)"); 202 } 203 if (ktrace(tracefile, ops, trpoints, getpid()) == -1) 204 err(1, "%s", tracefile); 205 execvp(argv[0], &argv[0]); 206 err(1, "exec of '%s' failed", argv[0]); 207 } 208 else if (ktrace(tracefile, ops, trpoints, pid) == -1) { 209 if (errno == ESRCH) 210 err(1, "%d", pid); 211 err(1, "%s", tracefile); 212 } 213 exit(0); 214 } 215 216 static int 217 rpid(const char *p) 218 { 219 const char *errstr; 220 static int first; 221 pid_t pid; 222 223 if (first++) { 224 warnx("only one -g or -p flag is permitted."); 225 usage(); 226 } 227 if (!*p) { 228 warnx("illegal process id."); 229 usage(); 230 } 231 pid = strtonum(p, 1, INT_MAX, &errstr); 232 if (errstr) { 233 warnx("illegal process id: %s", errstr); 234 usage(); 235 } 236 return pid; 237 } 238 239 static void 240 usage(void) 241 { 242 if (is_ltrace) 243 fprintf(stderr, "usage: %s [-ai] [-f trfile] [-t trstr]" 244 " [-u trspec] command\n", 245 __progname); 246 else 247 fprintf(stderr, "usage: %s [-aCcdi] [-f trfile] [-g pgid]" 248 " [-p pid] [-t trstr]\n" 249 " %s [-aBdiT] [-f trfile] [-t trstr] command\n", 250 __progname, __progname); 251 exit(1); 252 } 253 254 static void 255 no_ktrace(int signo) 256 { 257 dprintf(STDERR_FILENO, 258 "error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'option KTRACE'\n"); 259 _exit(1); 260 } 261