From d3eac090ac6f1035f603dc6d73e939469f397d61 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Jun 08 2009 16:17:09 +0000 Subject: - Make aide smarter about prelinked files (Peter Vrabec) - Add /lib64 to default config --- diff --git a/aide-0.13.1-prelink2.patch b/aide-0.13.1-prelink2.patch new file mode 100644 index 0000000..fd2a3f6 --- /dev/null +++ b/aide-0.13.1-prelink2.patch @@ -0,0 +1,286 @@ +diff -up aide-0.13.1/configure.in.prelink aide-0.13.1/configure.in +--- aide-0.13.1/configure.in.prelink 2006-12-08 22:49:21.000000000 +0100 ++++ aide-0.13.1/configure.in 2009-05-13 16:14:49.000000000 +0200 +@@ -405,6 +405,30 @@ AS_IF([test "x$with_selinux_support" != + + AC_SUBST(SELINUXLIB) + ++ ++AC_MSG_CHECKING(for prelink-support) ++AC_ARG_WITH([prelink], ++ [AC_HELP_STRING([--with-prelink],[use prelink (no checking)])], ++ [case $with_prelink in ++ yes) AC_DEFINE_UNQUOTED(PRELINK_PATH, "/usr/sbin/prelink", [path to prelink]) ++ AC_DEFINE(WITH_PRELINK,1,[use prelink]) ++ ELFLIB="-lelf" ++ compoptionstring="${compoptionstring}WITH_PRELINK\\n" ++ AC_MSG_RESULT([/usr/sbin/prelink]) ++ ;; ++ no) AC_MSG_RESULT(no) ++ ;; ++ *) AC_DEFINE_UNQUOTED(PRELINK_PATH, "$with_prelink", [path to prelink]) ++ AC_DEFINE(WITH_PRELINK,1,[use prelink]) ++ ELFLIB="-lelf" ++ compoptionstring="${compoptionstring}WITH_PRELINK\\n" ++ AC_MSG_RESULT([$with_prelink]) ++ ;; ++ esac], ++ [with_prelink=no] ++) ++AC_SUBST(ELFLIB) ++ + AC_MSG_CHECKING(for xattr-support) + AC_ARG_WITH([xattr], + [AC_HELP_STRING([--with-xattr], +diff -up aide-0.13.1/src/do_md.c.prelink aide-0.13.1/src/do_md.c +--- aide-0.13.1/src/do_md.c.prelink 2006-10-27 22:47:20.000000000 +0200 ++++ aide-0.13.1/src/do_md.c 2009-05-13 17:37:51.000000000 +0200 +@@ -65,6 +65,86 @@ + /* + #include + */ ++ ++#ifdef WITH_PRELINK ++#include ++#include ++ ++/* ++ * Is file descriptor prelinked binary/library? ++ * Return: 1(yes) / 0(no) ++ * ++ */ ++int is_prelinked(int fd) { ++ Elf *elf = NULL; ++ Elf_Scn *scn = NULL; ++ Elf_Data *data = NULL; ++ GElf_Ehdr ehdr; ++ GElf_Shdr shdr; ++ GElf_Dyn dyn; ++ int bingo; ++ ++ (void) elf_version(EV_CURRENT); ++ ++ if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL ++ || elf_kind(elf) != ELF_K_ELF ++ || gelf_getehdr(elf, &ehdr) == NULL ++ || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC)) ++ return 0; ++ ++ bingo = 0; ++ while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) { ++ (void) gelf_getshdr(scn, &shdr); ++ ++ if (shdr.sh_type != SHT_DYNAMIC) ++ continue; ++ ++ while (!bingo && (data = elf_getdata (scn, data)) != NULL) { ++ int maxndx = data->d_size / shdr.sh_entsize; ++ int ndx; ++ ++ for (ndx = 0; ndx < maxndx; ++ndx) { ++ (void) gelf_getdyn (data, ndx, &dyn); ++ if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST)) ++ continue; ++ bingo = 1; ++ break; ++ } ++ } ++ } ++ ++ return bingo; ++} ++ ++/* ++ * Open path via prelink -y, set fd ++ * Return: 0(not success) / !0(prelink child process) ++ * ++ */ ++pid_t open_prelinked(const char * path, int * fd) { ++ const char *cmd = PRELINK_PATH; ++ pid_t pid = 0; ++ int pipes[2]; ++ ++ pipes[0] = pipes[1] = -1; ++ pipe(pipes); ++ if (!(pid = fork())) { ++ /* child */ ++ close(pipes[0]); ++ dup2(pipes[1], STDOUT_FILENO); ++ close(pipes[1]); ++ unsetenv("MALLOC_CHECK_"); ++ execl(cmd, cmd, "--verify", path, (char *) NULL); ++ } ++ /* parent */ ++ close(pipes[1]); ++ *fd = pipes[0]; ++ return pid; ++ ++} ++ ++#endif ++ + void md_init_fail(const char* s,db_line* db,byte** hash,DB_ATTR_TYPE i) { + error(0,"Message digest %s initialise failed\nDisabling %s for file %s\n",s,s,db->filename); + db->attr=db->attr&(~i); +@@ -121,6 +201,9 @@ void calc_md(struct AIDE_STAT_TYPE* old_ + struct AIDE_STAT_TYPE fs; + int sres=0; + int stat_diff,filedes; ++#ifdef WITH_PRELINK ++ pid_t pid; ++#endif + + error(255,"calc_md called\n"); + #ifdef _PARAMETER_CHECK_ +@@ -166,6 +249,22 @@ void calc_md(struct AIDE_STAT_TYPE* old_ + /* + Now we have a 'valid' filehandle to read from a file. + */ ++ ++#ifdef WITH_PRELINK ++ /* ++ * Let's take care of prelinked libraries/binaries ++ */ ++ pid=0; ++ if ( is_prelinked(filedes) ) { ++ close(filedes); ++ pid = open_prelinked(line->filename, &filedes); ++ if (pid == 0) { ++ error(0, "Error on starting prelink undo\n"); ++ return; ++ } ++ } ++#endif ++ + off_t r_size=0; + off_t size=0; + char* buf; +@@ -176,47 +275,58 @@ void calc_md(struct AIDE_STAT_TYPE* old_ + + if (init_md(&mdc)==RETOK) { + #ifdef HAVE_MMAP +- off_t curpos=0; ++#ifdef WITH_PRELINK ++ if (pid == 0) { ++#endif ++ off_t curpos=0; + +- r_size=fs.st_size; +- /* in mmap branch r_size is used as size remaining */ +- while(r_size>0){ +- if(r_size0){ ++ if(r_sizefilename,strerror(errno)); +- close(filedes); +- close_md(&mdc); +- return; +- } +- conf->catch_mmap=1; +- if (update_md(&mdc,buf,size)!=RETOK) { +- error(0,"Message digest failed during update\n"); +- close_md(&mdc); +- munmap(buf,size); +- return; +- } +- munmap(buf,size); +- conf->catch_mmap=0; ++ curpos+=MMAP_BLOCK_SIZE; ++ size=MMAP_BLOCK_SIZE; ++ r_size-=MMAP_BLOCK_SIZE; ++ } ++ if ( buf == MAP_FAILED ) { ++ error(0,"error mmap'ing %s: %s\n", line->filename,strerror(errno)); ++ close(filedes); ++ close_md(&mdc); ++ return; ++ } ++ conf->catch_mmap=1; ++ if (update_md(&mdc,buf,size)!=RETOK) { ++ error(0,"Message digest failed during update\n"); ++ close_md(&mdc); ++ munmap(buf,size); ++ return; ++ } ++ munmap(buf,size); ++ conf->catch_mmap=0; ++ } ++ /* we have used MMAP, let's return */ ++ close_md(&mdc); ++ md2line(&mdc,line); ++ close(filedes); ++ return; ++#ifdef WITH_PRELINK + } +-#else /* not HAVE_MMAP */ ++#endif ++#endif /* not HAVE_MMAP */ + buf=malloc(READ_BLOCK_SIZE); + #if READ_BLOCK_SIZE>SSIZE_MAX + #error "READ_BLOCK_SIZE" is too large. Max value is SSIZE_MAX, and current is READ_BLOCK_SIZE +@@ -229,11 +339,22 @@ void calc_md(struct AIDE_STAT_TYPE* old_ + } + r_size+=size; + } ++ ++#ifdef WITH_PRELINK ++ if (pid) { ++ int status; ++ (void) waitpid(pid, &status, 0); ++ if (!WIFEXITED(status) || WEXITSTATUS(status)) { ++ error(0, "Error on exit of prelink child process\n"); ++ close_md(&mdc); ++ return; ++ } ++ } ++#endif + free(buf); +-#endif /* HAVE_MMAP else branch */ + close_md(&mdc); + md2line(&mdc,line); +- ++ + } else { + error(3,"Message digest initialization failed.\n"); + no_hash(line); +diff -up aide-0.13.1/src/Makefile.am.prelink aide-0.13.1/src/Makefile.am +--- aide-0.13.1/src/Makefile.am.prelink 2006-10-27 23:10:38.000000000 +0200 ++++ aide-0.13.1/src/Makefile.am 2009-05-13 16:14:49.000000000 +0200 +@@ -50,7 +50,7 @@ aide_SOURCES = \ + + INCLUDES = -I$(top_srcdir)/include + +-LDADD = -lm @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ ++LDADD = -lm @CRYPTLIB@ @ACLLIB@ @SELINUXLIB@ @AUDITLIB@ @ATTRLIB@ @ELFLIB@ + + AM_LDFLAGS = @LDFLAGS@ @LD_STATIC_FLAG@ + diff --git a/aide.conf b/aide.conf index bc1af8e..3aa83b3 100644 --- a/aide.conf +++ b/aide.conf @@ -89,6 +89,7 @@ DATAONLY = p+n+u+g+s+acl+selinux+xattrs+md5+sha256+rmd160+tiger /bin NORMAL /sbin NORMAL /lib NORMAL +/lib64 NORMAL /opt NORMAL /usr NORMAL /root NORMAL diff --git a/aide.spec b/aide.spec index da58d86..8413359 100644 --- a/aide.spec +++ b/aide.spec @@ -20,7 +20,7 @@ Patch3: aide-0.13.1-manuals.patch Patch4: aide-0.13.1-prelink2.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot-%(%{__id_u} -n) BuildRequires: mktemp -BuildRequires: prelink autoconf +BuildRequires: prelink autoconf automake Buildrequires: mhash-devel Buildrequires: zlib-devel libgcrypt-devel Buildrequires: flex bison