source: trunk/src/sh_kern.c@ 91

Last change on this file since 91 was 83, checked in by rainer, 18 years ago

Fix for ticket #46 (kernel check issue with 2.6.19).

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