source: trunk/src/sh_kern.c@ 276

Last change on this file since 276 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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