source: trunk/src/kern_head.c @ 360

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

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

File size: 24.1 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    {
[346]145      if (verbose)
146        fprintf(stderr, "read_kcode: /dev/kmem failed, now trying /proc/kmem\n");
147
[279]148      if (0 != access("/proc/kmem", R_OK)) 
149        {
150          perror("read_kcode: access /proc/kmem");
151
152          fprintf(stderr, "\n");
153     
[287]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");
[279]157          fprintf(stderr, "       $ make samhain_kmem.ko\n");
[287]158          fprintf(stderr, "       $ sudo /sbin/insmod samhain_kmem.ko; sudo ./kern_head > sh_ks.h; sudo /sbin/rmmod samhain_kmem\n");
[279]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");
[1]168      return -1;
169    }
[279]170
[41]171  if (kmem_mmap(fd, addr, buf, len) < 0)
[1]172    {
[41]173      close (fd);
[1]174      return -1;
175    }
[279]176
[41]177  close (fd);
[279]178
[1]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;
[279]230  char buf[512], addr[32], * p;
[1]231  unsigned long retval = 0;
[279]232#if defined(__x86_64__) || defined(__amd64__)
233  int off = 8;
234#else
235  int off = 0;
236#endif
[1]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    {
[279]248      if (buf[9+off] != flag)
[1]249        continue;
250
251      p = strchr(buf, '\n');
252      if (p != NULL)
253        *p = '\0';
254
[279]255      if (0 != strcmp(&buf[11+off], symbol))
[1]256        continue;
257
258      addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
[279]259      strncat(&addr[2], buf, 8+off);
[1]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]279  char buf[512], addr[32], name[128];
[1]280  int  i, j, count = 0, maxcall = 0;
[279]281#if defined(__x86_64__) || defined(__amd64__)
282  int off = 8;
283#else
284  int off = 0;
285#endif
[1]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     
[279]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))
[1]306        {
307          printf("/* found sys_call_table */\n");
308          /* --- copy symbol address ---
309           */
310          addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
[279]311          strncat(&addr[2], buf, 8+off);
312          addr[10+off] = '\0';
313
[1]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
[279]326      if (buf[9+off] != 'T')
[1]327        continue;
328
[279]329      if (0 == strncmp("system_call", &buf[11+off], 11))
[1]330        {
331          printf("/* found system_call */\n");
332          /* --- copy symbol address ---
333           */
334          addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
[279]335          strncat(&addr[2], buf, 8+off);
336          addr[10+off] = '\0';
[1]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
[279]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]!='_'))
[1]350        continue;
351
352      for (i = 0; i < num; ++i)
353        {
[279]354          for (j = 0; j < 127; ++j)
[1]355            {
[279]356              if (buf[11+off+j] == '\n' || buf[11+off+j] == '\0')
[1]357                {
358                  name[j] = '\0';
359                  break;
360                }
[279]361              name[j] = buf[11+off+j];
[1]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';
[279]371              strncat(&addr[2], buf, 8+off);
372              addr[10+off] = '\0';
[1]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);
[279]387
[1]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
[279]408  int major, minor, micro, is64 = 0;
409
[1]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
[279]437  if (3 != sscanf(p, "%d.%d.%d", &major, &minor, &micro))
[51]438    {
[279]439      perror("kern_head: sscanf");
440      exit (EXIT_FAILURE);
[51]441    }
[279]442
[360]443  if (major == 2)
[1]444    {
[360]445      if (minor != 4 && minor != 6)
446        {
447          fprintf(stderr, "kern_head: kernel %s not supported\n", p);
448          exit (EXIT_FAILURE);
449        }
[1]450    }
451
452 
453  if (utbuf.machine[0] != 'i' || utbuf.machine[2] != '8' || 
454      utbuf.machine[3] != '6')
455    {
[279]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        }
[1]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");
[279]473      fprintf(stderr, "       $ sudo ./kern_head > sh_ks.h\n");
[1]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
[279]481  printf("\n/* Kernel %s, machine %s, %d bit -- use table callz_2p4 */\n\n", 
[1]482         p, utbuf.machine,
[279]483         (is64 == 0) ? 32 : 64,
484         (is64 == 0) ? "syscalls_32" : "syscalls_64");
[1]485
486  /* initiate the system call table
487   */
[279]488  if (is64 == 0)
[1]489    {
[279]490      for (i = 0; i < SH_MAXCALLS; ++i)
[1]491        {
[279]492          if (syscalls_32[i] == NULL)
[1]493            break;
[279]494          strcpy(sh_smap[i].name, syscalls_32[i]);
495          sh_smap[i].addr    = 0UL;
[1]496        }
[360]497      if (major > 2 || minor == 6) /* fix syscall map for 2.6 */
[1]498        {
[279]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)
[1]509            break;
[279]510          strcpy(sh_smap[i].name, syscalls_64[i]);
511          sh_smap[i].addr    = 0UL;
[1]512        }
513    }
514
515  count = i;
516
[279]517  /* get the actual number of the highest syscall and use no more.
[1]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    }
[279]527
[1]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    }
[279]550
551  if (minor < 6)
[1]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
[279]671  if (KERNEL_VERSION(major,minor,micro) >= KERNEL_VERSION(2,6,17)) 
672    {
673      printf("#define TWO_SIX_SEVENTEEN_PLUS 1\n\n");
674    }
[51]675
[1]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
[9]773#ifdef __OpenBSD__
774  if      (utbuf.release[0] == '3')
775    which = 38;
[92]776  else if (utbuf.release[0] == '4')
777    which = 40;
[9]778#else
[1]779  if      (utbuf.release[0] == '4')
780    which = 4;
781  else if (utbuf.release[0] == '5')
782    which = 5;
[9]783  else if (utbuf.release[0] == '6')
784    which = 5;
785#endif
[1]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' ");
[96]803      fprintf(stderr, "(need to read from kernel)\n");
[1]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    }
[9]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    }
[1]836
837  if (which == 4)
838    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n", 
839                 utbuf.release, utbuf.machine, "callz_fbsd");
[9]840  else if (which == 5 || which == 6)
[1]841    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
842                 utbuf.release, utbuf.machine, "callz_fbsd5");
[92]843  else if (which == 38 || which == 40)
[9]844    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
845                 utbuf.release, utbuf.machine, "callz_obsd");
[1]846     
[9]847     
[1]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      {
[9]859        sys_list[336].n_name = callz_fbsd[151]; /* sendfile -> nosys */
[1]860      }
[9]861  } else if (which == 5 || which == 6) {
[1]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  }
[92]869  else if (which == 38 || which == 40) {
[9]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 
[1]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);
[9]891        fprintf(stderr, "              Probably the table in kern_head.h\n");
[1]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") &&
[9]924         (unsigned long)sy.sy_call != sys_list[151].n_value) 
[1]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.