source: trunk/src/kern_head.c@ 343

Last change on this file since 343 was 287, checked in by katerina, 14 years ago

Minor changes.

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