source: trunk/src/sh_kern.c@ 127

Last change on this file since 127 was 114, checked in by rainer, 17 years ago

Revision of file flag code.

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