source: branches/samhain-2_2-branch/src/sh_kern.c@ 82

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

Fix problems with linux kernel 2.6.17

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