source: trunk/src/sh_kern.c@ 278

Last change on this file since 278 was 277, checked in by katerina, 15 years ago

Fix for bug in kernel check (ticket #198).

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