source: trunk/src/sh_kern.c@ 225

Last change on this file since 225 was 223, checked in by katerina, 16 years ago

Allow to switch off check of PCI expansion ROMs (ticket #149).

File size: 49.5 KB
RevLine 
[1]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>
[41]37#include <sys/mman.h>
[1]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"
[131]60#include "sh_pthread.h"
[1]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 {
[223]90 N_("kernelcheckpci"),
91 sh_kern_set_pci
92 },
93 {
[1]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;
[223]126static int ShKernPCI = S_TRUE;
[1]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
[93]160/* This is the module 'reconfigure' function, which is a no-op.
161 */
[1]162int sh_kern_null()
163{
164 return 0;
165}
166
[93]167#define SH_KERN_DBPUSH 0
168#define SH_KERN_DBPOP 1
[1]169
170char * sh_kern_db_syscall (int num, char * prefix,
[93]171 void * in_name, unsigned long * addr,
[1]172 unsigned int * code1, unsigned int * code2,
173 int * size, int direction)
174{
[83]175 char path[128];
176 char * p = NULL;
177 unsigned long x1 = 0, x2 = 0;
178 unsigned char * name = (unsigned char *) in_name;
[1]179
180 sl_snprintf(path, 128, "K_%s_%04d", prefix, num);
181
[93]182 if (direction == SH_KERN_DBPUSH)
[1]183 {
184 x1 = *code1;
185 x2 = *code2;
186
[93]187 sh_hash_push2db (path, *addr, x1, x2,
[1]188 name, (name == NULL) ? 0 : (*size));
189 }
190 else
191 {
[93]192 p = sh_hash_db2pop (path, addr, &x1, &x2, size);
[1]193 *code1 = (unsigned int) x1;
194 *code2 = (unsigned int) x2;
195 }
196 return p;
197}
[93]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;
[137]209 char i2h[2];
[93]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 {
[137]234 p = sh_util_charhex (old[k], i2h);
[93]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 {
[137]242 p = sh_util_charhex (new[k], i2h);
[93]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}
[1]267
268#ifdef HOST_IS_LINUX
269
[93]270/*
271 * Interrupt Descriptor Table
272 */
[162]273#ifdef HAVE_ASM_SEGMENT_H
[93]274#include <asm/segment.h>
[162]275#endif
[93]276
277#define SH_MAXIDT 256
278
279static unsigned char sh_idt_table[SH_MAXIDT * 8];
280
281static char * sh_strseg(unsigned short segment)
[1]282{
[93]283 switch (segment) {
[162]284#ifdef __KERNEL_CS
[93]285 case __KERNEL_CS:
286 return _("KERNEL_CS");
[162]287#endif
288#ifdef __KERNEL_DS
[93]289 case __KERNEL_DS:
290 return _("KERNEL_DS");
[162]291#endif
292#ifdef __USER_CS
[93]293 case __USER_CS:
294 return _("USER_CS");
[162]295#endif
296#ifdef __USER_DS
[93]297 case __USER_DS:
298 return _("USER_DS");
[162]299#endif
[93]300 default:
301 return _("unknown");
302 }
303}
304
305
306static int sh_kern_data_init ()
307{
[1]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,
[93]317 &datasize, SH_KERN_DBPOP);
[1]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,
[93]337 &datasize, SH_KERN_DBPOP);
[1]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 }
[93]345
[1]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 }
[93]353
[1]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,
[93]367 &datasize, SH_KERN_DBPOP);
[1]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
[83]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 */
[1]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 *);
[22]403 /* flawfinder: ignore */
[1]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
[83]419/*
420 * this one is just for dummy purposes
[51]421 */
[1]422struct file_operations {
423 int (*create) (int *,int *,int);
424};
425
[83]426/* Defined in include/linux/proc_fs.h
427 * Here we are interested in the 'proc_iops' member.
428 */
[1]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;
[51]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;
[1]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
[93]456
[41]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 {
[192]494 memset(buf, '\0', len);
[41]495 return -1;
496 }
497 memcpy (buf, &kmap[roff], len);
498 return munmap(kmap, len+sz);
499}
500
[93]501
502static int check_init (int * init_retval)
[1]503{
504 static int is_init = 0;
505
[93]506 SL_ENTER(_("check_init"));
[1]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 {
[93]515 sh_error_handle (ShKernSeverity, FIL__, __LINE__, 1,
[1]516 MSG_E_SUBGEN,
[93]517 _("could not initialize kernel check - switching off"),
518 _("check_init") );
[1]519 ShKernActive = S_FALSE;
[93]520 *init_retval = is_init;
521 SL_RETURN( (-1), _("check_init"));
[1]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 {
[93]531 sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 0,
[1]532 MSG_E_SUBGEN,
[93]533 _("no or incomplete data in baseline database for kernel check"),
534 _("check_init") );
[1]535 }
536 }
537 }
[93]538 *init_retval = is_init;
539 SL_RETURN( (0), _("check_init"));
540}
[1]541
[93]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 = close(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
[1]567 */
[93]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 }
[1]579
[93]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)
[1]585 {
[93]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 {
[192]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;
[93]605 }
606 else
607 {
[192]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;
[93]612 }
613 }
[1]614 }
[93]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);
[192]631 if (sh_kern_read_data (kd, idt_addr,
632 (unsigned char *) sh_idt_table, idt_size*8))
633 status = -5;
[93]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 {
[192]644 if (sh_kern_read_data (kd, system_call_addr,
645 (unsigned char *) new_system_call_code,
646 SH_KERN_SCC))
647 status = -6;
[93]648 }
[1]649
[93]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 {
[192]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;
[93]664 }
[1]665
[93]666 /*
667 * Write out data to the pipe
668 */
[192]669 status = write(mpipe[1], &status, sizeof(int));
[93]670
[192]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));
[93]688
689 _exit( (status >= 0) ? 0 : status);
690}
[1]691
[93]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;
[192]708 int errcode;
[93]709
710 /* Close reading side of pipe, and wait some milliseconds
711 */
712 close (mpipe[1]);
713 retry_msleep (0, ShKernDelay); /* milliseconds */
714
[192]715 if (sizeof(int) != read(mpipe[0], &errcode, sizeof(int)))
716 status = -3;
[93]717 else
718 status = 0;
719
[192]720 if (errcode)
721 status = errcode - 100;
722
[93]723 if(status == 0)
[1]724 {
[192]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 {
[93]735 size = sizeof(unsigned int) * 2 * SH_KERN_SIZ;
[1]736
[93]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 close (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)
[1]823 {
[93]824 datasize = 8;
825 for (j = 0; j < SH_MAXIDT; ++j)
[1]826 {
[93]827 sh_kern_db_syscall (j, _("idt_table"),
828 &sh_idt_table[j*8],
829 &store0, &store1, &store2,
830 &datasize, SH_KERN_DBPUSH);
[1]831 }
[93]832 }
[1]833
[93]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[]
[1]840 */
[93]841 for (j = 0; j < SH_MAXIDT; ++j)
[1]842 {
[93]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)
[1]854 {
[93]855 sh_idt_table[i+2] = '\0';
856 sh_idt_table[i+3] = '\0';
857 sh_idt_table[i+5] = '\0';
[1]858
[93]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)
[1]864 {
[93]865 idt_table[i+2] = '\0';
866 idt_table[i+3] = '\0';
867 idt_table[i+5] = '\0';
[1]868 }
[93]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)
[1]884 {
[93]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'; }
[1]891 }
[93]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);
[1]919 }
920 }
[93]921 }
922 }
923}
[1]924
925
[93]926#define SYS_BUS_PCI _("/sys/bus/pci/devices")
927#include <dirent.h>
[1]928
[93]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);
[1]936
[93]937 (void) sl_strlcpy (theFile.fullpath, pcipath, PATH_MAX);
938 theFile.check_mask = sh_files_maskof(SH_LEVEL_READONLY);
[162]939 theFile.check_mask &= ~(MODI_MTM|MODI_CTM|MODI_INO);
[114]940 CLEAR_SH_FFLAG_REPORTED(theFile.file_reported);
[93]941 theFile.attr_string = NULL;
[167]942 theFile.link_path = NULL;
[93]943
944 status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO],
945 name, &theFile, fileHash, 0);
[1]946
[93]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);
[167]956 goto out;
[93]957 }
[1]958
[93]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 }
[1]967
[167]968 out:
969 if (theFile.attr_string) SH_FREE(theFile.attr_string);
970 if (theFile.link_path) SH_FREE(theFile.link_path);
[93]971 return;
972}
[1]973
[93]974static void check_pci_rom (char * pcipath, char * name)
975{
976 struct stat buf;
977 int fd;
[162]978 int status;
[1]979
[93]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 );
[223]986 if (fd)
987 {
988 do {
989 status = write( fd, "1", 1 );
990 } while (status < 0 && errno == EINTR);
991 close ( fd );
[1]992
[223]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 close ( fd );
1004 }
1005 }
1006 }
[1]1007 }
[93]1008 return;
1009}
[1]1010
[93]1011static void check_pci()
1012{
1013 char pci_dir[256];
1014 char * pcipath;
1015 DIR * df;
1016 struct dirent * entry;
1017
[223]1018 if (ShKernPCI != S_TRUE)
1019 return;
1020
[93]1021 sl_strlcpy(pci_dir, SYS_BUS_PCI, sizeof(pci_dir));
1022
1023 df = opendir(pci_dir);
1024 if (df)
[1]1025 {
[143]1026 while (1)
1027 {
1028 SH_MUTEX_LOCK(mutex_readdir);
1029 entry = readdir(df);
1030 SH_MUTEX_UNLOCK(mutex_readdir);
[131]1031
[143]1032 if (entry == NULL)
1033 break;
1034
[93]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 }
[131]1044
[93]1045 closedir(df);
[1]1046 }
[223]1047 return;
[93]1048}
[1]1049
[93]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
[102]1058/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
1059#if SH_KERNEL_NUMBER < 132629
1060 struct inode_operations proc_root_inode;
1061
[93]1062 memcpy (&proc_root_inode, &(kinfo->proc_root_inode), sizeof(struct inode_operations));
1063
[102]1064 /* Seems that the info does not relate anymore to proc_root_lookup(?)
1065 */
[1]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 }
[102]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)
[83]1075 && (proc_root_dir.size != proc_root_iops)
1076 && (((unsigned int) * &proc_root_dir.proc_fops) != proc_root_iops)
1077 )
[1]1078 {
1079 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
1080 _("proc_root.proc_iops != proc_root_inode_operations"));
1081 }
[102]1082
[93]1083 return;
1084}
[1]1085
[93]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
[3]1099 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]1100 {
1101 store0 = 0; store1 = 0; store2 = 0;
[93]1102 datasize = SH_KERN_SCC;
[1]1103 sh_kern_db_syscall (0, _("system_call"),
[93]1104 &(kinfo->new_system_call_code), &store0, &store1, &store2,
1105 &datasize, SH_KERN_DBPUSH);
[1]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 {
[93]1113 if (system_call_code[i] != kinfo->new_system_call_code[i])
[1]1114 {
1115
[93]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);
[1]1120
1121 sh_error_handle (ShKernSeverity, FIL__, __LINE__,
[93]1122 0, MSG_KERN_GATE,
1123 kinfo->new_system_call_code[i], 0,
[1]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)
[93]1129 system_call_code[j] = kinfo->new_system_call_code[j];
[1]1130 break;
1131 }
1132 }
1133 }
[93]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
[3]1162 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]1163 {
1164 for (i = 0; i < SH_MAXCALLS; ++i)
1165 {
[93]1166 store0 = kinfo->kmem_call_table[i];
1167 store1 = kinfo->kmem_code_table[i][0]; store2 = kinfo->kmem_code_table[i][1];
[1]1168 sh_kern_db_syscall (i, _("syscall"),
1169 NULL, &store0, &store1, &store2,
[93]1170 0, SH_KERN_DBPUSH);
[1]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
[93]1183 if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
[1]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__,
[93]1190 0, MSG_E_SUBGEN,
[1]1191 _("Modified kernel syscall (expected)."),
1192 _(sh_syscalls[i].name) );
1193 copy_if_next = i;
[93]1194 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]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__,
[93]1204 0, MSG_E_SUBGEN,
[1]1205 _("Modified kernel syscall (expected)."),
1206 _(sh_syscalls[i].name) );
1207 copy_if_next_64 = i;
[93]1208 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1209 continue;
1210 }
1211 /* #endif */
1212 else
1213 {
1214 size_old = sh_syscalls[i].addr;
[93]1215 size_new = kinfo->kmem_call_table[i];
[1]1216 mod_syscall_addr = 1;
1217 }
[93]1218 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1219 }
1220#else
[93]1221 if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
[1]1222 {
1223 size_old = sh_syscalls[i].addr;
[93]1224 size_new = kinfo->kmem_call_table[i];
[1]1225 mod_syscall_addr = 1;
[93]1226 sh_syscalls[i].addr = kinfo->kmem_call_table[i];
[1]1227 }
1228#endif
1229
1230
[93]1231 /* -- Check the code at syscall address
[1]1232 *
1233 * Stored(old) is sh_syscalls[]
1234 */
1235 if ( (mod_syscall_addr == 0) &&
[93]1236 ((sh_syscalls[i].code[0] != kinfo->kmem_code_table[i][0]) ||
1237 (sh_syscalls[i].code[1] != kinfo->kmem_code_table[i][1]))
[1]1238 )
1239 {
1240 mtime_old = sh_syscalls[i].code[0];
[93]1241 mtime_new = kinfo->kmem_code_table[i][0];
[1]1242 ctime_old = sh_syscalls[i].code[1];
[93]1243 ctime_new = kinfo->kmem_code_table[i][1];
[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
[93]1259 sh_syscalls[i].code[0] = kinfo->kmem_code_table[i][0];
1260 sh_syscalls[i].code[1] = kinfo->kmem_code_table[i][1];
[1]1261 }
[93]1262
1263 /* Build the error message, if something has been
[1]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 {
[132]1285 (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
1286 (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
[1]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);
[132]1297 (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
1298 (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
[1]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__,
[93]1311 0, MSG_KERN_SYSCALL,
[1]1312 i, _(sh_syscalls[i].name), msg);
1313 mod_syscall_addr = 0;
1314 mod_syscall_code = 0;
1315 }
1316 }
1317 }
[93]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;
[1]1328
[93]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))
[1]1338 {
[93]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)
[1]1373 {
[93]1374 case -1:
1375 status = -1;
1376 break;
1377 case 0:
[1]1378
[93]1379 /* -- Child process reads /dev/kmem and writes to pipe
[1]1380 */
[93]1381 run_child(kd, mpipe);
1382 break;
[1]1383
[93]1384 /* -- Parent process reads from child via pipe
1385 */
1386 default:
1387 close(kd);
1388 status = read_from_child(mpid, mpipe, &kinfo);
1389 break;
1390 }
1391 }
[1]1392
[93]1393 if ( status < 0)
1394 {
[192]1395 char errmsg[SH_ERRBUF_SIZE];
1396 sl_snprintf(errmsg, SH_ERRBUF_SIZE,
1397 _("error reading from /dev/kmem: %d"), status);
[93]1398 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
[192]1399 errmsg,
[93]1400 _("kern_check_internal") );
1401 SL_RETURN( (-1), _("sh_kern_check_internal"));
1402 }
[1]1403
[93]1404 /* -- Check the proc_root inode.
1405 *
1406 * This will detect adore-ng.
1407 */
1408 check_proc_root( &kinfo );
[1]1409
1410
[93]1411 /* -- Check the system_call syscall gate.
1412 *
1413 * Stored(old) is system_call_code[]
1414 */
1415 check_syscall_gate( is_init, &kinfo );
[1]1416
[93]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
[1]1431 SL_RETURN( (0), _("sh_kern_check_internal"));
1432}
1433/* ifdef HOST_IS_LINUX */
1434#else
1435
[93]1436/********************************************************
1437 *
1438 * --- BSD ---
1439 *
1440 ********************************************************/
1441
[1]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,
[93]1478 &datasize, SH_KERN_DBPOP);
[1]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 */
[3]1622 if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
[1]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,
[93]1669 0, SH_KERN_DBPUSH);
[1]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
[132]1759 (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
1760 (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
[1]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);
[132]1771 (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
1772 (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
[1]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
[140]1819int sh_kern_init (struct mod_type * arg)
[1]1820{
1821#if defined(HOST_IS_LINUX)
1822 struct utsname buf;
1823 char * str;
1824#endif
[140]1825 (void) arg;
[1]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
[68]1908int sh_kern_set_severity (const char * c)
[1]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
[68]1917int sh_kern_set_timer (const char * c)
[1]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
[68]1934int sh_kern_set_activate (const char * c)
[1]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
[68]1942int sh_kern_set_idt (const char * c)
[1]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
[223]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
[68]1958int sh_kern_set_sc_addr (const char * c)
[1]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
[68]1979int sh_kern_set_sct_addr (const char * c)
[1]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
[68]2000int sh_kern_set_proc_root (const char * c)
[1]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
[68]2022int sh_kern_set_proc_root_iops (const char * c)
[1]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
[68]2044int sh_kern_set_proc_root_lookup (const char * c)
[1]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
[68]2067/* #ifdef SH_USE_KERN */
[1]2068#endif
Note: See TracBrowser for help on using the repository browser.