source: trunk/src/sh_kern.c @ 425

Last change on this file since 425 was 425, checked in by katerina, 9 years ago

Fix for tickets #329, #330, #331, #332

File size: 51.2 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 2001 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20
21#include "config_xor.h"
22
23#define SH_SYSCALL_CODE
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <unistd.h>
33#include <errno.h>
34#include <limits.h>
35#include <sys/wait.h>
36#include <signal.h>
[41]37#include <sys/mman.h>
[1]38
39
40#ifdef SH_USE_KERN
41
42#undef  FIL__
43#define FIL__  _("sh_kern.c")
44
45#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
46
47#if TIME_WITH_SYS_TIME
48#include <sys/time.h>
49#include <time.h>
50#else
51#if HAVE_SYS_TIME_H
52#include <sys/time.h>
53#else
54#include <time.h>
55#endif
56#endif
57
58
59#include "samhain.h"
[131]60#include "sh_pthread.h"
[1]61#include "sh_utils.h"
62#include "sh_error.h"
63#include "sh_modules.h"
64#include "sh_kern.h"
65#include "sh_ks_xor.h"
66
67#include "sh_unix.h"
68#include "sh_hash.h"
69
70
71
72sh_rconf sh_kern_table[] = {
73  {
74    N_("severitykernel"),
75    sh_kern_set_severity
76  },
77  {
78    N_("kernelcheckactive"),
79    sh_kern_set_activate
80  },
81  {
82    N_("kernelcheckinterval"),
83    sh_kern_set_timer
84  },
85  {
86    N_("kernelcheckidt"),
87    sh_kern_set_idt
88  },
89  {
[223]90    N_("kernelcheckpci"),
91    sh_kern_set_pci
92  },
93  {
[425]94    N_("kernelcheckproc"),
95    sh_kern_set_proc
96  },
97  {
[1]98    N_("kernelsystemcall"),
99    sh_kern_set_sc_addr
100  },
101  {
102    N_("kernelsyscalltable"),
103    sh_kern_set_sct_addr
104  },
105  {
106    N_("kernelprocrootlookup"),
107    sh_kern_set_proc_root_lookup
108  },
109 {
110    N_("kernelprocrootiops"),
111    sh_kern_set_proc_root_iops
112  },
113  {
114    N_("kernelprocroot"),
115    sh_kern_set_proc_root
116  },
117  {
118    NULL,
119    NULL
120  },
121};
122
123
124static time_t  lastcheck;
125static int     ShKernActive   = S_TRUE;
126static int     ShKernInterval = 300;
127static int     ShKernSeverity = SH_ERR_SEVERE;
128static int     ShKernDelay    = 100; /* milliseconds */
129static int     ShKernIDT      = S_TRUE;
[223]130static int     ShKernPCI      = S_TRUE;
[425]131static int     ShKernPROC     = S_TRUE;
[1]132
133/* The address of system_call
134 */
135#ifdef SH_SYS_CALL_ADDR
136static unsigned long system_call_addr = SH_SYS_CALL_ADDR;
137#else
138static unsigned long system_call_addr = 0;
139#endif
140
141/* The address of the sys_call_table
142 */
143#ifdef SH_SYS_CALL_TABLE
[279]144static unsigned long  kaddr = SH_SYS_CALL_TABLE;
[1]145#else
[279]146static unsigned long  kaddr = 0;
[1]147#endif
148
149#ifdef PROC_ROOT_LOC
150static unsigned long proc_root = PROC_ROOT_LOC;
151#else
152static unsigned long proc_root = 0;
153#endif
154#ifdef PROC_ROOT_IOPS_LOC
155static unsigned long proc_root_iops = PROC_ROOT_IOPS_LOC;
156#else
157static unsigned long proc_root_iops = 0;
158#endif
159#ifdef PROC_ROOT_LOOKUP_LOC
160static unsigned long proc_root_lookup = PROC_ROOT_LOOKUP_LOC;
161#else
162static unsigned long proc_root_lookup = 0;
163#endif
164
[93]165/* This is the module 'reconfigure' function, which is a no-op.
166 */
[1]167int sh_kern_null()
168{
169  return 0;
170}
171
[93]172#define SH_KERN_DBPUSH 0
173#define SH_KERN_DBPOP  1
[1]174
175char * sh_kern_db_syscall (int num, char * prefix,
[294]176                           void * in_name, unsigned long * addr,
[1]177                           unsigned int * code1, unsigned int * code2,
178                           int * size, int direction)
179{
[83]180  char            path[128];
181  char          * p = NULL;
[303]182
[83]183  unsigned char * name = (unsigned char *) in_name;
[294]184  struct store2db save;
[1]185
186  sl_snprintf(path, 128, "K_%s_%04d", prefix, num);
187
[303]188  memset(&save, '\0', sizeof(struct store2db));
[294]189
[93]190  if (direction == SH_KERN_DBPUSH) 
[1]191    {
[294]192      save.val0 = *addr;
193      save.val1 = *code1;
194      save.val2 = *code2;
195      save.str  = name;
196      save.size = (name == NULL) ? 0 : (*size);
[1]197
[294]198      sh_hash_push2db (path, &save);
[1]199    }
200  else
201    {
[294]202      p = sh_hash_db2pop (path, &save);
203
204      *addr  = (unsigned long) save.val0;
205      *code1 = (unsigned int)  save.val1;
206      *code2 = (unsigned int)  save.val2;
207
208      *size  = (int)           save.size;
[1]209    }
210  return p;
211}
[93]212
213static char * sh_kern_pathmsg (char * msg, size_t msg_len,
214                               int num, char * prefix,
215                               unsigned char * old, size_t old_len,
216                               unsigned char * new, size_t new_len)
217{
218  size_t k;
219  char   tmp[128];
220  char  *p;
221  char  *linkpath_old;
222  char  *linkpath_new;
[137]223  char   i2h[2];
[93]224
225#ifdef SH_USE_XML
226  sl_snprintf(tmp, sizeof(tmp), _("path=\"K_%s_%04d\" "), 
227              prefix, num);
228#else
229  sl_snprintf(tmp, sizeof(tmp), _("path=<K_%s_%04d> "), 
230              prefix, num);
231#endif
232  sl_strlcpy(msg, tmp, msg_len);
233
234  if (SL_TRUE == sl_ok_muls(old_len, 2) &&
235      SL_TRUE == sl_ok_adds(old_len * 2, 1))
236    linkpath_old = SH_ALLOC(old_len * 2 + 1);
237  else
238    return msg;
239
240  if (SL_TRUE == sl_ok_muls(new_len, 2) &&
241      SL_TRUE == sl_ok_adds(new_len * 2, 1))
242    linkpath_new = SH_ALLOC(new_len * 2 + 1);
243  else
244    return msg;
245
246  for (k = 0; k < old_len; ++k)
247    {
[137]248      p = sh_util_charhex (old[k], i2h);
[93]249      linkpath_old[2*k]   = p[0];
250      linkpath_old[2*k+1] = p[1];
251      linkpath_old[2*k+2] = '\0';
252    }
253
254  for (k = 0; k < new_len; ++k)
255    {
[137]256      p = sh_util_charhex (new[k], i2h);
[93]257      linkpath_new[2*k]   = p[0];
258      linkpath_new[2*k+1] = p[1];
259      linkpath_new[2*k+2] = '\0';
260   
261}
262#ifdef SH_USE_XML
263  sl_strlcat(msg, _("link_old=\""),    msg_len);
264  sl_strlcat(msg, linkpath_old,        msg_len);
265  sl_strlcat(msg, _("\" link_new=\""), msg_len);
266  sl_strlcat(msg, linkpath_new,        msg_len);
267  sl_strlcat(msg, _("\""),             msg_len);
268#else
269  sl_strlcat(msg, _("link_old=<"),     msg_len);
270  sl_strlcat(msg, linkpath_old,        msg_len);
271  sl_strlcat(msg, _(">, link_new=<"),  msg_len);
272  sl_strlcat(msg, linkpath_new,        msg_len);
273  sl_strlcat(msg, _(">"),              msg_len);
274#endif
275
276  SH_FREE(linkpath_old);
277  SH_FREE(linkpath_new);
278
279  return msg;
280}
[1]281 
282#ifdef HOST_IS_LINUX
283
[279]284#ifndef KERNEL_VERSION
285#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
286#endif
287
[93]288/*
289 * Interrupt Descriptor Table
290 */
[162]291#ifdef HAVE_ASM_SEGMENT_H
[93]292#include <asm/segment.h>
[162]293#endif
[93]294
295#define SH_MAXIDT   256
296
297static unsigned char sh_idt_table[SH_MAXIDT * 8];
298
299static char * sh_strseg(unsigned short segment)
[1]300{
[279]301  static int flip = 0;
302  static char one[32];
303  static char two[32];
304
[93]305  switch (segment) {
[162]306#ifdef __KERNEL_CS
[93]307  case __KERNEL_CS:
308    return _("KERNEL_CS");
[162]309#endif
310#ifdef __KERNEL_DS
[93]311  case __KERNEL_DS:
312    return _("KERNEL_DS");
[162]313#endif
314#ifdef __USER_CS
[93]315  case __USER_CS:
316    return _("USER_CS");
[162]317#endif
318#ifdef __USER_DS
[93]319  case __USER_DS:
320    return _("USER_DS");
[162]321#endif
[93]322  default:
[279]323    if (flip == 0)
324      {
325        snprintf(one, sizeof(one), "%hX", segment);
326        flip = 1;
327        return one;
328      }
329    else
330      {
331        snprintf(two, sizeof(two), "%hX", segment);
332        flip = 0;
333        return two;
334      }
[93]335  }
336}
337
338
339static int sh_kern_data_init ()
340{
[1]341  unsigned long store0 = 0;
342  unsigned int  store1 = 0, store2 = 0;
343  int           datasize, i, j;
344  char        * databuf;
345
346  /* system_call code
347   */
348  databuf = sh_kern_db_syscall (0, _("system_call"), 
349                                NULL, &store0, &store1, &store2,
[93]350                                &datasize, SH_KERN_DBPOP);
[1]351  if (datasize == sizeof(system_call_code))
352    {
353      memcpy (system_call_code, databuf, sizeof(system_call_code));
354      SH_FREE(databuf);
355    }
356  else
357    {
358      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
359                      _("system_call_code not found in database"), 
360                      _("sh_kern_data_init"));
361      return -1;
362    }
363
364  /* syscall address and code
365   */ 
366  for (i = 0; i < SH_MAXCALLS; ++i) 
367    {
368      databuf = sh_kern_db_syscall (i, _("syscall"), 
369                                    NULL, &store0, &store1, &store2,
[93]370                                    &datasize, SH_KERN_DBPOP);
[1]371      sh_syscalls[i].addr = store0;
372      if (store0 == 0) {
373        sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, i, MSG_E_SUBGEN,
374                        _("syscall address not found in database"), 
375                        _("sh_kern_data_init"));
376        return -1;
377      }
[93]378
[1]379      sh_syscalls[i].code[0] = (unsigned int) store1; 
380      sh_syscalls[i].code[1] = (unsigned int) store2;
381      if ((store1 == 0) || (store2 == 0)) {
382        sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, i, MSG_E_SUBGEN,
383                        _("syscall code not found in database"), 
384                        _("sh_kern_data_init"));
385      }
[93]386
[1]387      if (databuf != NULL) {
388        SH_FREE(databuf);
389      }
390     
391    }
392
393  if (ShKernIDT == S_TRUE)
394    {
395      for (j = 0; j < SH_MAXIDT; ++j) 
396        {
397          databuf = sh_kern_db_syscall (j, _("idt_table"), 
398                                        NULL, 
399                                        &store0, &store1, &store2,
[93]400                                        &datasize, SH_KERN_DBPOP);
[1]401          if (datasize == 8) {
402            memcpy(&idt_table[j*8], databuf, 8);
403            SH_FREE(databuf);
404          } else {
405            sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, j, MSG_E_SUBGEN,
406                            _("idt table not found in database"), 
407                            _("sh_kern_data_init"));
408            return -1;
409          }
410        }
411    }
412
413  return 0;
414}
415
[83]416
417/*
418 * Defined in include/linux/fs.h
419 */
420
421/* Here. we are only interested in 'lookup'. I.e. the struct
422 * must be <= the real one, and 'lookup' must be at the
423 * correct position.
424 */
[1]425struct inode_operations {
426  int (*create) (int *,int *,int);
427  int * (*lookup) (int *,int *);
428  int (*link) (int *,int *,int *);
429  int (*unlink) (int *,int *);
430  int (*symlink) (int *,int *,const char *);
431  int (*mkdir) (int *,int *,int);
432  int (*rmdir) (int *,int *);
433  int (*mknod) (int *,int *,int,int);
434  int (*rename) (int *, int *,
435                 int *, int *);
[22]436  /* flawfinder: ignore */
[1]437  int (*readlink) (int *, char *,int);
438  int (*follow_link) (int *, int *);
439  void (*truncate) (int *);
440  int (*permission) (int *, int);
441  int (*revalidate) (int *);
442  /*
443    int (*setattr) (int *, int *);
444    int (*getattr) (int *, int *);
445    int (*setxattr) (int *, const char *, void *, size_t, int);
446    ssize_t (*getxattr) (int *, const char *, void *, size_t);
447    ssize_t (*listxattr) (int *, char *, size_t);
448    int (*removexattr) (int *, const char *);
449  */
450};
451
[83]452/*
453 * this one is just for dummy purposes
[51]454 */
[1]455struct file_operations {
456  int (*create) (int *,int *,int);
457};
458
[83]459/* Defined in include/linux/proc_fs.h
460 * Here we are interested in the 'proc_iops' member.
461 */
[1]462struct proc_dir_entry {
463  unsigned short low_ino;
464  unsigned short namelen;
465  const char * name;
466  mode_t mode;
467  nlink_t nlink;
468  uid_t uid;
469  gid_t gid;
[51]470#if defined  TWO_SIX_SEVENTEEN_PLUS
471  /* size is loff_t in 2.6.17+ kernels */
472  unsigned long dummy; 
473#endif
474  unsigned long size;
[1]475  struct inode_operations * proc_iops;
476  struct file_operations * proc_fops;
477  /*
478  get_info_t *get_info;
479  struct module *owner;
480  struct proc_dir_entry *next, *parent, *subdir;
481  void *data;
482  read_proc_t *read_proc;
483  write_proc_t *write_proc;
484  atomic_t count;         
485  int deleted; 
486  */         
487};
488
[93]489
[41]490static int sh_kern_kmem_read (int fd, unsigned long addr, 
491                              unsigned char * buf, int len)
492{
493  if (lseek(fd, addr, SEEK_SET) == (off_t) (-1))
494    {
495      return -1;
496    }
497  if (read(fd, buf, len) < 0)
498    {
499      return -1;
500    }
501  return 0;
502}
503
504static int sh_kern_read_data (int fd, unsigned long addr, 
505                              unsigned char * buf, size_t len)
506{
507  size_t    moff, roff;
508  size_t    sz;
509  char    * kmap;
510
511  /* next, try mmap()
512   */
513  sz = getpagesize(); /* unistd.h */
514
515  moff = ((size_t)(addr/sz)) * sz;                 /* lower page boundary */
516  roff = addr - moff;    /* off relative to lower address of mmapped area */
517
518  kmap = mmap(0, len+sz, PROT_READ, MAP_PRIVATE, fd, moff);/* sys/mman.h */
519
520  if (kmap == MAP_FAILED)
521    {
[286]522      /* then, try read()
523       */
524      if (0 == sh_kern_kmem_read (fd, addr, buf, len))
525        return 0;
526
[192]527      memset(buf, '\0', len);
[41]528      return -1;
529    }
[286]530
[41]531  memcpy (buf, &kmap[roff], len);
532  return munmap(kmap, len+sz);
533}
534
[93]535
536static int check_init (int * init_retval)
[1]537{
538  static int is_init = 0;
539
[93]540  SL_ENTER(_("check_init"));
[1]541
542  if (is_init == 0)
543    {
544      if (sh.flag.checkSum != SH_CHECK_INIT && sh.flag.update != S_TRUE)
545        {
546          if (0 == sh_kern_data_init()) {
547            is_init = 1;
548          } else {
[93]549            sh_error_handle (ShKernSeverity, FIL__, __LINE__, 1, 
[1]550                             MSG_E_SUBGEN,
[93]551                             _("could not initialize kernel check - switching off"),
552                             _("check_init") );
[1]553            ShKernActive = S_FALSE;
[93]554            *init_retval = is_init;
555            SL_RETURN( (-1), _("check_init"));
[1]556          }
557        }
558      else if ((sh.flag.checkSum == SH_CHECK_INIT || 
559                sh.flag.checkSum == SH_CHECK_CHECK) && 
560               (sh.flag.update == S_TRUE))
561        {
562          if (0 == sh_kern_data_init()) {
563            is_init = 1;
564          } else {
[93]565            sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 0, 
[1]566                             MSG_E_SUBGEN,
[93]567                             _("no or incomplete data in baseline database for kernel check"),
568                             _("check_init") );
[1]569          }
570        }
571    }
[93]572  *init_retval = is_init;
573  SL_RETURN( (0), _("check_init"));
574}
[1]575
[93]576#define SH_KERN_SIZ 512
577#define SH_KERN_SCC 256
578
579static void run_child(int kd, int mpipe[2])
580{
581  int j;
582
583  unsigned long kmem_call_table[SH_KERN_SIZ];
584  unsigned int  kmem_code_table[SH_KERN_SIZ][2];
585
586  unsigned char new_system_call_code[SH_KERN_SCC];
587
588  struct inode_operations proc_root_inode;
589  struct proc_dir_entry   proc_root_dir;
590
[252]591  int status = sl_close_fd(FIL__, __LINE__, mpipe[0]);
[93]592
593  setpgid(0, 0);
594         
595  /* Seek to the system call table (at kaddr) and read it into
596   * the kmem_call_table array
[1]597   */
[93]598  if(status == 0)
599    {
600      retry_msleep (0, ShKernDelay); /* milliseconds */
601     
602      if (sh_kern_read_data (kd, kaddr, 
603                             (unsigned char *) &kmem_call_table, 
604                             sizeof(kmem_call_table)))
605        {
606          status = -2;
607        }
608    }
[1]609
[93]610  /*
611   * Seek to the system call address (at sh_syscalls[j].addr) and
612   * read first 8 bytes into the array kmem_code_table[j][] (2 * unsigned int)
613   */
614  if(status == 0)
[1]615    {
[93]616      memset(kmem_code_table, 0, sizeof(kmem_code_table));
617      for (j = 0; j < SH_MAXCALLS; ++j) 
618        {
619          if (sh_syscalls[j].addr == 0UL) {
620            sh_syscalls[j].addr = kmem_call_table[j];
621          }
622
623          if (sh_syscalls[j].name == NULL || 
624              sh_syscalls[j].addr == 0UL)
625            break;
626
627          if ((sh.flag.checkSum == SH_CHECK_INIT || 
628               sh.flag.checkSum == SH_CHECK_CHECK) && 
629              (sh.flag.update == S_TRUE))
630            {
[192]631              if (sh_kern_read_data (kd, kmem_call_table[j], 
632                                     (unsigned char *) &(kmem_code_table[j][0]),
633                                     2 * sizeof(unsigned int)))
634                status = -3;
[93]635            }
636          else
637            {
[192]638              if (sh_kern_read_data (kd, sh_syscalls[j].addr, 
639                                     (unsigned char *) &(kmem_code_table[j][0]),
640                                     2 * sizeof(unsigned int)))
641                status = -4;
[93]642            }
643        }
[1]644    }
[93]645
646  if(status == 0)
647    {
648      /*
649       * Get the address and size of Interrupt Descriptor Table,
650       * and read the content into the global array sh_idt_table[]
651       */
[279]652      struct {
653        char pad[6];
654        unsigned short size;
655        unsigned long  addr;
656      } idt;
657
658      __asm__ volatile ("sidt %0": "=m" (idt.size));
659
660      idt.size = (idt.size + 1)/8;
[93]661     
[279]662      if (idt.size > SH_MAXIDT)
663        idt.size = SH_MAXIDT;
[93]664     
665      memset(sh_idt_table, '\0', SH_MAXIDT*8);
[279]666      if (sh_kern_read_data (kd, idt.addr, 
667                             (unsigned char *) sh_idt_table, idt.size*8))
[192]668        status = -5;
[93]669    }
670
671  /*
672   * Seek to the system_call address (at system_call_addr) and
673   * read first 256 bytes into new_system_call_code[]
674   *
675   * system_call_addr is defined in the include file.
676   */
677  if(status == 0)
678    {
[192]679      if (sh_kern_read_data (kd, system_call_addr, 
680                             (unsigned char *) new_system_call_code, 
681                             SH_KERN_SCC))
682        status = -6;
[93]683    }
[1]684 
[93]685  /*
686   * Seek to proc_root and read the structure.
687   * Seek to proc_root_inode_operations and get the structure.
688   */
689  if(status == 0)
690    {
[192]691      if (sh_kern_read_data (kd, proc_root, 
692                             (unsigned char *) &proc_root_dir, 
693                             sizeof(proc_root_dir)))
694        status = -7;
[277]695    }
696/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
[279]697#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
[277]698  if(status == 0)
699    {
[192]700      if (sh_kern_read_data (kd, proc_root_iops, 
701                             (unsigned char *) &proc_root_inode, 
702                             sizeof(proc_root_inode)))
703        status = -8;
[93]704    }
[277]705#else
[279]706    memset(&proc_root_inode, '\0', sizeof(proc_root_inode));
[277]707#endif
[1]708 
[93]709  /*
710   * Write out data to the pipe
711   */
[192]712  status = write(mpipe[1], &status, sizeof(int));
[93]713
[192]714  if (status > 0)
715    status = write(mpipe[1], &kmem_call_table, sizeof(kmem_call_table));
716 
717  if(status > 0)
718    status = write(mpipe[1], &kmem_code_table, sizeof(kmem_code_table));
719 
720  if(status > 0)
721    status = write(mpipe[1], &sh_idt_table, sizeof(sh_idt_table));
722 
723  if(status > 0)
724    status = write(mpipe[1], new_system_call_code, SH_KERN_SCC);
725 
726  if(status > 0)
727    status = write(mpipe[1], &proc_root_dir, sizeof(proc_root_dir));
728 
729  if(status > 0)
730    status = write(mpipe[1], &proc_root_inode, sizeof(proc_root_inode));
[93]731
732  _exit( (status >= 0) ? 0 : status);
733}
[1]734
[93]735struct sh_kernel_info {
736  unsigned long kmem_call_table[SH_KERN_SIZ];
737  unsigned int  kmem_code_table[SH_KERN_SIZ][2];
738
739  unsigned char new_system_call_code[SH_KERN_SCC];
740
741  struct inode_operations proc_root_inode;
742  struct proc_dir_entry   proc_root_dir;
743};
744
745static int read_from_child(pid_t mpid, int * mpipe, 
746                           struct sh_kernel_info * kinfo)
747{
748  int  res;
749  int  status;
750  long size;
[192]751  int  errcode;
[93]752
[321]753#ifdef WCONTINUED
754      int wflags = WNOHANG|WUNTRACED|WCONTINUED;
755#else
756      int wflags = WNOHANG|WUNTRACED;
757#endif
758
[93]759  /* Close reading side of pipe, and wait some milliseconds
760   */
[252]761  sl_close_fd (FIL__, __LINE__, mpipe[1]);
[93]762  retry_msleep (0, ShKernDelay); /* milliseconds */
763
[192]764  if (sizeof(int) != read(mpipe[0], &errcode, sizeof(int)))
765    status = -3;
[93]766  else
767    status = 0;
768
[192]769  if (errcode)
770    status = errcode - 100;
771
[93]772  if(status == 0)
[1]773    {
[192]774      size = SH_KERN_SIZ * sizeof(unsigned long);
775
776      if (size != read(mpipe[0], &(kinfo->kmem_call_table), size))
777        status = -4;
778      else
779        status = 0;
780    }
781
782  if(status == 0)
783    {
[93]784      size = sizeof(unsigned int) * 2 * SH_KERN_SIZ;
[1]785
[93]786      if (size != read(mpipe[0], &(kinfo->kmem_code_table), size))
787        status = -5;
788      else
789        status = 0;
790    }
791
792  if(status == 0)
793    {
794      memset(sh_idt_table, '\0', SH_MAXIDT*8);
795      if (sizeof(sh_idt_table) != 
796          read(mpipe[0], &sh_idt_table, sizeof(sh_idt_table)))
797        status = -5;
798      else
799        status = 0;
800    }
801
802  if(status == 0)
803    {
804      size = SH_KERN_SCC;
805
806      if (size != read(mpipe[0], &(kinfo->new_system_call_code), size))
807        status = -6;
808      else
809        status = 0;
810    }
811 
812  if(status == 0)
813    {
814      size = sizeof (struct proc_dir_entry);
815
816      if (size != read(mpipe[0], &(kinfo->proc_root_dir), size))
817        status = -7;
818      else
819        status = 0;
820    }
821
822  if(status == 0)
823    {
824      size = sizeof (struct inode_operations);
825
826      if (size != read(mpipe[0], &(kinfo->proc_root_inode), size))
827        status = -8;
828      else
829        status = 0;
830    }
831
832  if (status < 0)
[321]833    res = waitpid(mpid, NULL,    wflags);
[93]834  else 
835    {
[321]836      res = waitpid(mpid, &status, wflags);
[93]837      if (res == 0 && 0 != WIFEXITED(status))
838        status = WEXITSTATUS(status);
839    }
[252]840  sl_close_fd (FIL__, __LINE__, mpipe[0]);
[93]841  if (res <= 0)
842    {
843      aud_kill(FIL__, __LINE__, mpid, 9);
844      waitpid(mpid, NULL, 0);
845    }
846  return status;
847}
848
849
850static void check_idt_table(int is_init)
851{
852  int            i, j;
853
854  unsigned short idt_offset_lo, idt_offset_hi, idt_selector;
[362]855  unsigned char  /* idt_reserved, */ idt_flag;
[93]856  unsigned short sh_idt_offset_lo, sh_idt_offset_hi, sh_idt_selector;
[362]857  unsigned char  /* sh_idt_reserved, */ sh_idt_flag;
[93]858  int            dpl;
859  unsigned long  idt_iaddr;
860  int            sh_dpl;
861  unsigned long  sh_idt_iaddr;
862  char           idt_type, sh_idt_type;
863
864  unsigned long store0;
865  unsigned int  store1, store2;
866  int           datasize;
867  char          msg[2*SH_BUFSIZE];
868
869  if (ShKernIDT == S_TRUE)
870    {
871      if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]872        {
[93]873          datasize = 8;
874          for (j = 0; j < SH_MAXIDT; ++j) 
[1]875            {
[93]876              sh_kern_db_syscall (j, _("idt_table"), 
877                                  &sh_idt_table[j*8], 
878                                  &store0, &store1, &store2,
879                                  &datasize, SH_KERN_DBPUSH);
[1]880            }
[93]881        }
[1]882
[93]883      if ((sh.flag.checkSum != SH_CHECK_INIT) || 
884          (sh.flag.update == S_TRUE && is_init == 1))
885        {
886          /* Check the Interrupt Descriptor Table
887           *
888           * Stored(old) is idt_table[]
[1]889           */
[93]890          for (j = 0; j < SH_MAXIDT; ++j)
[1]891            {
[93]892              i = j * 8;
893         
894              sh_idt_offset_lo = *((unsigned short *) &sh_idt_table[i]);
895              sh_idt_selector  = *((unsigned short *) &sh_idt_table[i+2]);
[362]896              /* sh_idt_reserved  = (unsigned char) sh_idt_table[i+4]; */
[93]897              sh_idt_flag      = (unsigned char) sh_idt_table[i+5];
898              sh_idt_offset_hi = *((unsigned short *) &sh_idt_table[i+6]);
899              sh_idt_iaddr = (unsigned long)(sh_idt_offset_hi << 16) 
900                + sh_idt_offset_lo;
901             
902              if (sh_idt_iaddr == 0)
[1]903                {
[93]904                  sh_idt_table[i+2] = '\0';
905                  sh_idt_table[i+3] = '\0';
906                  sh_idt_table[i+5] = '\0';
[1]907
[93]908                  idt_offset_lo = *((unsigned short *) &idt_table[i]);
909                  idt_offset_hi = *((unsigned short *) &idt_table[i+6]);
910                  idt_iaddr = (unsigned long)(idt_offset_hi << 16) 
911                    + idt_offset_lo;
912                  if (idt_iaddr == 0)
[1]913                    {
[93]914                      idt_table[i+2] = '\0';
915                      idt_table[i+3] = '\0';
916                      idt_table[i+5] = '\0';
[1]917                    }
[93]918                 
919                }
920         
921              if (memcmp(&sh_idt_table[i], &idt_table[i], 8) != 0)
922                {
923                 
924                  idt_offset_lo = *((unsigned short *) &idt_table[i]);
925                  idt_selector  = *((unsigned short *) &idt_table[i+2]);
[362]926                  /* idt_reserved  = (unsigned char) idt_table[i+4]; */
[93]927                  idt_flag      = (unsigned char) idt_table[i+5];
928                  idt_offset_hi = *((unsigned short *) &idt_table[i+6]);
929                  idt_iaddr = (unsigned long)(idt_offset_hi << 16) 
930                    + idt_offset_lo;
931             
932                  if (idt_iaddr != 0)
[1]933                    {
[93]934                      if (idt_flag & 64) { dpl = 3; }
935                      else               { dpl = 0; }
936                      if (idt_flag & 1)  { 
937                        if (dpl == 3) idt_type = 'S'; 
938                        else idt_type = 'T'; }
939                      else               { idt_type = 'I'; }
[1]940                    }
[93]941                  else { dpl = -1; idt_type = 'U'; }
942                 
943                  if (sh_idt_iaddr != 0)
944                    {
945                      if (sh_idt_flag & 64) { sh_dpl = 3; }
946                      else               { sh_dpl = 0; }
947                      if (sh_idt_flag & 1)  { 
948                        if (sh_dpl == 3) sh_idt_type = 'S'; 
949                        else sh_idt_type = 'T'; }
950                      else               { sh_idt_type = 'I'; }
951                    }
952                  else { sh_dpl = -1; sh_idt_type = 'U'; }
953                 
954                  sh_kern_pathmsg (msg, SH_BUFSIZE,
955                                   j, _("idt_table"),
956                                   &idt_table[i], 8,
957                                   &sh_idt_table[i], 8);
958
959                  sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
960                                   0, MSG_KERN_IDT,
961                                   j, 
962                                   sh_idt_iaddr, sh_strseg(sh_idt_selector), 
963                                   (int) sh_dpl, sh_idt_type, 
964                                   idt_iaddr, sh_strseg(idt_selector),
965                                   (int) dpl, idt_type, msg);
966                 
967                  memcpy(&idt_table[i], &sh_idt_table[i], 8);
[1]968                }
969            }
[93]970        }
971    }
972}
[1]973
974
[93]975#define SYS_BUS_PCI _("/sys/bus/pci/devices")
976#include <dirent.h>
[1]977
[93]978static void check_rom (char * pcipath, char * name)
979{
980  file_type       theFile;
981  char            fileHash[2*(KEY_LEN + 1)];
982  int             status;
983  char          * tmp;
984  extern unsigned long sh_files_maskof (int class);
[1]985
[93]986  (void) sl_strlcpy (theFile.fullpath, pcipath, PATH_MAX);
987  theFile.check_mask  = sh_files_maskof(SH_LEVEL_READONLY);
[162]988  theFile.check_mask &= ~(MODI_MTM|MODI_CTM|MODI_INO);
[114]989  CLEAR_SH_FFLAG_REPORTED(theFile.file_reported);
[93]990  theFile.attr_string = NULL;
[167]991  theFile.link_path   = NULL;
[93]992 
993  status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 
994                            name, &theFile, fileHash, 0);
[1]995
[93]996  if (status != 0)
997    {
998      tmp = sh_util_safe_name(pcipath);
999      sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
1000                       0, MSG_E_SUBGPATH,
1001                       _("Could not check PCI ROM"),
1002                       _("check_rom"),
1003                       tmp);
1004      SH_FREE(tmp);
[167]1005      goto out;
[93]1006    }
[1]1007
[93]1008  if ( sh.flag.checkSum == SH_CHECK_INIT ) 
1009    {
1010      sh_hash_pushdata (&theFile, fileHash);
1011    }
1012  else if (sh.flag.checkSum == SH_CHECK_CHECK ) 
1013    {
1014      sh_hash_compdata (SH_LEVEL_READONLY, &theFile, fileHash, NULL, -1);
1015    }
[1]1016
[167]1017 out:
1018  if (theFile.attr_string) SH_FREE(theFile.attr_string);
1019  if (theFile.link_path)   SH_FREE(theFile.link_path);
[93]1020  return;
1021}
[1]1022
[93]1023static void check_pci_rom (char * pcipath, char * name)
1024{
1025  struct stat buf;
1026  int         fd;
[162]1027  int         status;
[1]1028
[93]1029  if (0 == stat(pcipath, &buf))
1030    {
1031      /* Need to write "1" to the file to enable the ROM. Afterwards,
1032       * write "0" to disable it.
1033       */
1034      fd = open ( pcipath, O_RDWR );
[223]1035      if (fd)
1036        {
1037          do {
1038            status = write( fd, "1", 1 );
1039          } while (status < 0 && errno == EINTR);
[252]1040          sl_close_fd (FIL__, __LINE__,  fd );
[1]1041
[223]1042          if (status > 0)
1043            {
1044              check_rom(pcipath, name);
1045             
1046              fd = open ( pcipath, O_RDWR );
1047              if (fd)
1048                {
1049                  do {
1050                    status = write( fd, "0", 1 );
1051                  } while (status < 0 && errno == EINTR);
[252]1052                  sl_close_fd (FIL__, __LINE__,  fd );
[223]1053                }
1054            }
1055        }
[1]1056    }
[93]1057  return;
1058}
[1]1059
[93]1060static void check_pci()
1061{
1062  char pci_dir[256];
1063  char * pcipath;
1064  DIR * df;
1065  struct dirent * entry;
1066
[223]1067  if (ShKernPCI != S_TRUE)
1068    return;
1069
[93]1070  sl_strlcpy(pci_dir, SYS_BUS_PCI, sizeof(pci_dir));
1071
1072  df = opendir(pci_dir);
1073  if (df)
[1]1074    {
[143]1075      while (1)
1076        {
1077          SH_MUTEX_LOCK(mutex_readdir);
1078          entry = readdir(df);
1079          SH_MUTEX_UNLOCK(mutex_readdir);
[131]1080
[143]1081          if (entry == NULL)
1082            break;
1083
[93]1084          if (0 == strcmp(entry->d_name, ".") && 
1085              0 == strcmp(entry->d_name, ".."))
1086            continue;
1087
1088          pcipath = sh_util_strconcat(pci_dir, "/", 
1089                                      entry->d_name, "/rom", NULL);
1090          check_pci_rom(pcipath, entry->d_name);
1091          SH_FREE(pcipath);
1092        }
[131]1093
[93]1094      closedir(df);
[1]1095    }
[223]1096  return;
[93]1097}
[1]1098
[93]1099/* -- Check the proc_root inode.
1100 *
1101 * This will detect adore-ng.
1102 */
1103static void check_proc_root (struct sh_kernel_info * kinfo)
1104{
[279]1105  struct proc_dir_entry     proc_root_dir;
[348]1106  int                       proc_root_inode_op_flag = 0;
[93]1107
[102]1108/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
[279]1109#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
[102]1110  struct inode_operations proc_root_inode;
[425]1111#endif
[102]1112
[425]1113  if (ShKernPROC != S_TRUE)
1114    return;
1115
1116/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
1117#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
[93]1118  memcpy (&proc_root_inode, &(kinfo->proc_root_inode), sizeof(struct inode_operations));
1119
[102]1120  /* Seems that the info does not relate anymore to proc_root_lookup(?)
1121   */
[1]1122  if ( (unsigned int) *proc_root_inode.lookup != proc_root_lookup)
1123    {
1124      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
1125                       _("proc_root_inode_operations.lookup != proc_root_lookup"));
1126    }
[102]1127#endif
1128
1129  memcpy (&proc_root_dir,   &(kinfo->proc_root_dir),   sizeof(struct proc_dir_entry));
[279]1130
1131  if (((unsigned long) * &proc_root_dir.proc_iops) == proc_root_iops)
[1]1132    {
[348]1133      proc_root_inode_op_flag = 1;
[279]1134    }
1135  else if (proc_root_dir.size == proc_root_iops)
1136    {
[348]1137      proc_root_inode_op_flag = 1;
[279]1138    }
1139  else if ((unsigned long) * &proc_root_dir.proc_fops == proc_root_iops)
1140    {
[348]1141      proc_root_inode_op_flag = 1;
[279]1142    }
1143
[348]1144  if (0 == proc_root_inode_op_flag)
[279]1145    {
[1]1146      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
1147                       _("proc_root.proc_iops != proc_root_inode_operations"));
1148    }
[102]1149
[93]1150  return;
1151}
[1]1152
[93]1153/* -- Check the system_call syscall gate.
1154 *
1155 * Stored(old) is system_call_code[]
1156 */
1157static void check_syscall_gate(int is_init, struct sh_kernel_info * kinfo)
1158{
1159  int           i, j;
1160  unsigned long store0;
1161  unsigned int  store1, store2;
1162  int           datasize;
1163  int           max_system_call = (SYS_CALL_LOC < 128) ? 128 : SYS_CALL_LOC;
1164  char          msg[2*SH_BUFSIZE];
1165 
[3]1166  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]1167    {
1168      store0 = 0; store1 = 0; store2 = 0;
[93]1169      datasize = SH_KERN_SCC;
[1]1170      sh_kern_db_syscall (0, _("system_call"), 
[93]1171                          &(kinfo->new_system_call_code), &store0, &store1, &store2,
1172                          &datasize, SH_KERN_DBPUSH);
[1]1173    }
1174
1175  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
1176      (sh.flag.update == S_TRUE && is_init == 1))
1177    {
1178      for (i = 0; i < (max_system_call + 4); ++i) 
1179        {
[93]1180          if (system_call_code[i] != kinfo->new_system_call_code[i])
[1]1181            {
1182
[93]1183              sh_kern_pathmsg (msg, sizeof(msg),
1184                               0, _("system_call"),
1185                               system_call_code, SH_KERN_SCC,
1186                               kinfo->new_system_call_code, SH_KERN_SCC);
[1]1187
1188              sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
[93]1189                               0, MSG_KERN_GATE,
1190                               kinfo->new_system_call_code[i], 0,
[1]1191                               system_call_code[i], 0,
1192                               0, _("system_call (interrupt handler)"),
1193                               msg);
1194             
1195              for (j = 0; j < (max_system_call + 4); ++j)
[93]1196                system_call_code[j] = kinfo->new_system_call_code[j];
[1]1197              break;
1198            }
1199        }
1200    }
[93]1201  return;
1202}
1203
1204static void check_system_calls (int is_init, struct sh_kernel_info * kinfo)
1205{
1206  int           i;
1207
1208#ifdef SH_USE_LKM
1209  static int check_getdents      = 0;
1210  /* #ifdef __NR_getdents64 */
1211  static int check_getdents64    = 0;
1212  /* #endif */
1213  static int copy_if_next        = -1;
1214  static int copy_if_next_64     = -1;
1215#endif
1216
1217  unsigned long store0;
1218  unsigned int  store1, store2;
1219  int           mod_syscall_addr = 0;
1220  int           mod_syscall_code = 0;
1221  UINT64        size_old  = 0, size_new = 0;
1222  UINT64        mtime_old = 0, mtime_new = 0;
1223  UINT64        ctime_old = 0, ctime_new = 0;
1224  char          tmp[128];
1225  char          msg[2*SH_BUFSIZE];
1226  char timstr_o[32];
1227  char timstr_n[32];
1228
[3]1229  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]1230    {
1231      for (i = 0; i < SH_MAXCALLS; ++i) 
1232        {
[93]1233          store0 = kinfo->kmem_call_table[i]; 
1234          store1 = kinfo->kmem_code_table[i][0]; store2 = kinfo->kmem_code_table[i][1];
[1]1235          sh_kern_db_syscall (i, _("syscall"), 
1236                              NULL, &store0, &store1, &store2,
[93]1237                              0, SH_KERN_DBPUSH);
[1]1238        }
1239    }
1240
1241  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
1242      (sh.flag.update == S_TRUE && is_init == 1))
1243    {
1244      for (i = 0; i < SH_MAXCALLS; ++i) 
1245        {
1246          if (sh_syscalls[i].name == NULL /* || sh_syscalls[i].addr == 0UL */)
1247            break;
1248
1249#ifdef SH_USE_LKM
[93]1250          if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
[1]1251            {
1252              if (check_getdents == 0 && 
1253                  0 == strcmp(_(sh_syscalls[i].name), _("sys_getdents")))
1254                {
1255                  check_getdents = 1;
1256                  sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 
[93]1257                                   0, MSG_E_SUBGEN,
[1]1258                                   _("Modified kernel syscall (expected)."),
1259                                   _(sh_syscalls[i].name) );
1260                  copy_if_next = i;
[93]1261                  sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1262                  continue;
1263                }
1264              /* #ifdef __NR_getdents64 */
1265              else if  (check_getdents64 == 0 && 
1266                        0 == strcmp(_(sh_syscalls[i].name), 
1267                                    _("sys_getdents64")))
1268                {
1269                  check_getdents64 = 1;
1270                  sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 
[93]1271                                   0, MSG_E_SUBGEN,
[1]1272                                   _("Modified kernel syscall (expected)."),
1273                                   _(sh_syscalls[i].name) );
1274                  copy_if_next_64 = i;
[93]1275                  sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1276                  continue;
1277                }
1278              /* #endif */
1279              else
1280                {
1281                  size_old = sh_syscalls[i].addr;
[93]1282                  size_new = kinfo->kmem_call_table[i];
[1]1283                  mod_syscall_addr = 1;
1284                }
[93]1285              sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1286            }
1287#else
[93]1288          if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
[1]1289            {
1290              size_old = sh_syscalls[i].addr;
[93]1291              size_new = kinfo->kmem_call_table[i];
[1]1292              mod_syscall_addr = 1;
[93]1293              sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1294            }
1295#endif
1296
1297
[93]1298          /* -- Check the code at syscall address
[1]1299           *
1300           * Stored(old) is sh_syscalls[]
1301           */
1302          if ( (mod_syscall_addr == 0) && 
[93]1303               ((sh_syscalls[i].code[0] != kinfo->kmem_code_table[i][0]) || 
1304                (sh_syscalls[i].code[1] != kinfo->kmem_code_table[i][1]))
[1]1305               )
1306            {
1307              mtime_old = sh_syscalls[i].code[0];
[93]1308              mtime_new = kinfo->kmem_code_table[i][0];
[1]1309              ctime_old = sh_syscalls[i].code[1];
[93]1310              ctime_new = kinfo->kmem_code_table[i][1];
[1]1311              mod_syscall_code = 1;
1312
1313#ifdef SH_USE_LKM
1314              if (i == copy_if_next)
1315                {
1316                  mod_syscall_code =  0;
1317                  copy_if_next     = -1;
1318                }
1319              if (i == copy_if_next_64)
1320                {
1321                  mod_syscall_code =  0;
1322                  copy_if_next_64  = -1;
1323                }
1324#endif
1325
[93]1326              sh_syscalls[i].code[0] = kinfo->kmem_code_table[i][0];
1327              sh_syscalls[i].code[1] = kinfo->kmem_code_table[i][1];
[1]1328            }
[93]1329
1330          /* Build the error message, if something has been
[1]1331           * detected.
1332           */
1333          if ((mod_syscall_addr != 0) || (mod_syscall_code != 0))
1334            {
1335#ifdef SH_USE_XML
1336              sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
1337                          _("syscall"), i);
1338#else
1339              sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
1340                          _("syscall"), i);
1341#endif
1342              sl_strlcpy(msg, tmp, SH_BUFSIZE);
1343
1344              if (mod_syscall_addr != 0)
1345                {
1346                  sl_snprintf(tmp, 128, sh_hash_size_format(),
1347                              size_old, size_new);
1348                  sl_strlcat(msg, tmp, SH_BUFSIZE); 
1349                }
1350              if (mod_syscall_code != 0)
1351                {
[132]1352                  (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
1353                  (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
[1]1354#ifdef SH_USE_XML
1355                  sl_snprintf(tmp, 128, 
1356                              _("ctime_old=\"%s\" ctime_new=\"%s\" "), 
1357                              timstr_o, timstr_n);
1358#else
1359                  sl_snprintf(tmp, 128, 
1360                              _("ctime_old=<%s>, ctime_new=<%s>, "), 
1361                              timstr_o, timstr_n);
1362#endif
1363                  sl_strlcat(msg, tmp, SH_BUFSIZE); 
[132]1364                  (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
1365                  (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
[1]1366#ifdef SH_USE_XML
1367                  sl_snprintf(tmp, 128, 
1368                              _("mtime_old=\"%s\" mtime_new=\"%s\" "), 
1369                              timstr_o, timstr_n);
1370#else
1371                  sl_snprintf(tmp, 128, 
1372                              _("mtime_old=<%s>, mtime_new=<%s> "), 
1373                              timstr_o, timstr_n);
1374#endif
1375                  sl_strlcat(msg, tmp, SH_BUFSIZE); 
1376                }
1377              sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
[93]1378                               0, MSG_KERN_SYSCALL,
[1]1379                               i, _(sh_syscalls[i].name), msg);
1380              mod_syscall_addr = 0;
1381              mod_syscall_code = 0;
1382            }
1383        }
1384    }
[93]1385  return;
1386}
1387 
1388int sh_kern_check_internal ()
1389{
1390  int kd;
1391  int is_init;
1392  pid_t mpid;
1393  int mpipe[2];
1394  int status = 0;
[1]1395
[93]1396  struct sh_kernel_info kinfo;
1397
1398
1399  SL_ENTER(_("sh_kern_check_internal"));
1400
1401  /* -- Check whether initialisation is required; if yes, initialize.
1402   */
1403
1404  if (0 != check_init(&is_init))
[1]1405    {
[93]1406      SL_RETURN( (-1), _("sh_kern_check_internal"));
1407    }
1408
1409
1410  /* -- Open /dev/kmem and fork subprocess to read from it.
1411   */
1412   
1413  if (kaddr == (unsigned int) -1) /* kaddr = address of the sys_call_table */
1414    {
1415      sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, MSG_E_SUBGEN,
1416                       _("no address for sys_call_table - switching off"),
1417                       _("kern_check_internal") );
1418      ShKernActive = S_FALSE;
1419      SL_RETURN( (-1), _("sh_kern_check_internal"));
1420    }
1421 
1422  kd = aud_open(FIL__, __LINE__, SL_YESPRIV, _("/dev/kmem"), O_RDONLY, 0);
1423 
1424  if (kd < 0)
1425    {
[279]1426      kd = aud_open(FIL__, __LINE__, SL_YESPRIV, _("/proc/kmem"), O_RDONLY, 0);
1427    }
1428
1429  if (kd < 0)
1430    {
[93]1431      status = errno;
1432      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1433                       _("error opening /dev/kmem"),
1434                       _("kern_check_internal") );
1435      SL_RETURN( (-1), _("sh_kern_check_internal"));
1436    }
1437
1438  status = aud_pipe(FIL__, __LINE__, mpipe);
1439
1440  if (status == 0)
1441    {
1442      mpid = aud_fork(FIL__, __LINE__);
1443
1444      switch (mpid) 
[1]1445        {
[93]1446        case -1:
1447          status = -1;
1448          break;
1449        case 0: 
[1]1450
[93]1451          /* -- Child process reads /dev/kmem and writes to pipe
[1]1452           */
[93]1453          run_child(kd, mpipe);
1454          break;
[1]1455         
[93]1456          /* -- Parent process reads from child via pipe
1457           */
1458        default:
[252]1459          sl_close_fd(FIL__, __LINE__, kd);
[93]1460          status = read_from_child(mpid, mpipe, &kinfo);
1461          break;
1462        }
1463    }
[1]1464
[93]1465  if ( status < 0)
1466    {
[192]1467      char errmsg[SH_ERRBUF_SIZE];
1468      sl_snprintf(errmsg, SH_ERRBUF_SIZE, 
1469                  _("error reading from /dev/kmem: %d"), status);
[93]1470      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
[192]1471                       errmsg,
[93]1472                       _("kern_check_internal") );
1473      SL_RETURN( (-1), _("sh_kern_check_internal"));
1474    }
[1]1475
[93]1476  /* -- Check the proc_root inode.
1477   *
1478   * This will detect adore-ng.
1479   */
1480  check_proc_root( &kinfo );
[1]1481
1482
[93]1483  /* -- Check the system_call syscall gate.
1484   *
1485   * Stored(old) is system_call_code[]
1486   */
1487  check_syscall_gate( is_init, &kinfo );
[1]1488
[93]1489  /* -- Check the individual syscalls
1490   *
1491   * Stored(old) is sh_syscalls[] array.
1492   */
1493  check_system_calls ( is_init, &kinfo );
1494
1495  /* -- Check the Interrupt Descriptor Table
1496   */
1497  check_idt_table(is_init);
1498
1499  /* -- Check PCI ROM
1500   */
1501  check_pci();
1502
[1]1503  SL_RETURN( (0), _("sh_kern_check_internal"));
1504}
1505/* ifdef HOST_IS_LINUX */
1506#else
1507
[93]1508/********************************************************
1509 *
1510 *  --- BSD ---
1511 *
1512 ********************************************************/
1513
[1]1514#include <err.h>
1515#include <kvm.h>
1516#include <nlist.h>
1517
1518/* not OpenBSD */
1519#if defined(HOST_IS_FREEBSD)
1520#include <sys/sysent.h>
1521#endif
1522
1523#include <sys/syscall.h>
1524#ifndef  SYS_MAXSYSCALL
1525#define  SYS_MAXSYSCALL 512
1526#endif
1527
1528#ifdef __OpenBSD__
1529struct proc;
1530struct sysent {
1531        short sy_narg;
1532        short sy_argsize;
1533        int   (*sy_call)(struct proc *, void *, register_t *);
1534};
1535#endif
1536
1537int sh_kern_data_init ()
1538{
1539  unsigned long store0 = 0;
1540  unsigned int  store1 = 0, store2 = 0;
1541  int           datasize, i;
1542  char        * databuf = NULL;
1543
1544  /* syscall address and code
1545   */ 
1546  for (i = 0; i < SH_MAXCALLS; ++i) 
1547    {
1548      databuf = sh_kern_db_syscall (i, _("syscall"), 
1549                                    NULL, &store0, &store1, &store2,
[93]1550                                    &datasize, SH_KERN_DBPOP);
[1]1551      sh_syscalls[i].addr = store0;
1552      if (databuf != NULL) { SH_FREE(databuf); }
1553      if (store0 == 0) {
1554        sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1555                        _("syscall address not found in database"), 
1556                        _("sh_kern_data_init"));
1557        return -1;
1558      }
1559
1560      sh_syscalls[i].code[0] = (unsigned int) store1; 
1561      sh_syscalls[i].code[1] = (unsigned int) store2;
1562      if ((store1 == 0) || (store2 == 0)) {
1563        sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1564                        _("syscall code not found in database"), 
1565                        _("sh_kern_data_init"));
1566        return -1;
1567      }
1568
1569    }
1570
1571  return 0;
1572}
1573
1574int sh_kern_check_internal ()
1575{
1576  struct sysent  sy;
1577  kvm_t * kd;
1578  int     i;
1579  int     status = -1;
1580  char    errbuf[_POSIX2_LINE_MAX+1];
1581  struct  nlist * sys_list;
1582  struct  nlist list[2];
1583
1584  unsigned long offset = 0L;
1585  unsigned int  syscall_code[2];  /* 8 bytes */
1586  unsigned long syscall_addr;
1587
1588  unsigned long store0 = 0;
1589  unsigned int  store1 = 0, store2 = 0;
1590
1591  UINT64        size_old  = 0, size_new = 0;
1592  UINT64        mtime_old = 0, mtime_new = 0;
1593  UINT64        ctime_old = 0, ctime_new = 0;
1594  char          tmp[128];
1595  char          msg[2*SH_BUFSIZE];
1596  char timstr_o[32];
1597  char timstr_n[32];
1598
1599  static int is_init = 0;
1600
1601  SL_ENTER(_("sh_kern_check_internal"));
1602
1603  if (is_init == 0)
1604    { 
1605      if (sh.flag.checkSum != SH_CHECK_INIT && sh.flag.update != S_TRUE)
1606        {
1607          if (0 == sh_kern_data_init()) {
1608            is_init = 1;
1609          } else {
1610            sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, 
1611                             MSG_E_SUBGEN,
1612                             _("could not initialize - switching off"),
1613                             _("kern_check_internal") );
1614            ShKernActive = S_FALSE;
1615            SL_RETURN( (-1), _("sh_kern_check_internal"));
1616          }
1617        }
1618      else if ((sh.flag.checkSum == SH_CHECK_INIT ||
1619                sh.flag.checkSum == SH_CHECK_CHECK) && 
1620               (sh.flag.update == S_TRUE))
1621        {       
1622          if (0 == sh_kern_data_init()) {
1623            is_init = 1;
1624          } else {
1625            sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, 
1626                             MSG_E_SUBGEN,
1627                             _("no or incomplete data in baseline database"),
1628                             _("kern_check_internal") );
1629          }
1630        }
1631    }
1632
1633  /* defined, but not used
1634   */
1635  ShKernDelay    = 0;
1636   
1637  list[0].n_name = "_sysent";
1638  list[1].n_name = NULL;
1639
1640  kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
1641  if (!kd)
1642    {
1643      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1644                       errbuf,
1645                       _("kvm_openfiles") );
1646      SL_RETURN( (-1), _("sh_kern_check_internal"));
1647    }
1648
1649  i = kvm_nlist(kd, list);
1650  if (i == -1)
1651    {
1652      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1653                       kvm_geterr(kd),
1654                       _("kvm_nlist (_sysent)") );
1655      kvm_close(kd);
1656      SL_RETURN( (-1), _("sh_kern_check_internal"));
1657    }
1658
1659  sys_list = SH_ALLOC((SYS_MAXSYSCALL+1) * sizeof(struct nlist));
1660
1661  for (i = 0; i < SH_MAXCALLS; ++i)
1662    sys_list[i].n_name = sh_syscalls[i].name;
1663  sys_list[SH_MAXCALLS].n_name = NULL;
1664
1665  i = kvm_nlist(kd, sys_list);
1666  if (i == -1)
1667    {
1668      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1669                       kvm_geterr(kd),
1670                       _("kvm_nlist (syscalls)") );
1671      kvm_close(kd);
1672      SH_FREE(sys_list);
1673      SL_RETURN( (-1), _("sh_kern_check_internal"));
1674    }
1675  else if (i > 0)
1676    {
1677      sl_snprintf(tmp, 128,
1678                  _("%d invalid syscalls"), i);
1679      /*
1680      for (i = 0; i < SH_MAXCALLS; ++i) {
1681        if (sys_list[i].n_type == 0 && sys_list[i].n_value == 0)
1682          fprintf(stderr, "invalid: [%3d] %s\n", i, sh_syscalls[i].name);
1683      }
1684      */
1685      sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
1686                       tmp,
1687                       _("kvm_nlist (syscalls)") );
1688    }
1689
1690  /* Check the individual syscalls
1691   *
1692   * Stored(old) is sh_syscalls[] array.
1693   */
[3]1694  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]1695    {
1696      for (i = 0; i < SH_MAXCALLS; ++i) 
1697        {
1698          if (sh_syscalls[i].name == NULL)
1699            {
1700              sl_snprintf(tmp, 128, 
1701                          _("too few entries in sh_syscalls[]: have %d, expect %d"), 
1702                          i, SH_MAXCALLS);
1703
1704              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1705                               tmp,
1706                               _("sh_kern_check_internal") );
1707              break;
1708            }
1709
1710          /* read address of syscall from sysent table
1711           */
1712          offset = list[0].n_value + (i*sizeof(struct sysent));
1713          if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
1714            {
1715              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1716                               kvm_geterr(kd),
1717                               _("kvm_read (syscall table)") );
1718              kvm_close(kd);
1719              SH_FREE(sys_list);
1720              SL_RETURN( (-1), _("sh_kern_check_internal"));
1721            }
1722          syscall_addr = (unsigned long) sy.sy_call;
1723          store0 = syscall_addr;
1724         
1725          /* read the syscall code
1726           */
1727          if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]), 
1728                      2 * sizeof(unsigned int)) < 0)
1729            {
1730              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1731                               kvm_geterr(kd),
1732                               _("kvm_read (syscall code)") );
1733              kvm_close(kd);
1734              SH_FREE(sys_list);
1735              SL_RETURN( (-1), _("sh_kern_check_internal"));
1736            }
1737          store1 = syscall_code[0]; store2 = syscall_code[1];
1738         
1739          sh_kern_db_syscall (i, _("syscall"), 
1740                              NULL, &store0, &store1, &store2,
[93]1741                              0, SH_KERN_DBPUSH);
[1]1742        }
1743    }
1744
1745  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
1746      (sh.flag.update == S_TRUE && is_init == 1))
1747    {
1748      for (i = 0; i < SH_MAXCALLS; ++i)
1749        {
1750          if (sh_syscalls[i].name == NULL)
1751            {
1752              sl_snprintf(tmp, 128, 
1753                          _("too few entries in sh_syscalls[]: have %d, expect %d"), 
1754                          i, SH_MAXCALLS);
1755
1756              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1757                               tmp,
1758                               _("sh_kern_check_internal") );
1759              break;
1760            }
1761         
1762          /* read address of syscall from sysent table
1763           */
1764          offset = list[0].n_value + (i*sizeof(struct sysent));
1765          if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
1766            {
1767              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1768                               kvm_geterr(kd),
1769                               _("kvm_read (syscall table)") );
1770              kvm_close(kd);
1771              SH_FREE(sys_list);
1772              SL_RETURN( (-1), _("sh_kern_check_internal"));
1773            }
1774          syscall_addr = (unsigned long) sy.sy_call;
1775         
1776          if (sh_syscalls[i].addr != syscall_addr)
1777            {
1778#ifdef SH_USE_XML
1779              sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
1780                          _("syscall"), i);
1781#else
1782              sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
1783                          _("syscall"), i);
1784#endif
1785              sl_strlcpy(msg, tmp, SH_BUFSIZE);
1786
1787              size_old = sh_syscalls[i].addr; 
1788              size_new = syscall_addr;
1789              sl_snprintf(tmp, 128, sh_hash_size_format(),
1790                          size_old, size_new);
1791              sl_strlcat(msg, tmp, SH_BUFSIZE);
1792 
1793              sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
1794                               status, MSG_KERN_SYSCALL,
1795                               i, _(sh_syscalls[i].name),
1796                               msg);
1797              sh_syscalls[i].addr = syscall_addr;
1798            }
1799          else
1800            {   
1801              /* read the syscall code
1802               */
1803              if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]), 
1804                          2 * sizeof(unsigned int)) < 0)
1805                {
1806                  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1807                                   kvm_geterr(kd),
1808                                   _("kvm_read (syscall code)") );
1809                  kvm_close(kd);
1810                  SH_FREE(sys_list);
1811                  SL_RETURN( (-1), _("sh_kern_check_internal"));
1812                }
1813             
1814              if (sh_syscalls[i].code[0] != syscall_code[0] || 
1815                  sh_syscalls[i].code[1] != syscall_code[1])
1816                {
1817                  mtime_old = sh_syscalls[i].code[0];
1818                  mtime_new = syscall_code[0];
1819                  ctime_old = sh_syscalls[i].code[1];
1820                  ctime_new = syscall_code[1];
1821
1822#ifdef SH_USE_XML
1823                  sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
1824                              _("syscall"), i);
1825#else
1826                  sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
1827                              _("syscall"), i);
1828#endif
1829                  sl_strlcpy(msg, tmp, SH_BUFSIZE);
1830
[132]1831                  (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
1832                  (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
[1]1833#ifdef SH_USE_XML
1834                  sl_snprintf(tmp, 128, 
1835                              _("ctime_old=\"%s\" ctime_new=\"%s\" "), 
1836                              timstr_o, timstr_n);
1837#else
1838                  sl_snprintf(tmp, 128, 
1839                              _("ctime_old=<%s>, ctime_new=<%s>, "), 
1840                              timstr_o, timstr_n);
1841#endif
1842                  sl_strlcat(msg, tmp, SH_BUFSIZE); 
[132]1843                  (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
1844                  (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
[1]1845#ifdef SH_USE_XML
1846                  sl_snprintf(tmp, 128, 
1847                              _("mtime_old=\"%s\" mtime_new=\"%s\" "), 
1848                              timstr_o, timstr_n);
1849#else
1850                  sl_snprintf(tmp, 128, 
1851                              _("mtime_old=<%s>, mtime_new=<%s> "), 
1852                              timstr_o, timstr_n);
1853#endif
1854                  sl_strlcat(msg, tmp, SH_BUFSIZE); 
1855
1856                  sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
1857                                   status, MSG_KERN_SYSCALL,
1858                                   i, _(sh_syscalls[i].name),
1859                                   msg);
1860                  sh_syscalls[i].code[0] = syscall_code[0];
1861                  sh_syscalls[i].code[1] = syscall_code[1];
1862                }
1863            }
1864        }
1865    }
1866  SH_FREE(sys_list);
1867  if(kvm_close(kd) < 0)
1868    {
1869      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1870                       kvm_geterr(kd),
1871                       _("kvm_close") );
1872      exit(EXIT_FAILURE);
1873    }
1874
1875  SL_RETURN( (0), _("sh_kern_check_internal"));
1876}
1877
1878#endif
1879
1880/*************
1881 *
1882 * module init
1883 *
1884 *************/
1885#if defined(HOST_IS_LINUX)
1886#include <sys/utsname.h>
1887#endif
1888
1889static int AddressReconf = 0;
1890
[140]1891int sh_kern_init (struct mod_type * arg)
[1]1892{
1893#if defined(HOST_IS_LINUX)
1894  struct utsname buf;
1895  char         * str;
1896#endif
[140]1897  (void) arg;
[1]1898
1899  SL_ENTER(_("sh_kern_init"));
1900  if (ShKernActive == S_FALSE)
1901    SL_RETURN( (-1), _("sh_kern_init"));
1902
1903#if defined(HOST_IS_LINUX)
1904  uname(&buf);
1905
1906  if ((AddressReconf < 5) && (0 != strcmp(SH_KERNEL_VERSION, buf.release)))
1907    {
1908      str = SH_ALLOC(256);
1909      sl_snprintf(str, 256, 
1910                  "Compiled for kernel %s, but current kernel is %s, and kernel addresses have not been re-configured",
1911                  SH_KERNEL_VERSION, buf.release);
1912      sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
1913                       str,
1914                       _("kern_check") );
1915      SH_FREE(str);
1916      ShKernActive = S_FALSE;
1917      SL_RETURN( (-1), _("sh_kern_init"));
1918    }
1919#endif
1920
1921  lastcheck  = time (NULL);
1922  if (sh.flag.checkSum != SH_CHECK_INIT)
1923    {
1924      sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1925                       _("Checking kernel syscalls"),
1926                       _("kern_check") );
1927    }
1928  sh_kern_check_internal ();
1929  SL_RETURN( (0), _("sh_kern_init"));
1930}
1931
1932/*************
1933 *
1934 * module cleanup
1935 *
1936 *************/
1937int sh_kern_end ()
1938{
1939  return (0);
1940}
1941
1942
1943/*************
1944 *
1945 * module timer
1946 *
1947 *************/
1948int sh_kern_timer (time_t tcurrent)
1949{
1950  if (ShKernActive == S_FALSE)
1951    return 0;
1952
1953  if ((int) (tcurrent - lastcheck) >= ShKernInterval)
1954    {
1955      lastcheck  = tcurrent;
1956      return (-1);
1957    }
1958  return 0;
1959}
1960
1961/*************
1962 *
1963 * module check
1964 *
1965 *************/
1966int sh_kern_check ()
1967{
1968  sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
1969                   _("Checking kernel syscalls"),
1970                   _("kern_check") );
1971  return (sh_kern_check_internal ());
1972}
1973
1974/*************
1975 *
1976 * module setup
1977 *
1978 *************/
1979
[68]1980int sh_kern_set_severity  (const char * c)
[1]1981{
1982  char tmp[32];
1983  tmp[0] = '='; tmp[1] = '\0';
1984  sl_strlcat (tmp, c, 32);
1985  sh_error_set_level (tmp, &ShKernSeverity);
1986  return 0;
1987}
1988
[68]1989int sh_kern_set_timer (const char * c)
[1]1990{
1991  long val;
1992
1993  SL_ENTER(_("sh_kern_set_timer"));
1994
1995  val = strtol (c, (char **)NULL, 10);
1996  if (val <= 0)
1997    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1998                      _("kern timer"), c);
1999
2000  val = (val <= 0 ? 60 : val);
2001
2002  ShKernInterval = (time_t) val;
2003  SL_RETURN( 0, _("sh_kern_set_timer"));
2004}
2005
[68]2006int sh_kern_set_activate (const char * c)
[1]2007{
2008  int i;
2009  SL_ENTER(_("sh_kern_set_activate"));
2010  i = sh_util_flagval(c, &ShKernActive);
2011  SL_RETURN(i, _("sh_kern_set_activate"));
2012}
2013
[68]2014int sh_kern_set_idt (const char * c)
[1]2015{
2016  int i;
2017  SL_ENTER(_("sh_kern_set_idt"));
2018  i = sh_util_flagval(c, &ShKernIDT);
2019  SL_RETURN(i, _("sh_kern_set_idt"));
2020}
2021
[223]2022int sh_kern_set_pci (const char * c)
2023{
2024  int i;
2025  SL_ENTER(_("sh_kern_set_pci"));
2026  i = sh_util_flagval(c, &ShKernPCI);
2027  SL_RETURN(i, _("sh_kern_set_pci"));
2028}
2029
[425]2030int sh_kern_set_proc (const char * c)
2031{
2032  int i;
2033  SL_ENTER(_("sh_kern_set_proc"));
2034  i = sh_util_flagval(c, &ShKernPROC);
2035  SL_RETURN(i, _("sh_kern_set_proc"));
2036}
2037
[68]2038int sh_kern_set_sc_addr (const char * c)
[1]2039{
2040  char * endptr;
2041  unsigned long value;
2042
2043  SL_ENTER(_("sh_kern_set_sc_addr"));
2044  errno = 0;
2045  value = strtoul(c, &endptr, 16);
2046  if ((ULONG_MAX == value) && (errno == ERANGE))
2047    {
2048      SL_RETURN((-1), _("sh_kern_set_sc_addr"));
2049    }
2050  if ((*c == '\0') || (*endptr != '\0'))
2051    {
2052      SL_RETURN((-1), _("sh_kern_set_sc_addr"));
2053    }
2054  system_call_addr = value;
2055  ++AddressReconf;
2056  SL_RETURN((0), _("sh_kern_set_sc_addr"));
2057}
2058
[68]2059int sh_kern_set_sct_addr (const char * c)
[1]2060{
2061  char * endptr;
2062  unsigned long value;
2063
2064  SL_ENTER(_("sh_kern_set_sct_addr"));
2065  errno = 0;
2066  value = strtoul(c, &endptr, 16);
2067  if ((ULONG_MAX == value) && (errno == ERANGE))
2068    {
2069      SL_RETURN((-1), _("sh_kern_set_sct_addr"));
2070    }
2071  if ((*c == '\0') || (*endptr != '\0'))
2072    {
2073      SL_RETURN((-1), _("sh_kern_set_sct_addr"));
2074    }
2075  kaddr = (unsigned int) value;
2076  ++AddressReconf;
2077  SL_RETURN((0), _("sh_kern_set_sct_addr"));
2078}
2079
[68]2080int sh_kern_set_proc_root (const char * c)
[1]2081{
2082  char * endptr;
2083  unsigned long value;
2084
2085  SL_ENTER(_("sh_kern_set_proc_root"));
2086  errno = 0;
2087  value = strtoul(c, &endptr, 16);
2088  if ((ULONG_MAX == value) && (errno == ERANGE))
2089    {
2090      SL_RETURN((-1), _("sh_kern_set_proc_root"));
2091    }
2092  if ((*c == '\0') || (*endptr != '\0'))
2093    {
2094      SL_RETURN((-1), _("sh_kern_set_proc_root"));
2095    }
2096 
2097  proc_root = value;
2098  ++AddressReconf;
2099  SL_RETURN((0), _("sh_kern_set_proc_root"));
2100}
2101
[68]2102int sh_kern_set_proc_root_iops (const char * c)
[1]2103{
2104  char * endptr;
2105  unsigned long value;
2106
2107  SL_ENTER(_("sh_kern_set_proc_root_iops"));
2108  errno = 0;
2109  value = strtoul(c, &endptr, 16);
2110  if ((ULONG_MAX == value) && (errno == ERANGE))
2111    {
2112      SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
2113    }
2114  if ((*c == '\0') || (*endptr != '\0'))
2115    {
2116      SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
2117    }
2118 
2119  proc_root_iops = value;
2120  ++AddressReconf;
2121  SL_RETURN((0), _("sh_kern_set_proc_root_iops"));
2122}
2123
[68]2124int sh_kern_set_proc_root_lookup (const char * c)
[1]2125{
2126  char * endptr;
2127  unsigned long value;
2128
2129  SL_ENTER(_("sh_kern_set_proc_root_lookup"));
2130  errno = 0;
2131  value = strtoul(c, &endptr, 16);
2132  if ((ULONG_MAX == value) && (errno == ERANGE))
2133    {
2134      SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
2135    }
2136  if ((*c == '\0') || (*endptr != '\0'))
2137    {
2138      SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
2139    }
2140  proc_root_lookup = value;
2141  ++AddressReconf;
2142  SL_RETURN((0), _("sh_kern_set_proc_root_lookup"));
2143}
2144
2145#endif
2146
[68]2147/* #ifdef SH_USE_KERN */
[1]2148#endif
Note: See TracBrowser for help on using the repository browser.