1 /* $OpenBSD: modstat.c,v 1.22 2005/07/04 01:54:10 djm Exp $ */
2
3 /*
4 * Copyright (c) 1993 Terrence R. Lambert.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Terrence R. Lambert.
18 * 4. The name Terrence R. Lambert may not be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 */
35
36 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <sys/conf.h>
39 #include <sys/mount.h>
40 #include <sys/lkm.h>
41
42 #include <a.out.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50
51 #include "pathnames.h"
52
53 #define POINTERSIZE ((int)(2 * sizeof(void*)))
54
55 static char *type_names[] = {
56 "SYSCALL",
57 "VFS",
58 "DEV",
59 "EXEC",
60 "MISC"
61 };
62
63 static void
usage(void)64 usage(void)
65 {
66 extern char *__progname;
67
68 (void)fprintf(stderr, "usage: %s [-i id] [-n name]\n", __progname);
69 exit(1);
70 }
71
72 static int
dostat(int devfd,int modnum,char * modname)73 dostat(int devfd, int modnum, char *modname)
74 {
75 char name[MAXLKMNAME];
76 struct lmc_stat sbuf;
77
78 bzero(&name, sizeof name);
79 bzero(&sbuf, sizeof sbuf);
80 sbuf.id = modnum;
81 sbuf.name = name;
82
83 if (modname != NULL) {
84 if (strlen(modname) >= sizeof(name))
85 return 4;
86 strlcpy(sbuf.name, modname, sizeof(name));
87 }
88
89 if (ioctl(devfd, LMSTAT, &sbuf) == -1) {
90 switch (errno) {
91 case EINVAL: /* out of range */
92 return 2;
93 case ENOENT: /* no such entry */
94 return 1;
95 default: /* other error (EFAULT, etc) */
96 warn("LMSTAT");
97 return 4;
98 }
99 }
100
101 /* Decode this stat buffer... */
102 printf("%-7s %3d %3ld %0*lx %04lx %0*lx %3ld %s\n",
103 type_names[sbuf.type], sbuf.id, sbuf.offset, POINTERSIZE,
104 (long)sbuf.area, (long)sbuf.size, POINTERSIZE,
105 (long)sbuf.private, (long)sbuf.ver, sbuf.name);
106
107 return 0;
108 }
109
110 int
main(int argc,char * argv[])111 main(int argc, char *argv[])
112 {
113 int c, modnum = -1;
114 char *modname = NULL;
115 char *endptr;
116 int devfd;
117 gid_t gid;
118
119 while ((c = getopt(argc, argv, "i:n:")) != -1) {
120 switch (c) {
121 case 'i':
122 modnum = (int)strtol(optarg, &endptr, 0);
123 if (modnum < 0 || modnum > INT_MAX || *endptr != '\0')
124 errx(1, "%s: not a valid number", optarg);
125 break;
126 case 'n':
127 modname = optarg;
128 break;
129 default:
130 usage();
131 break;
132 }
133 }
134 argc -= optind;
135 argv += optind;
136
137 if (argc != 0)
138 usage();
139
140 /*
141 * Open the virtual device device driver for exclusive use (needed
142 * to ioctl() to retrive the loaded module(s) status).
143 */
144 if ((devfd = open(_PATH_LKM, O_RDONLY)) == -1)
145 err(2, "%s", _PATH_LKM);
146
147 gid = getgid();
148 if (setresgid(gid, gid, gid) == -1)
149 err(1, "setresgid");
150
151 printf("Type Id Off %-*s Size %-*s Rev Module Name\n",
152 POINTERSIZE, "Loadaddr", POINTERSIZE, "Info");
153
154 if (modnum != -1 || modname != NULL) {
155 if (dostat(devfd, modnum, modname))
156 exit(3);
157 exit(0);
158 }
159
160 /* Start at 0 and work up until we receive EINVAL. */
161 for (modnum = 0; dostat(devfd, modnum, NULL) < 2; modnum++)
162 ;
163
164 exit(0);
165 }
166