source: trunk/src/sh_kern.c@ 147

Last change on this file since 147 was 146, checked in by rainer, 17 years ago

Fix for ticket #82 (spurious alerts caused by PCI ROM check).

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