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