source: trunk/src/sh_kern.c@ 97

Last change on this file since 97 was 93, checked in by rainer, 18 years ago

Add check for PCI ROMs; fix ticket #51 (symlinks in root directory reported with leading double slash).

File size: 47.7 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 theFile.reported = S_FALSE;
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 inode_operations proc_root_inode;
990 struct proc_dir_entry proc_root_dir;
991
992 memcpy (&proc_root_inode, &(kinfo->proc_root_inode), sizeof(struct inode_operations));
993 memcpy (&proc_root_dir, &(kinfo->proc_root_dir), sizeof(struct proc_dir_entry));
994
995 if ( (unsigned int) *proc_root_inode.lookup != proc_root_lookup)
996 {
997 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
998 _("proc_root_inode_operations.lookup != proc_root_lookup"));
999 }
1000 else if ( (((unsigned int) * &proc_root_dir.proc_iops) != proc_root_iops)
1001 && (proc_root_dir.size != proc_root_iops)
1002 && (((unsigned int) * &proc_root_dir.proc_fops) != proc_root_iops)
1003 )
1004 {
1005 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
1006 _("proc_root.proc_iops != proc_root_inode_operations"));
1007 }
1008 return;
1009}
1010
1011/* -- Check the system_call syscall gate.
1012 *
1013 * Stored(old) is system_call_code[]
1014 */
1015static void check_syscall_gate(int is_init, struct sh_kernel_info * kinfo)
1016{
1017 int i, j;
1018 unsigned long store0;
1019 unsigned int store1, store2;
1020 int datasize;
1021 int max_system_call = (SYS_CALL_LOC < 128) ? 128 : SYS_CALL_LOC;
1022 char msg[2*SH_BUFSIZE];
1023
1024 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
1025 {
1026 store0 = 0; store1 = 0; store2 = 0;
1027 datasize = SH_KERN_SCC;
1028 sh_kern_db_syscall (0, _("system_call"),
1029 &(kinfo->new_system_call_code), &store0, &store1, &store2,
1030 &datasize, SH_KERN_DBPUSH);
1031 }
1032
1033 if ((sh.flag.checkSum != SH_CHECK_INIT) ||
1034 (sh.flag.update == S_TRUE && is_init == 1))
1035 {
1036 for (i = 0; i < (max_system_call + 4); ++i)
1037 {
1038 if (system_call_code[i] != kinfo->new_system_call_code[i])
1039 {
1040
1041 sh_kern_pathmsg (msg, sizeof(msg),
1042 0, _("system_call"),
1043 system_call_code, SH_KERN_SCC,
1044 kinfo->new_system_call_code, SH_KERN_SCC);
1045
1046 sh_error_handle (ShKernSeverity, FIL__, __LINE__,
1047 0, MSG_KERN_GATE,
1048 kinfo->new_system_call_code[i], 0,
1049 system_call_code[i], 0,
1050 0, _("system_call (interrupt handler)"),
1051 msg);
1052
1053 for (j = 0; j < (max_system_call + 4); ++j)
1054 system_call_code[j] = kinfo->new_system_call_code[j];
1055 break;
1056 }
1057 }
1058 }
1059 return;
1060}
1061
1062static void check_system_calls (int is_init, struct sh_kernel_info * kinfo)
1063{
1064 int i;
1065
1066#ifdef SH_USE_LKM
1067 static int check_getdents = 0;
1068 /* #ifdef __NR_getdents64 */
1069 static int check_getdents64 = 0;
1070 /* #endif */
1071 static int copy_if_next = -1;
1072 static int copy_if_next_64 = -1;
1073#endif
1074
1075 unsigned long store0;
1076 unsigned int store1, store2;
1077 int mod_syscall_addr = 0;
1078 int mod_syscall_code = 0;
1079 UINT64 size_old = 0, size_new = 0;
1080 UINT64 mtime_old = 0, mtime_new = 0;
1081 UINT64 ctime_old = 0, ctime_new = 0;
1082 char tmp[128];
1083 char msg[2*SH_BUFSIZE];
1084 char timstr_o[32];
1085 char timstr_n[32];
1086
1087 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
1088 {
1089 for (i = 0; i < SH_MAXCALLS; ++i)
1090 {
1091 store0 = kinfo->kmem_call_table[i];
1092 store1 = kinfo->kmem_code_table[i][0]; store2 = kinfo->kmem_code_table[i][1];
1093 sh_kern_db_syscall (i, _("syscall"),
1094 NULL, &store0, &store1, &store2,
1095 0, SH_KERN_DBPUSH);
1096 }
1097 }
1098
1099 if ((sh.flag.checkSum != SH_CHECK_INIT) ||
1100 (sh.flag.update == S_TRUE && is_init == 1))
1101 {
1102 for (i = 0; i < SH_MAXCALLS; ++i)
1103 {
1104 if (sh_syscalls[i].name == NULL /* || sh_syscalls[i].addr == 0UL */)
1105 break;
1106
1107#ifdef SH_USE_LKM
1108 if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
1109 {
1110 if (check_getdents == 0 &&
1111 0 == strcmp(_(sh_syscalls[i].name), _("sys_getdents")))
1112 {
1113 check_getdents = 1;
1114 sh_error_handle (SH_ERR_WARN, FIL__, __LINE__,
1115 0, MSG_E_SUBGEN,
1116 _("Modified kernel syscall (expected)."),
1117 _(sh_syscalls[i].name) );
1118 copy_if_next = i;
1119 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
1120 continue;
1121 }
1122 /* #ifdef __NR_getdents64 */
1123 else if (check_getdents64 == 0 &&
1124 0 == strcmp(_(sh_syscalls[i].name),
1125 _("sys_getdents64")))
1126 {
1127 check_getdents64 = 1;
1128 sh_error_handle (SH_ERR_WARN, FIL__, __LINE__,
1129 0, MSG_E_SUBGEN,
1130 _("Modified kernel syscall (expected)."),
1131 _(sh_syscalls[i].name) );
1132 copy_if_next_64 = i;
1133 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
1134 continue;
1135 }
1136 /* #endif */
1137 else
1138 {
1139 size_old = sh_syscalls[i].addr;
1140 size_new = kinfo->kmem_call_table[i];
1141 mod_syscall_addr = 1;
1142 }
1143 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
1144 }
1145#else
1146 if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
1147 {
1148 size_old = sh_syscalls[i].addr;
1149 size_new = kinfo->kmem_call_table[i];
1150 mod_syscall_addr = 1;
1151 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
1152 }
1153#endif
1154
1155
1156 /* -- Check the code at syscall address
1157 *
1158 * Stored(old) is sh_syscalls[]
1159 */
1160 if ( (mod_syscall_addr == 0) &&
1161 ((sh_syscalls[i].code[0] != kinfo->kmem_code_table[i][0]) ||
1162 (sh_syscalls[i].code[1] != kinfo->kmem_code_table[i][1]))
1163 )
1164 {
1165 mtime_old = sh_syscalls[i].code[0];
1166 mtime_new = kinfo->kmem_code_table[i][0];
1167 ctime_old = sh_syscalls[i].code[1];
1168 ctime_new = kinfo->kmem_code_table[i][1];
1169 mod_syscall_code = 1;
1170
1171#ifdef SH_USE_LKM
1172 if (i == copy_if_next)
1173 {
1174 mod_syscall_code = 0;
1175 copy_if_next = -1;
1176 }
1177 if (i == copy_if_next_64)
1178 {
1179 mod_syscall_code = 0;
1180 copy_if_next_64 = -1;
1181 }
1182#endif
1183
1184 sh_syscalls[i].code[0] = kinfo->kmem_code_table[i][0];
1185 sh_syscalls[i].code[1] = kinfo->kmem_code_table[i][1];
1186 }
1187
1188 /* Build the error message, if something has been
1189 * detected.
1190 */
1191 if ((mod_syscall_addr != 0) || (mod_syscall_code != 0))
1192 {
1193#ifdef SH_USE_XML
1194 sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ",
1195 _("syscall"), i);
1196#else
1197 sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ",
1198 _("syscall"), i);
1199#endif
1200 sl_strlcpy(msg, tmp, SH_BUFSIZE);
1201
1202 if (mod_syscall_addr != 0)
1203 {
1204 sl_snprintf(tmp, 128, sh_hash_size_format(),
1205 size_old, size_new);
1206 sl_strlcat(msg, tmp, SH_BUFSIZE);
1207 }
1208 if (mod_syscall_code != 0)
1209 {
1210 sl_strlcpy (timstr_o, sh_unix_gmttime (ctime_old), 32);
1211 sl_strlcpy (timstr_n, sh_unix_gmttime (ctime_new), 32);
1212#ifdef SH_USE_XML
1213 sl_snprintf(tmp, 128,
1214 _("ctime_old=\"%s\" ctime_new=\"%s\" "),
1215 timstr_o, timstr_n);
1216#else
1217 sl_snprintf(tmp, 128,
1218 _("ctime_old=<%s>, ctime_new=<%s>, "),
1219 timstr_o, timstr_n);
1220#endif
1221 sl_strlcat(msg, tmp, SH_BUFSIZE);
1222 sl_strlcpy (timstr_o, sh_unix_gmttime (mtime_old), 32);
1223 sl_strlcpy (timstr_n, sh_unix_gmttime (mtime_new), 32);
1224#ifdef SH_USE_XML
1225 sl_snprintf(tmp, 128,
1226 _("mtime_old=\"%s\" mtime_new=\"%s\" "),
1227 timstr_o, timstr_n);
1228#else
1229 sl_snprintf(tmp, 128,
1230 _("mtime_old=<%s>, mtime_new=<%s> "),
1231 timstr_o, timstr_n);
1232#endif
1233 sl_strlcat(msg, tmp, SH_BUFSIZE);
1234 }
1235 sh_error_handle (ShKernSeverity, FIL__, __LINE__,
1236 0, MSG_KERN_SYSCALL,
1237 i, _(sh_syscalls[i].name), msg);
1238 mod_syscall_addr = 0;
1239 mod_syscall_code = 0;
1240 }
1241 }
1242 }
1243 return;
1244}
1245
1246int sh_kern_check_internal ()
1247{
1248 int kd;
1249 int is_init;
1250 pid_t mpid;
1251 int mpipe[2];
1252 int status = 0;
1253
1254 struct sh_kernel_info kinfo;
1255
1256
1257 SL_ENTER(_("sh_kern_check_internal"));
1258
1259 /* -- Check whether initialisation is required; if yes, initialize.
1260 */
1261
1262 if (0 != check_init(&is_init))
1263 {
1264 SL_RETURN( (-1), _("sh_kern_check_internal"));
1265 }
1266
1267
1268 /* -- Open /dev/kmem and fork subprocess to read from it.
1269 */
1270
1271 if (kaddr == (unsigned int) -1) /* kaddr = address of the sys_call_table */
1272 {
1273 sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, MSG_E_SUBGEN,
1274 _("no address for sys_call_table - switching off"),
1275 _("kern_check_internal") );
1276 ShKernActive = S_FALSE;
1277 SL_RETURN( (-1), _("sh_kern_check_internal"));
1278 }
1279
1280 kd = aud_open(FIL__, __LINE__, SL_YESPRIV, _("/dev/kmem"), O_RDONLY, 0);
1281
1282 if (kd < 0)
1283 {
1284 status = errno;
1285 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1286 _("error opening /dev/kmem"),
1287 _("kern_check_internal") );
1288 SL_RETURN( (-1), _("sh_kern_check_internal"));
1289 }
1290
1291 status = aud_pipe(FIL__, __LINE__, mpipe);
1292
1293 if (status == 0)
1294 {
1295 mpid = aud_fork(FIL__, __LINE__);
1296
1297 switch (mpid)
1298 {
1299 case -1:
1300 status = -1;
1301 break;
1302 case 0:
1303
1304 /* -- Child process reads /dev/kmem and writes to pipe
1305 */
1306 run_child(kd, mpipe);
1307 break;
1308
1309 /* -- Parent process reads from child via pipe
1310 */
1311 default:
1312 close(kd);
1313 status = read_from_child(mpid, mpipe, &kinfo);
1314 break;
1315 }
1316 }
1317
1318 if ( status < 0)
1319 {
1320 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1321 _("error reading from /dev/kmem"),
1322 _("kern_check_internal") );
1323 SL_RETURN( (-1), _("sh_kern_check_internal"));
1324 }
1325
1326 /* -- Check the proc_root inode.
1327 *
1328 * This will detect adore-ng.
1329 */
1330 check_proc_root( &kinfo );
1331
1332
1333 /* -- Check the system_call syscall gate.
1334 *
1335 * Stored(old) is system_call_code[]
1336 */
1337 check_syscall_gate( is_init, &kinfo );
1338
1339 /* -- Check the individual syscalls
1340 *
1341 * Stored(old) is sh_syscalls[] array.
1342 */
1343 check_system_calls ( is_init, &kinfo );
1344
1345 /* -- Check the Interrupt Descriptor Table
1346 */
1347 check_idt_table(is_init);
1348
1349 /* -- Check PCI ROM
1350 */
1351 check_pci();
1352
1353 SL_RETURN( (0), _("sh_kern_check_internal"));
1354}
1355/* ifdef HOST_IS_LINUX */
1356#else
1357
1358/********************************************************
1359 *
1360 * --- BSD ---
1361 *
1362 ********************************************************/
1363
1364#include <err.h>
1365#include <kvm.h>
1366#include <nlist.h>
1367
1368/* not OpenBSD */
1369#if defined(HOST_IS_FREEBSD)
1370#include <sys/sysent.h>
1371#endif
1372
1373#include <sys/syscall.h>
1374#ifndef SYS_MAXSYSCALL
1375#define SYS_MAXSYSCALL 512
1376#endif
1377
1378#ifdef __OpenBSD__
1379struct proc;
1380struct sysent {
1381 short sy_narg;
1382 short sy_argsize;
1383 int (*sy_call)(struct proc *, void *, register_t *);
1384};
1385#endif
1386
1387int sh_kern_data_init ()
1388{
1389 unsigned long store0 = 0;
1390 unsigned int store1 = 0, store2 = 0;
1391 int datasize, i;
1392 char * databuf = NULL;
1393
1394 /* syscall address and code
1395 */
1396 for (i = 0; i < SH_MAXCALLS; ++i)
1397 {
1398 databuf = sh_kern_db_syscall (i, _("syscall"),
1399 NULL, &store0, &store1, &store2,
1400 &datasize, SH_KERN_DBPOP);
1401 sh_syscalls[i].addr = store0;
1402 if (databuf != NULL) { SH_FREE(databuf); }
1403 if (store0 == 0) {
1404 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1405 _("syscall address not found in database"),
1406 _("sh_kern_data_init"));
1407 return -1;
1408 }
1409
1410 sh_syscalls[i].code[0] = (unsigned int) store1;
1411 sh_syscalls[i].code[1] = (unsigned int) store2;
1412 if ((store1 == 0) || (store2 == 0)) {
1413 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1414 _("syscall code not found in database"),
1415 _("sh_kern_data_init"));
1416 return -1;
1417 }
1418
1419 }
1420
1421 return 0;
1422}
1423
1424int sh_kern_check_internal ()
1425{
1426 struct sysent sy;
1427 kvm_t * kd;
1428 int i;
1429 int status = -1;
1430 char errbuf[_POSIX2_LINE_MAX+1];
1431 struct nlist * sys_list;
1432 struct nlist list[2];
1433
1434 unsigned long offset = 0L;
1435 unsigned int syscall_code[2]; /* 8 bytes */
1436 unsigned long syscall_addr;
1437
1438 unsigned long store0 = 0;
1439 unsigned int store1 = 0, store2 = 0;
1440
1441 UINT64 size_old = 0, size_new = 0;
1442 UINT64 mtime_old = 0, mtime_new = 0;
1443 UINT64 ctime_old = 0, ctime_new = 0;
1444 char tmp[128];
1445 char msg[2*SH_BUFSIZE];
1446 char timstr_o[32];
1447 char timstr_n[32];
1448
1449 static int is_init = 0;
1450
1451 SL_ENTER(_("sh_kern_check_internal"));
1452
1453 if (is_init == 0)
1454 {
1455 if (sh.flag.checkSum != SH_CHECK_INIT && sh.flag.update != S_TRUE)
1456 {
1457 if (0 == sh_kern_data_init()) {
1458 is_init = 1;
1459 } else {
1460 sh_error_handle (ShKernSeverity, FIL__, __LINE__, status,
1461 MSG_E_SUBGEN,
1462 _("could not initialize - switching off"),
1463 _("kern_check_internal") );
1464 ShKernActive = S_FALSE;
1465 SL_RETURN( (-1), _("sh_kern_check_internal"));
1466 }
1467 }
1468 else if ((sh.flag.checkSum == SH_CHECK_INIT ||
1469 sh.flag.checkSum == SH_CHECK_CHECK) &&
1470 (sh.flag.update == S_TRUE))
1471 {
1472 if (0 == sh_kern_data_init()) {
1473 is_init = 1;
1474 } else {
1475 sh_error_handle (ShKernSeverity, FIL__, __LINE__, status,
1476 MSG_E_SUBGEN,
1477 _("no or incomplete data in baseline database"),
1478 _("kern_check_internal") );
1479 }
1480 }
1481 }
1482
1483 /* defined, but not used
1484 */
1485 ShKernDelay = 0;
1486
1487 list[0].n_name = "_sysent";
1488 list[1].n_name = NULL;
1489
1490 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
1491 if (!kd)
1492 {
1493 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1494 errbuf,
1495 _("kvm_openfiles") );
1496 SL_RETURN( (-1), _("sh_kern_check_internal"));
1497 }
1498
1499 i = kvm_nlist(kd, list);
1500 if (i == -1)
1501 {
1502 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1503 kvm_geterr(kd),
1504 _("kvm_nlist (_sysent)") );
1505 kvm_close(kd);
1506 SL_RETURN( (-1), _("sh_kern_check_internal"));
1507 }
1508
1509 sys_list = SH_ALLOC((SYS_MAXSYSCALL+1) * sizeof(struct nlist));
1510
1511 for (i = 0; i < SH_MAXCALLS; ++i)
1512 sys_list[i].n_name = sh_syscalls[i].name;
1513 sys_list[SH_MAXCALLS].n_name = NULL;
1514
1515 i = kvm_nlist(kd, sys_list);
1516 if (i == -1)
1517 {
1518 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1519 kvm_geterr(kd),
1520 _("kvm_nlist (syscalls)") );
1521 kvm_close(kd);
1522 SH_FREE(sys_list);
1523 SL_RETURN( (-1), _("sh_kern_check_internal"));
1524 }
1525 else if (i > 0)
1526 {
1527 sl_snprintf(tmp, 128,
1528 _("%d invalid syscalls"), i);
1529 /*
1530 for (i = 0; i < SH_MAXCALLS; ++i) {
1531 if (sys_list[i].n_type == 0 && sys_list[i].n_value == 0)
1532 fprintf(stderr, "invalid: [%3d] %s\n", i, sh_syscalls[i].name);
1533 }
1534 */
1535 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
1536 tmp,
1537 _("kvm_nlist (syscalls)") );
1538 }
1539
1540 /* Check the individual syscalls
1541 *
1542 * Stored(old) is sh_syscalls[] array.
1543 */
1544 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
1545 {
1546 for (i = 0; i < SH_MAXCALLS; ++i)
1547 {
1548 if (sh_syscalls[i].name == NULL)
1549 {
1550 sl_snprintf(tmp, 128,
1551 _("too few entries in sh_syscalls[]: have %d, expect %d"),
1552 i, SH_MAXCALLS);
1553
1554 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1555 tmp,
1556 _("sh_kern_check_internal") );
1557 break;
1558 }
1559
1560 /* read address of syscall from sysent table
1561 */
1562 offset = list[0].n_value + (i*sizeof(struct sysent));
1563 if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
1564 {
1565 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1566 kvm_geterr(kd),
1567 _("kvm_read (syscall table)") );
1568 kvm_close(kd);
1569 SH_FREE(sys_list);
1570 SL_RETURN( (-1), _("sh_kern_check_internal"));
1571 }
1572 syscall_addr = (unsigned long) sy.sy_call;
1573 store0 = syscall_addr;
1574
1575 /* read the syscall code
1576 */
1577 if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]),
1578 2 * sizeof(unsigned int)) < 0)
1579 {
1580 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1581 kvm_geterr(kd),
1582 _("kvm_read (syscall code)") );
1583 kvm_close(kd);
1584 SH_FREE(sys_list);
1585 SL_RETURN( (-1), _("sh_kern_check_internal"));
1586 }
1587 store1 = syscall_code[0]; store2 = syscall_code[1];
1588
1589 sh_kern_db_syscall (i, _("syscall"),
1590 NULL, &store0, &store1, &store2,
1591 0, SH_KERN_DBPUSH);
1592 }
1593 }
1594
1595 if ((sh.flag.checkSum != SH_CHECK_INIT) ||
1596 (sh.flag.update == S_TRUE && is_init == 1))
1597 {
1598 for (i = 0; i < SH_MAXCALLS; ++i)
1599 {
1600 if (sh_syscalls[i].name == NULL)
1601 {
1602 sl_snprintf(tmp, 128,
1603 _("too few entries in sh_syscalls[]: have %d, expect %d"),
1604 i, SH_MAXCALLS);
1605
1606 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1607 tmp,
1608 _("sh_kern_check_internal") );
1609 break;
1610 }
1611
1612 /* read address of syscall from sysent table
1613 */
1614 offset = list[0].n_value + (i*sizeof(struct sysent));
1615 if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
1616 {
1617 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1618 kvm_geterr(kd),
1619 _("kvm_read (syscall table)") );
1620 kvm_close(kd);
1621 SH_FREE(sys_list);
1622 SL_RETURN( (-1), _("sh_kern_check_internal"));
1623 }
1624 syscall_addr = (unsigned long) sy.sy_call;
1625
1626 if (sh_syscalls[i].addr != syscall_addr)
1627 {
1628#ifdef SH_USE_XML
1629 sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ",
1630 _("syscall"), i);
1631#else
1632 sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ",
1633 _("syscall"), i);
1634#endif
1635 sl_strlcpy(msg, tmp, SH_BUFSIZE);
1636
1637 size_old = sh_syscalls[i].addr;
1638 size_new = syscall_addr;
1639 sl_snprintf(tmp, 128, sh_hash_size_format(),
1640 size_old, size_new);
1641 sl_strlcat(msg, tmp, SH_BUFSIZE);
1642
1643 sh_error_handle (ShKernSeverity, FIL__, __LINE__,
1644 status, MSG_KERN_SYSCALL,
1645 i, _(sh_syscalls[i].name),
1646 msg);
1647 sh_syscalls[i].addr = syscall_addr;
1648 }
1649 else
1650 {
1651 /* read the syscall code
1652 */
1653 if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]),
1654 2 * sizeof(unsigned int)) < 0)
1655 {
1656 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1657 kvm_geterr(kd),
1658 _("kvm_read (syscall code)") );
1659 kvm_close(kd);
1660 SH_FREE(sys_list);
1661 SL_RETURN( (-1), _("sh_kern_check_internal"));
1662 }
1663
1664 if (sh_syscalls[i].code[0] != syscall_code[0] ||
1665 sh_syscalls[i].code[1] != syscall_code[1])
1666 {
1667 mtime_old = sh_syscalls[i].code[0];
1668 mtime_new = syscall_code[0];
1669 ctime_old = sh_syscalls[i].code[1];
1670 ctime_new = syscall_code[1];
1671
1672#ifdef SH_USE_XML
1673 sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ",
1674 _("syscall"), i);
1675#else
1676 sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ",
1677 _("syscall"), i);
1678#endif
1679 sl_strlcpy(msg, tmp, SH_BUFSIZE);
1680
1681 sl_strlcpy (timstr_o, sh_unix_gmttime (ctime_old), 32);
1682 sl_strlcpy (timstr_n, sh_unix_gmttime (ctime_new), 32);
1683#ifdef SH_USE_XML
1684 sl_snprintf(tmp, 128,
1685 _("ctime_old=\"%s\" ctime_new=\"%s\" "),
1686 timstr_o, timstr_n);
1687#else
1688 sl_snprintf(tmp, 128,
1689 _("ctime_old=<%s>, ctime_new=<%s>, "),
1690 timstr_o, timstr_n);
1691#endif
1692 sl_strlcat(msg, tmp, SH_BUFSIZE);
1693 sl_strlcpy (timstr_o, sh_unix_gmttime (mtime_old), 32);
1694 sl_strlcpy (timstr_n, sh_unix_gmttime (mtime_new), 32);
1695#ifdef SH_USE_XML
1696 sl_snprintf(tmp, 128,
1697 _("mtime_old=\"%s\" mtime_new=\"%s\" "),
1698 timstr_o, timstr_n);
1699#else
1700 sl_snprintf(tmp, 128,
1701 _("mtime_old=<%s>, mtime_new=<%s> "),
1702 timstr_o, timstr_n);
1703#endif
1704 sl_strlcat(msg, tmp, SH_BUFSIZE);
1705
1706 sh_error_handle (ShKernSeverity, FIL__, __LINE__,
1707 status, MSG_KERN_SYSCALL,
1708 i, _(sh_syscalls[i].name),
1709 msg);
1710 sh_syscalls[i].code[0] = syscall_code[0];
1711 sh_syscalls[i].code[1] = syscall_code[1];
1712 }
1713 }
1714 }
1715 }
1716 SH_FREE(sys_list);
1717 if(kvm_close(kd) < 0)
1718 {
1719 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1720 kvm_geterr(kd),
1721 _("kvm_close") );
1722 exit(EXIT_FAILURE);
1723 }
1724
1725 SL_RETURN( (0), _("sh_kern_check_internal"));
1726}
1727
1728#endif
1729
1730/*************
1731 *
1732 * module init
1733 *
1734 *************/
1735#if defined(HOST_IS_LINUX)
1736#include <sys/utsname.h>
1737#endif
1738
1739static int AddressReconf = 0;
1740
1741int sh_kern_init ()
1742{
1743#if defined(HOST_IS_LINUX)
1744 struct utsname buf;
1745 char * str;
1746#endif
1747
1748 SL_ENTER(_("sh_kern_init"));
1749 if (ShKernActive == S_FALSE)
1750 SL_RETURN( (-1), _("sh_kern_init"));
1751
1752#if defined(HOST_IS_LINUX)
1753 uname(&buf);
1754
1755 if ((AddressReconf < 5) && (0 != strcmp(SH_KERNEL_VERSION, buf.release)))
1756 {
1757 str = SH_ALLOC(256);
1758 sl_snprintf(str, 256,
1759 "Compiled for kernel %s, but current kernel is %s, and kernel addresses have not been re-configured",
1760 SH_KERNEL_VERSION, buf.release);
1761 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
1762 str,
1763 _("kern_check") );
1764 SH_FREE(str);
1765 ShKernActive = S_FALSE;
1766 SL_RETURN( (-1), _("sh_kern_init"));
1767 }
1768#endif
1769
1770 lastcheck = time (NULL);
1771 if (sh.flag.checkSum != SH_CHECK_INIT)
1772 {
1773 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1774 _("Checking kernel syscalls"),
1775 _("kern_check") );
1776 }
1777 sh_kern_check_internal ();
1778 SL_RETURN( (0), _("sh_kern_init"));
1779}
1780
1781/*************
1782 *
1783 * module cleanup
1784 *
1785 *************/
1786int sh_kern_end ()
1787{
1788 return (0);
1789}
1790
1791
1792/*************
1793 *
1794 * module timer
1795 *
1796 *************/
1797int sh_kern_timer (time_t tcurrent)
1798{
1799 if (ShKernActive == S_FALSE)
1800 return 0;
1801
1802 if ((int) (tcurrent - lastcheck) >= ShKernInterval)
1803 {
1804 lastcheck = tcurrent;
1805 return (-1);
1806 }
1807 return 0;
1808}
1809
1810/*************
1811 *
1812 * module check
1813 *
1814 *************/
1815int sh_kern_check ()
1816{
1817 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
1818 _("Checking kernel syscalls"),
1819 _("kern_check") );
1820 return (sh_kern_check_internal ());
1821}
1822
1823/*************
1824 *
1825 * module setup
1826 *
1827 *************/
1828
1829int sh_kern_set_severity (const char * c)
1830{
1831 char tmp[32];
1832 tmp[0] = '='; tmp[1] = '\0';
1833 sl_strlcat (tmp, c, 32);
1834 sh_error_set_level (tmp, &ShKernSeverity);
1835 return 0;
1836}
1837
1838int sh_kern_set_timer (const char * c)
1839{
1840 long val;
1841
1842 SL_ENTER(_("sh_kern_set_timer"));
1843
1844 val = strtol (c, (char **)NULL, 10);
1845 if (val <= 0)
1846 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1847 _("kern timer"), c);
1848
1849 val = (val <= 0 ? 60 : val);
1850
1851 ShKernInterval = (time_t) val;
1852 SL_RETURN( 0, _("sh_kern_set_timer"));
1853}
1854
1855int sh_kern_set_activate (const char * c)
1856{
1857 int i;
1858 SL_ENTER(_("sh_kern_set_activate"));
1859 i = sh_util_flagval(c, &ShKernActive);
1860 SL_RETURN(i, _("sh_kern_set_activate"));
1861}
1862
1863int sh_kern_set_idt (const char * c)
1864{
1865 int i;
1866 SL_ENTER(_("sh_kern_set_idt"));
1867 i = sh_util_flagval(c, &ShKernIDT);
1868 SL_RETURN(i, _("sh_kern_set_idt"));
1869}
1870
1871int sh_kern_set_sc_addr (const char * c)
1872{
1873 char * endptr;
1874 unsigned long value;
1875
1876 SL_ENTER(_("sh_kern_set_sc_addr"));
1877 errno = 0;
1878 value = strtoul(c, &endptr, 16);
1879 if ((ULONG_MAX == value) && (errno == ERANGE))
1880 {
1881 SL_RETURN((-1), _("sh_kern_set_sc_addr"));
1882 }
1883 if ((*c == '\0') || (*endptr != '\0'))
1884 {
1885 SL_RETURN((-1), _("sh_kern_set_sc_addr"));
1886 }
1887 system_call_addr = value;
1888 ++AddressReconf;
1889 SL_RETURN((0), _("sh_kern_set_sc_addr"));
1890}
1891
1892int sh_kern_set_sct_addr (const char * c)
1893{
1894 char * endptr;
1895 unsigned long value;
1896
1897 SL_ENTER(_("sh_kern_set_sct_addr"));
1898 errno = 0;
1899 value = strtoul(c, &endptr, 16);
1900 if ((ULONG_MAX == value) && (errno == ERANGE))
1901 {
1902 SL_RETURN((-1), _("sh_kern_set_sct_addr"));
1903 }
1904 if ((*c == '\0') || (*endptr != '\0'))
1905 {
1906 SL_RETURN((-1), _("sh_kern_set_sct_addr"));
1907 }
1908 kaddr = (unsigned int) value;
1909 ++AddressReconf;
1910 SL_RETURN((0), _("sh_kern_set_sct_addr"));
1911}
1912
1913int sh_kern_set_proc_root (const char * c)
1914{
1915 char * endptr;
1916 unsigned long value;
1917
1918 SL_ENTER(_("sh_kern_set_proc_root"));
1919 errno = 0;
1920 value = strtoul(c, &endptr, 16);
1921 if ((ULONG_MAX == value) && (errno == ERANGE))
1922 {
1923 SL_RETURN((-1), _("sh_kern_set_proc_root"));
1924 }
1925 if ((*c == '\0') || (*endptr != '\0'))
1926 {
1927 SL_RETURN((-1), _("sh_kern_set_proc_root"));
1928 }
1929
1930 proc_root = value;
1931 ++AddressReconf;
1932 SL_RETURN((0), _("sh_kern_set_proc_root"));
1933}
1934
1935int sh_kern_set_proc_root_iops (const char * c)
1936{
1937 char * endptr;
1938 unsigned long value;
1939
1940 SL_ENTER(_("sh_kern_set_proc_root_iops"));
1941 errno = 0;
1942 value = strtoul(c, &endptr, 16);
1943 if ((ULONG_MAX == value) && (errno == ERANGE))
1944 {
1945 SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
1946 }
1947 if ((*c == '\0') || (*endptr != '\0'))
1948 {
1949 SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
1950 }
1951
1952 proc_root_iops = value;
1953 ++AddressReconf;
1954 SL_RETURN((0), _("sh_kern_set_proc_root_iops"));
1955}
1956
1957int sh_kern_set_proc_root_lookup (const char * c)
1958{
1959 char * endptr;
1960 unsigned long value;
1961
1962 SL_ENTER(_("sh_kern_set_proc_root_lookup"));
1963 errno = 0;
1964 value = strtoul(c, &endptr, 16);
1965 if ((ULONG_MAX == value) && (errno == ERANGE))
1966 {
1967 SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
1968 }
1969 if ((*c == '\0') || (*endptr != '\0'))
1970 {
1971 SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
1972 }
1973 proc_root_lookup = value;
1974 ++AddressReconf;
1975 SL_RETURN((0), _("sh_kern_set_proc_root_lookup"));
1976}
1977
1978#endif
1979
1980/* #ifdef SH_USE_KERN */
1981#endif
Note: See TracBrowser for help on using the repository browser.