source: trunk/src/kern_head.c@ 285

Last change on this file since 285 was 279, checked in by katerina, 15 years ago

Fix for tickets #200 to #206 (kernel check, login checks, bugfixes).

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