source: trunk/src/sh_kern.c@ 47

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

Use mmap() if read() fails for /dev/kmem

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