source: trunk/src/sh_kern.c@ 34

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

Code cleanup and minor fixes

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