source: trunk/src/sh_kern.c@ 77

Last change on this file since 77 was 68, checked in by rainer, 18 years ago

Update trunk to samhain 2.3

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