source: trunk/src/sh_kern.c@ 20

Last change on this file since 20 was 3, checked in by rainer, 19 years ago

More fixes for update function, released 2.1.1 version.

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