source: trunk/src/sh_kern.c@ 164

Last change on this file since 164 was 162, checked in by katerina, 17 years ago

Fix for ticket #89, #90, and #91 (locking,compile failure).

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