source: trunk/src/kern_head.c@ 474

Last change on this file since 474 was 360, checked in by katerina, 13 years ago

Fix for ticket #266 (kern_head does not work on 3.x kernels).

File size: 24.1 KB
Line 
1/*
2 * need to #define SH_USE_KERN
3 *
4 */
5#define SH_SYSCALL_CODE
6
7#include "config.h"
8
9#if defined(HOST_IS_I86LINUX) || defined(HOST_IS_64LINUX)
10#define SH_IDT_TABLE
11#endif
12
13#include <stdio.h>
14#include <stdlib.h>
15
16#if defined(SH_USE_KERN)
17
18#undef _
19#define _(string) string
20#undef N_
21#define N_(string) string
22
23void usage(int flag)
24{
25 printf("\n");
26 printf("Usage: kern_head [-v | --verbose]\n");
27 printf(" kern_head [-h | --help]\n");
28 printf("\n");
29 /*
30 * printf(" You need superuser privileges to use this program,\n");
31 * printf(" because only the superuser can read from /dev/kmem.\n");
32 * printf("\n");
33 */
34 exit(flag);
35}
36
37#if defined(HOST_IS_LINUX)
38
39
40#include <string.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <unistd.h>
45#include <errno.h>
46#include <limits.h>
47#include <sys/utsname.h>
48#include <sys/mman.h>
49
50/* number of system calls */
51#define SH_MAXCALLS 512
52
53#include "kern_head.h"
54
55static int verbose = 0;
56
57typedef struct _smap_entry {
58#ifdef SH_SYSCALL_CODE
59 unsigned int code[2]; /* 8 bytes */
60#endif
61 unsigned long addr;
62 char name[64];
63} smap_entry;
64
65union {
66 unsigned long addr_sys_call_table;
67 unsigned char str_sys_call_table[sizeof(unsigned long)];
68} sh_sys_call;
69
70#define SYS_CODE_SIZE 1024
71
72static unsigned long addr_system_call;
73static unsigned char system_call_code[SYS_CODE_SIZE];
74
75#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
76
77static int kmem_read (int fd, unsigned long addr, unsigned char * buf, int len)
78{
79 if (lseek(fd, addr, SEEK_SET) == (off_t) (-1))
80 {
81 if (verbose)
82 perror("kmem_read: lseek");
83 return -1;
84 }
85 if (read(fd, buf, len) < 0)
86 {
87 if (verbose)
88 perror("kmem_read: read");
89 return -1;
90 }
91 return 0;
92}
93
94static int kmem_mmap (int fd, unsigned long addr, unsigned char * buf, int len)
95{
96 size_t moff, roff;
97 size_t sz;
98 char * kmap;
99
100 sz = getpagesize(); /* unistd.h */
101
102 moff = ((size_t)(addr/sz)) * sz; /* lower page boundary */
103 roff = addr - moff; /* off relative to lower address of mmapped area */
104 kmap = mmap(0, len+sz, PROT_READ, MAP_PRIVATE, fd, moff);/* sys/mman.h */
105
106 if (kmap == MAP_FAILED)
107 {
108 /* then, try read()
109 */
110 if (verbose)
111 fprintf(stderr, "kmem_mmap: mmap() failed, now trying read()\n");
112
113 if (0 == kmem_read (fd, addr, buf, len))
114 return 0;
115
116 perror("kmem_mmap: mmap");
117 return -1;
118 }
119
120 memcpy (buf, &kmap[roff], len);
121
122 if (munmap(kmap, len+sz) != 0)
123 {
124 perror("kmem_mmap: munmap");
125 return -1;
126 }
127
128 return 0;
129}
130
131int read_kcode (unsigned long addr, unsigned char * buf, int len)
132{
133 int fd;
134
135 if (addr == 0UL)
136 {
137 perror("read_kcode: invalid input");
138 return -1;
139 }
140
141 fd = open ("/dev/kmem", O_RDONLY);
142
143 if (fd < 0)
144 {
145 if (verbose)
146 fprintf(stderr, "read_kcode: /dev/kmem failed, now trying /proc/kmem\n");
147
148 if (0 != access("/proc/kmem", R_OK))
149 {
150 perror("read_kcode: access /proc/kmem");
151
152 fprintf(stderr, "\n");
153
154 fprintf(stderr, "NOTE: kern_head: apparently you have no /dev/kmem, and the\n");
155 fprintf(stderr, " samhain_kmem module is not loaded\n");
156 fprintf(stderr, " If you get this message, please proceed as follows:\n");
157 fprintf(stderr, " $ make samhain_kmem.ko\n");
158 fprintf(stderr, " $ sudo /sbin/insmod samhain_kmem.ko; sudo ./kern_head > sh_ks.h; sudo /sbin/rmmod samhain_kmem\n");
159 fprintf(stderr, " $ make\n\n");
160 exit (EXIT_FAILURE);
161 }
162 fd = open ("/proc/kmem", O_RDONLY);
163 }
164
165 if (fd < 0)
166 {
167 perror("read_kcode: open /dev/kmem and /proc/kmem");
168 return -1;
169 }
170
171 if (kmem_mmap(fd, addr, buf, len) < 0)
172 {
173 close (fd);
174 return -1;
175 }
176
177 close (fd);
178
179 return 0;
180}
181
182int get_dispatch (int * qq)
183{
184 int i;
185
186 if (addr_system_call == 0L || sh_sys_call.addr_sys_call_table == 0L)
187 {
188 fprintf(stderr, "get_dispatch: invalid data\n");
189 return -1;
190 }
191
192 if (0 != read_kcode (addr_system_call, system_call_code, SYS_CODE_SIZE))
193 {
194 fprintf(stderr, "get_dispatch: could not read system_call code\n");
195 return -1;
196 }
197
198 for (i = 0; i < (SYS_CODE_SIZE - 4); ++i)
199 {
200 if (system_call_code[i] == sh_sys_call.str_sys_call_table[0] &&
201 system_call_code[i+1] == sh_sys_call.str_sys_call_table[1] &&
202 system_call_code[i+2] == sh_sys_call.str_sys_call_table[2] &&
203 system_call_code[i+3] == sh_sys_call.str_sys_call_table[3])
204 {
205 /*
206 fprintf(stderr, "INFO: get_dispatch: found sys_call_table in "\
207 "system_call code at %d\n", i);
208 */
209 *qq = i;
210 return 0;
211 }
212 }
213 fprintf(stderr,
214 "get_dispatch: did not find sys_call_table in system_call code\n");
215 fprintf(stderr,
216 "** This indicates that either your System.map does not match\n");
217 fprintf(stderr,
218 "** the currently running kernel, or that your System.map does\n");
219 fprintf(stderr,
220 "** not provide the required information, and thus use of\n");
221 fprintf(stderr,
222 "** the --with-kcheck option is not possible\n");
223 return -1;
224}
225
226unsigned long get_symbol_from_systemmap (char * systemmap,
227 char * symbol, char flag)
228{
229 FILE * fp;
230 char buf[512], addr[32], * p;
231 unsigned long retval = 0;
232#if defined(__x86_64__) || defined(__amd64__)
233 int off = 8;
234#else
235 int off = 0;
236#endif
237
238 fp = fopen (systemmap, "r");
239
240 if (!fp)
241 {
242 fprintf(stderr, "error opening <%s>\n", systemmap);
243 perror("get_symbol_from_systemmap: fopen");
244 return -1;
245 }
246 while (fgets(buf, 512, fp) != NULL)
247 {
248 if (buf[9+off] != flag)
249 continue;
250
251 p = strchr(buf, '\n');
252 if (p != NULL)
253 *p = '\0';
254
255 if (0 != strcmp(&buf[11+off], symbol))
256 continue;
257
258 addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
259 strncat(&addr[2], buf, 8+off);
260
261 retval = strtoul(addr, NULL, 0);
262 if (retval == ULONG_MAX)
263 {
264 perror("get_symbol_from_systemmap");
265 return -1;
266 }
267 }
268 fclose(fp);
269 return retval;
270}
271
272
273/* returns the number N of entries in syscall table
274 * (0 .. N-1) with valid syscalls
275 */
276int fill_smap(smap_entry * sh_smap, int num)
277{
278 FILE * fp;
279 char buf[512], addr[32], name[128];
280 int i, j, count = 0, maxcall = 0;
281#if defined(__x86_64__) || defined(__amd64__)
282 int off = 8;
283#else
284 int off = 0;
285#endif
286
287 fp = fopen (SYSTEMMAP, "r");
288
289 if (!fp)
290 {
291 perror("fill_smap: fopen");
292 fprintf(stderr, "fill_smap: error opening <%s>\n", SYSTEMMAP);
293 return -1;
294 }
295
296 /* initialize
297 */
298 sh_sys_call.addr_sys_call_table = 0L;
299
300 while (fgets(buf, 512, fp) != NULL)
301 {
302
303 if ( ( (buf[9+off] == 'D') || (buf[9+off] == 'd') ||
304 (buf[9+off] == 'R') || (buf[9+off] == 'r')) &&
305 0 == strncmp("sys_call_table", &buf[11+off], 14))
306 {
307 printf("/* found sys_call_table */\n");
308 /* --- copy symbol address ---
309 */
310 addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
311 strncat(&addr[2], buf, 8+off);
312 addr[10+off] = '\0';
313
314 sh_sys_call.addr_sys_call_table = strtoul(addr, NULL, 0);
315 if (sh_sys_call.addr_sys_call_table == ULONG_MAX)
316 {
317 perror("fill_smap");
318 return -1;
319 }
320 else
321 {
322 printf("#define SH_SYS_CALL_TABLE %s\n", addr);
323 }
324 }
325
326 if (buf[9+off] != 'T')
327 continue;
328
329 if (0 == strncmp("system_call", &buf[11+off], 11))
330 {
331 printf("/* found system_call */\n");
332 /* --- copy symbol address ---
333 */
334 addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
335 strncat(&addr[2], buf, 8+off);
336 addr[10+off] = '\0';
337 addr_system_call = strtoul(addr, NULL, 0);
338 if (addr_system_call == ULONG_MAX)
339 {
340 perror("fill_smap");
341 return -1;
342 }
343 }
344
345
346 if ( (buf[11+off]!='s' || buf[12+off]!='y' ||
347 buf[13+off]!='s' || buf[14+off]!='_') &&
348 (buf[11+off]!='o' || buf[12+off]!='l' ||
349 buf[13+off]!='d' || buf[14+off]!='_'))
350 continue;
351
352 for (i = 0; i < num; ++i)
353 {
354 for (j = 0; j < 127; ++j)
355 {
356 if (buf[11+off+j] == '\n' || buf[11+off+j] == '\0')
357 {
358 name[j] = '\0';
359 break;
360 }
361 name[j] = buf[11+off+j];
362 }
363
364
365 if (0 == strcmp(name, sh_smap[i].name))
366 {
367
368 /* --- copy symbol address ---
369 */
370 addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
371 strncat(&addr[2], buf, 8+off);
372 addr[10+off] = '\0';
373 sh_smap[i].addr = strtoul(addr, NULL, 0);
374 if (sh_smap[i].addr == ULONG_MAX)
375 {
376 perror("fill_smap");
377 return -1;
378 }
379 ++count;
380 if (i > maxcall) maxcall = i;
381 /* printf("maxcall = %d\n", maxcall); */
382 /* break; */
383 }
384 }
385 }
386 fclose(fp);
387
388 if ((count > 0) && (maxcall > 0))
389 return maxcall+1;
390 else
391 return count;
392}
393
394
395int main(int argc, char * argv[])
396{
397 int i, count, maxcall, qq;
398 smap_entry sh_smap[SH_MAXCALLS];
399 struct utsname utbuf;
400 char *p = NULL;
401
402 unsigned long proc_root;
403 unsigned long proc_root_iops;
404 unsigned long proc_root_lookup;
405
406 unsigned long addr_ni_syscall = 0;
407
408 int major, minor, micro, is64 = 0;
409
410 if (argc > 1)
411 {
412 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
413 usage(EXIT_SUCCESS);
414 else if (strcmp(argv[1], "-v") == 0 ||
415 strcmp(argv[1], "--verbose") == 0)
416 verbose = 1;
417 }
418
419 if (0 != uname(&utbuf))
420 {
421 perror("kern_head: uname");
422 exit (EXIT_FAILURE);
423 }
424
425 if (strncmp(utbuf.release, SH_KERNEL_VERSION, 3) != 0)
426 {
427 fprintf(stderr, "kern_head: current kernel version %s does not match\n",
428 utbuf.release);
429 fprintf(stderr, "kern_head: %s from config.h\n", SH_KERNEL_VERSION);
430 fprintf(stderr, "kern_head: continuing with %s\n", SH_KERNEL_VERSION);
431
432 p = SH_KERNEL_VERSION;
433 } else {
434 p = utbuf.release;
435 }
436
437 if (3 != sscanf(p, "%d.%d.%d", &major, &minor, &micro))
438 {
439 perror("kern_head: sscanf");
440 exit (EXIT_FAILURE);
441 }
442
443 if (major == 2)
444 {
445 if (minor != 4 && minor != 6)
446 {
447 fprintf(stderr, "kern_head: kernel %s not supported\n", p);
448 exit (EXIT_FAILURE);
449 }
450 }
451
452
453 if (utbuf.machine[0] != 'i' || utbuf.machine[2] != '8' ||
454 utbuf.machine[3] != '6')
455 {
456 if (0 != strcmp(utbuf.machine, "x86_64"))
457 {
458 fprintf(stderr, "kern_head: machine %s not supported\n", utbuf.machine);
459 exit (EXIT_FAILURE);
460 }
461 else
462 {
463 is64 = 1;
464 }
465 }
466
467 if (0 != getuid())
468 {
469 fprintf(stderr, "\n");
470
471 fprintf(stderr, "NOTE: kern_head: must run as 'root' (need to read from /dev/kmem)\n");
472 fprintf(stderr, " If you get this message, then proceed as follows:\n");
473 fprintf(stderr, " $ sudo ./kern_head > sh_ks.h\n");
474 fprintf(stderr, " $ make\n\n");
475 exit (EXIT_FAILURE);
476 }
477
478 printf("#ifndef SH_KERN_CALLS_H\n");
479 printf("#define SH_KERN_CALLS_H\n\n");
480
481 printf("\n/* Kernel %s, machine %s, %d bit -- use table callz_2p4 */\n\n",
482 p, utbuf.machine,
483 (is64 == 0) ? 32 : 64,
484 (is64 == 0) ? "syscalls_32" : "syscalls_64");
485
486 /* initiate the system call table
487 */
488 if (is64 == 0)
489 {
490 for (i = 0; i < SH_MAXCALLS; ++i)
491 {
492 if (syscalls_32[i] == NULL)
493 break;
494 strcpy(sh_smap[i].name, syscalls_32[i]);
495 sh_smap[i].addr = 0UL;
496 }
497 if (major > 2 || minor == 6) /* fix syscall map for 2.6 */
498 {
499 strcpy(sh_smap[0].name, "sys_restart_syscall");
500 strcpy(sh_smap[180].name, "sys_pread64");
501 strcpy(sh_smap[181].name, "sys_pwrite64");
502 }
503 }
504 else /* x86_64 */
505 {
506 for (i = 0; i < SH_MAXCALLS; ++i)
507 {
508 if (syscalls_64[i] == NULL)
509 break;
510 strcpy(sh_smap[i].name, syscalls_64[i]);
511 sh_smap[i].addr = 0UL;
512 }
513 }
514
515 count = i;
516
517 /* get the actual number of the highest syscall and use no more.
518 * get sys_call_table and system_call
519 */
520 maxcall = fill_smap(sh_smap, count);
521 if ( maxcall < 0)
522 {
523 printf("#endif\n");
524 fprintf(stderr, "kern_head: fill_smap failed\n");
525 exit (EXIT_FAILURE);
526 }
527
528 if (addr_system_call == 0L)
529 {
530 printf("#endif\n");
531 fprintf(stderr,
532 "kern_head: address of system_call not found in System.map\n");
533 fprintf(stderr,
534 "** This indicates that your System.map does not provide\n");
535 fprintf(stderr,
536 "** the required information, and thus use of the\n");
537 fprintf(stderr,
538 "** --with-kcheck option is not possible\n");
539 exit (EXIT_FAILURE);
540 }
541
542 for (i = 0; i < maxcall; ++i)
543 {
544 if (0 == strcmp(sh_smap[i].name, "sys_ni_syscall"))
545 {
546 addr_ni_syscall = sh_smap[i].addr;
547 break;
548 }
549 }
550
551 if (minor < 6)
552 {
553 maxcall = (maxcall > 256) ? 256 : maxcall;
554 }
555
556 for (i = 0; i < maxcall; ++i)
557 {
558 if (sh_smap[i].addr == 0UL)
559 {
560 if (verbose > 0)
561 fprintf(stderr, "** unknown syscall **: [%s]\n", sh_smap[i].name);
562 strcpy(sh_smap[i].name, "sys_ni_syscall");
563 sh_smap[i].addr = addr_ni_syscall;
564 }
565 }
566
567
568 /* get the location of the syscall table address within system_call
569 */
570 if ( get_dispatch (&qq) < 0)
571 {
572 printf("#endif\n");
573 fprintf(stderr, "kern_head: get_dispatch failed\n");
574 exit (EXIT_FAILURE);
575 }
576
577 if (qq <= 252)
578 printf("#define SYS_CALL_LOC %d\n", qq);
579 else
580 {
581 printf("#endif\n");
582 fprintf(stderr, "kern_head: SYS_CALL_LOC (%d) too large\n", qq);
583 exit(EXIT_FAILURE);
584 }
585 printf("#define SH_SYS_CALL_ADDR %#lx\n\n", addr_system_call);
586
587 printf("static unsigned char system_call_code[256] = { 0 };\n");
588
589 printf("#define SH_MAXCALLS %d\n\n", maxcall);
590
591#ifdef SH_IDT_TABLE
592 printf("static unsigned char idt_table[2048] = { 0 };\n");
593#endif
594
595 printf("typedef struct _sh_syscall_t {\n");
596#ifdef SH_SYSCALL_CODE
597 printf(" unsigned int code[2]; /* 8 bytes */\n");
598#endif
599 printf(" unsigned long addr;\n");
600 printf(" char * name;\n");
601 printf("} sh_syscall_t;\n\n");
602
603 printf("static sh_syscall_t sh_syscalls[] = {\n");
604
605 for (i = 0; i < maxcall; ++i)
606 {
607#ifdef SH_SYSCALL_CODE
608 printf(" /* %03d */ { { 0, 0 }, 0, N_(%c%s%c) },\n",
609 i, '"', sh_smap[i].name, '"');
610#else
611 printf(" /* %03d */ { 0, N_(%c%s%c) },\n",
612 i, '"', sh_smap[i].name, '"');
613#endif
614 }
615#ifdef SH_SYSCALL_CODE
616 printf(" /* eof */ { { 0x00000000, 0x00000000 }, 0x00000000, NULL }\n");
617#else
618 printf(" /* eof */ { 0x00000000, NULL }\n");
619#endif
620 printf("};\n\n");
621
622
623 /* get proc addresses
624 */
625 proc_root = get_symbol_from_systemmap (SYSTEMMAP,
626 "proc_root", 'D');
627 if (proc_root == 0)
628 {
629 proc_root = get_symbol_from_systemmap (SYSTEMMAP,
630 "proc_root", 'd');
631 }
632 if (proc_root == 0)
633 {
634 proc_root = get_symbol_from_systemmap (SYSTEMMAP,
635 "proc_root", 'R');
636 }
637 if (proc_root != 0) {
638 printf("#define PROC_ROOT_LOC %#lx\n\n", proc_root);
639 }
640
641 proc_root_lookup = get_symbol_from_systemmap (SYSTEMMAP,
642 "proc_root_lookup", 't');
643 if (proc_root_lookup == 0)
644 {
645 proc_root_lookup = get_symbol_from_systemmap (SYSTEMMAP,
646 "proc_root_lookup", 'T');
647 }
648 if (proc_root_lookup != 0) {
649 printf("#define PROC_ROOT_LOOKUP_LOC %#lx\n\n", proc_root_lookup);
650 }
651
652 proc_root_iops = get_symbol_from_systemmap (SYSTEMMAP,
653 "proc_root_inode_operations",
654 'd');
655 if (proc_root_iops == 0)
656 {
657 proc_root_iops = get_symbol_from_systemmap (SYSTEMMAP,
658 "proc_root_inode_operations",
659 'D');
660 }
661 if (proc_root_iops == 0)
662 {
663 proc_root_iops = get_symbol_from_systemmap (SYSTEMMAP,
664 "proc_root_inode_operations",
665 'R');
666 }
667 if (proc_root_iops != 0) {
668 printf("#define PROC_ROOT_IOPS_LOC %#lx\n\n", proc_root_iops);
669 }
670
671 if (KERNEL_VERSION(major,minor,micro) >= KERNEL_VERSION(2,6,17))
672 {
673 printf("#define TWO_SIX_SEVENTEEN_PLUS 1\n\n");
674 }
675
676 printf("#endif\n");
677
678 exit (EXIT_SUCCESS);
679}
680
681/* if defined(HOST_IS_LINUX) */
682#endif
683
684/************************************************************
685 *
686 *
687 * FreeBSD Implementation
688 *
689 ************************************************************/
690
691#if defined(HOST_IS_FREEBSD) || defined(__OpenBSD__)
692
693#include <stdlib.h>
694#include <unistd.h>
695#include <string.h>
696#include <err.h>
697#include <kvm.h>
698#include <fcntl.h>
699#include <nlist.h>
700#include <limits.h>
701#include <sys/types.h>
702#include <sys/utsname.h>
703
704#ifdef __FreeBSD__
705#include <sys/sysent.h>
706#endif
707
708#include <sys/syscall.h>
709
710#ifndef SYS_MAXSYSCALL
711#define SYS_MAXSYSCALL 512
712#endif
713
714/* number of system calls */
715#define SH_MAXCALLS 512
716#include "kern_head.h"
717static int verbose = 0;
718
719#ifdef __OpenBSD__
720struct proc;
721struct sysent {
722 short sy_narg;
723 short sy_argsize;
724 int (*sy_call)(struct proc *, void *, register_t *);
725};
726#endif
727
728typedef struct _smap_entry {
729 unsigned int code[2]; /* 8 bytes */
730 unsigned long addr;
731 char name[64];
732} smap_entry;
733
734union {
735 unsigned long addr_sys_call_table;
736 unsigned char str_sys_call_table[sizeof(unsigned long)];
737} sh_sys_call;
738
739struct nlist sys_list[SYS_MAXSYSCALL+1];
740
741struct nlist list[2];
742
743
744int main(int argc, char * argv[])
745{
746 int i, count, which;
747 smap_entry sh_smap[SYS_MAXSYSCALL];
748 struct utsname utbuf;
749 char errbuf[_POSIX2_LINE_MAX];
750
751 struct sysent sy;
752 unsigned long offset = 0L;
753 kvm_t *kd;
754
755 list[0].n_name = "_sysent";
756 list[1].n_name = NULL;
757
758 if (argc > 1)
759 {
760 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
761 usage(EXIT_SUCCESS);
762 else if (strcmp(argv[1], "-v") == 0 ||
763 strcmp(argv[1], "--verbose") == 0)
764 verbose = 1;
765 }
766
767 if (0 != uname(&utbuf))
768 {
769 perror("kern_head: uname");
770 exit (EXIT_FAILURE);
771 }
772
773#ifdef __OpenBSD__
774 if (utbuf.release[0] == '3')
775 which = 38;
776 else if (utbuf.release[0] == '4')
777 which = 40;
778#else
779 if (utbuf.release[0] == '4')
780 which = 4;
781 else if (utbuf.release[0] == '5')
782 which = 5;
783 else if (utbuf.release[0] == '6')
784 which = 5;
785#endif
786 else
787 {
788 fprintf(stderr, "kern_head: kernel %s not supported\n", utbuf.release);
789 exit (EXIT_FAILURE);
790 }
791
792 if (utbuf.machine[0] != 'i' || utbuf.machine[2] != '8' ||
793 utbuf.machine[3] != '6')
794 {
795 fprintf(stderr, "kern_head: machine %s not supported\n", utbuf.machine);
796 exit (EXIT_FAILURE);
797 }
798
799 if (0 != getuid())
800 {
801 fprintf(stderr, "\n");
802 fprintf(stderr, "NOTE: kern_head: must run as 'root' ");
803 fprintf(stderr, "(need to read from kernel)\n");
804 fprintf(stderr, " If you get this message, then proceed ");
805 fprintf(stderr, "as follows:\n");
806 fprintf(stderr, " $ su\n");
807 fprintf(stderr, " $ ./kern_head > sh_ks.h\n");
808 fprintf(stderr, " $ exit\n");
809 fprintf(stderr, " $ make\n\n");
810 exit (EXIT_FAILURE);
811 }
812
813 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
814 if (!kd)
815 {
816 fprintf(stderr, "check_sysent: kvm_openfiles: %s\n", errbuf);
817 exit(EXIT_FAILURE);
818 }
819
820 i = kvm_nlist(kd, list);
821 if (i == -1)
822 {
823 fprintf(stderr, "check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
824 exit(EXIT_FAILURE);
825 }
826 else if (i == 1)
827 {
828 fprintf(stderr, "check_sysent: kvm_nlist: _sysent not found\n");
829 exit(EXIT_FAILURE);
830 }
831 else if (list[0].n_value == 0)
832 {
833 fprintf(stderr, "check_sysent: kvm_nlist: zero address for _sysent\n");
834 exit(EXIT_FAILURE);
835 }
836
837 if (which == 4)
838 printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
839 utbuf.release, utbuf.machine, "callz_fbsd");
840 else if (which == 5 || which == 6)
841 printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
842 utbuf.release, utbuf.machine, "callz_fbsd5");
843 else if (which == 38 || which == 40)
844 printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
845 utbuf.release, utbuf.machine, "callz_obsd");
846
847
848 i = 0;
849 if (which == 4) {
850 while ((callz_fbsd[i] != NULL) && (i < SYS_MAXSYSCALL))
851 {
852 sys_list[i].n_name = callz_fbsd[i];
853 /* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
854 ++i;
855 }
856 if ((utbuf.release[1] == '.') && (utbuf.release[2] == '1') &&
857 (utbuf.release[3] == '0'))
858 {
859 sys_list[336].n_name = callz_fbsd[151]; /* sendfile -> nosys */
860 }
861 } else if (which == 5 || which == 6) {
862 while ((callz_fbsd5[i] != NULL) && (i < SYS_MAXSYSCALL))
863 {
864 sys_list[i].n_name = callz_fbsd5[i];
865 /* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
866 ++i;
867 }
868 }
869 else if (which == 38 || which == 40) {
870 while ((callz_obsd[i] != NULL) && (i < SYS_MAXSYSCALL))
871 {
872 sys_list[i].n_name = callz_obsd[i];
873 /* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
874 ++i;
875 }
876 }
877
878 count = i;
879 sys_list[i].n_name = NULL;
880
881 i = kvm_nlist(kd, sys_list);
882 if (i == -1)
883 {
884 fprintf(stderr, "check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
885 /* exit(EXIT_FAILURE); */
886 }
887 else if (i != 0 && verbose != 0)
888 {
889 fprintf(stderr, "check_sysent: kvm_nlist: %d out of %d invalid.\n",
890 i, count);
891 fprintf(stderr, " Probably the table in kern_head.h\n");
892 fprintf(stderr, " is not for your kernel version.\n");
893 fprintf(stderr, " (No reason to worry, kcheck will "\
894 "work anyway)\n\n");
895 }
896
897 for (i = 0; i < count /* SYS_MAXSYSCALL */; i++)
898 {
899 if (NULL == sys_list[i].n_name)
900 break;
901 if (!sys_list[i].n_value && 0 != strcmp(sys_list[i].n_name, "_nosys")
902 && verbose != 0)
903 {
904 fprintf(stderr,"check_sysent: not found: slot %03d [%s]\n",
905 i, sys_list[i].n_name);
906 /* exit(EXIT_FAILURE); */
907 }
908 offset = list[0].n_value + (i*sizeof(struct sysent));
909 if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
910 {
911 fprintf(stderr,"check_sysent: kvm_read: %s\n", kvm_geterr(kd));
912 exit(EXIT_FAILURE);
913 }
914
915 if (verbose > 0)
916 fprintf(stderr, "(kvm_nlist) %#lx %#lx (sysent[%03d]) %03d [%s]\n",
917 (unsigned long) sys_list[i].n_value,
918 (unsigned long) sy.sy_call,
919 i, i, sys_list[i].n_name);
920
921 if((unsigned long)sy.sy_call != sys_list[i].n_value &&
922 sys_list[i].n_value != 0 &&
923 0 != strcmp(sys_list[i].n_name, "_nosys") &&
924 (unsigned long)sy.sy_call != sys_list[151].n_value)
925 {
926 fprintf(stderr,
927 "WARNING: (kvm_nlist) %#lx != %#lx (sysent[%03d]) %03d [%s]\n",
928 (unsigned long) sys_list[i].n_value,
929 (unsigned long) sy.sy_call,
930 i, i, sys_list[i].n_name);
931 }
932 sh_smap[i].addr = (unsigned long) sy.sy_call;
933 strncpy(sh_smap[i].name, sys_list[i].n_name, 64);
934 if(kvm_read(kd, (unsigned int) sy.sy_call, &(sh_smap[i].code[0]),
935 2 * sizeof(unsigned int)) < 0)
936 {
937 fprintf(stderr,"check_sysent: kvm_read: %s\n", kvm_geterr(kd));
938 exit(EXIT_FAILURE);
939 }
940 }
941
942 if(kvm_close(kd) < 0)
943 {
944 fprintf(stderr,"check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
945 exit(EXIT_FAILURE);
946 }
947
948 printf("#ifndef SH_KERN_CALLS_H\n");
949 printf("#define SH_KERN_CALLS_H\n\n");
950
951 printf("#define SH_MAXCALLS %d\n\n", count);
952
953 printf("typedef struct _sh_syscall_t {\n");
954 printf(" unsigned int code[2]; /* 8 bytes */\n");
955 printf(" unsigned long addr;\n");
956 printf(" char * name;\n");
957 printf("} sh_syscall_t;\n\n");
958
959 printf("static sh_syscall_t sh_syscalls[] = {\n");
960 for (i = 0; i < count; ++i) {
961 printf(" /* %03d */ {{ 0x%-8.8x, 0x%-8.8x }, 0x%-8.8lx, N_(%c%s%c) },\n",
962 i, sh_smap[i].code[0], sh_smap[i].code[1],
963 sh_smap[i].addr, '"', sh_smap[i].name, '"');
964 }
965 printf(" /* eof */ { { 0x00000000, 0x00000000 }, 0x00000000, NULL }\n");
966 printf("};\n\n");
967 printf("#endif\n");
968 return 0;
969}
970/* if defined(HOST_IS_FREEBSD) */
971#endif
972
973/* #if defined(SH_USE_KERN) */
974#else
975
976#include <stdio.h>
977#include <stdlib.h>
978
979int main()
980{
981 printf("#ifndef SH_KERN_CALLS_H\n");
982 printf("#define SH_KERN_CALLS_H\n\n");
983
984 printf("/* Dummy header. */\n\n");
985
986 printf("typedef struct _sh_syscall_t {\n");
987 printf(" unsigned long addr;\n");
988 printf(" char * name;\n");
989 printf("} sh_syscall_t;\n\n");
990
991 printf("#endif\n");
992
993 return (EXIT_SUCCESS);
994}
995
996/* #ifdef SH_USE_KERN */
997#endif
Note: See TracBrowser for help on using the repository browser.