[Libguestfs] [PATCH v4 3/7] New API: yara_load

Richard W.M. Jones rjones at redhat.com
Tue Apr 4 12:53:53 UTC 2017


On Sun, Mar 12, 2017 at 11:13:32PM +0200, Matteo Cafasso wrote:
> The yara_load API allows to load a set of Yara rules contained within a
> file on the host.
> 
> Rules can be in binary format, as when compiled with yarac command, or
> in source code format. In the latter case, the rules will be first
> compiled and then loaded.
> 
> Subsequent calls of the yara_load API will result in the discard of the
> previously loaded rules.
> 
> Signed-off-by: Matteo Cafasso <noxdafox at gmail.com>
> ---
>  daemon/Makefile.am    |   1 +
>  daemon/cleanups.c     |   9 +++
>  daemon/cleanups.h     |   2 +
>  daemon/yara.c         | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  generator/Makefile.am |   3 +
>  generator/actions.ml  |   3 +-
>  generator/proc_nr.ml  |   1 +
>  gobject/Makefile.inc  |   6 +-
>  lib/MAX_PROC_NR       |   2 +-

I think this patch is missing the actions_yara.ml and .mli files ...?

Rich.

>  9 files changed, 224 insertions(+), 4 deletions(-)
>  create mode 100644 daemon/yara.c
> 
> diff --git a/daemon/Makefile.am b/daemon/Makefile.am
> index 9d73bb805..563622cdb 100644
> --- a/daemon/Makefile.am
> +++ b/daemon/Makefile.am
> @@ -164,6 +164,7 @@ guestfsd_SOURCES = \
>  	wc.c \
>  	xattr.c \
>  	xfs.c \
> +	yara.c \
>  	zero.c \
>  	zerofree.c
> 
> diff --git a/daemon/cleanups.c b/daemon/cleanups.c
> index 092e493d7..3102cf94b 100644
> --- a/daemon/cleanups.c
> +++ b/daemon/cleanups.c
> @@ -62,6 +62,15 @@ cleanup_close (void *ptr)
>  }
> 
>  void
> +cleanup_fclose (void *ptr)
> +{
> +  FILE *f = * (FILE **) ptr;
> +
> +  if (f)
> +    fclose (f);
> +}
> +
> +void
>  cleanup_aug_close (void *ptr)
>  {
>    augeas *aug = * (augeas **) ptr;
> diff --git a/daemon/cleanups.h b/daemon/cleanups.h
> index 6746e2744..a791244cb 100644
> --- a/daemon/cleanups.h
> +++ b/daemon/cleanups.h
> @@ -26,6 +26,7 @@ extern void cleanup_free (void *ptr);
>  extern void cleanup_free_string_list (void *ptr);
>  extern void cleanup_unlink_free (void *ptr);
>  extern void cleanup_close (void *ptr);
> +extern void cleanup_fclose (void *ptr);
>  extern void cleanup_aug_close (void *ptr);
>  extern void cleanup_free_stringsbuf (void *ptr);
> 
> @@ -35,6 +36,7 @@ extern void cleanup_free_stringsbuf (void *ptr);
>      __attribute__((cleanup(cleanup_free_string_list)))
>  #define CLEANUP_UNLINK_FREE __attribute__((cleanup(cleanup_unlink_free)))
>  #define CLEANUP_CLOSE __attribute__((cleanup(cleanup_close)))
> +#define CLEANUP_FCLOSE __attribute__((cleanup(cleanup_fclose)))
>  #define CLEANUP_AUG_CLOSE __attribute__((cleanup(cleanup_aug_close)))
>  #define CLEANUP_FREE_STRINGSBUF __attribute__((cleanup(cleanup_free_stringsbuf)))
>  #else
> diff --git a/daemon/yara.c b/daemon/yara.c
> new file mode 100644
> index 000000000..0e4128aed
> --- /dev/null
> +++ b/daemon/yara.c
> @@ -0,0 +1,201 @@
> +/* libguestfs - the guestfsd daemon
> + * Copyright (C) 2016 Red Hat Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#include <config.h>
> +
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdbool.h>
> +#include <rpc/xdr.h>
> +#include <rpc/types.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +
> +#include "daemon.h"
> +#include "actions.h"
> +#include "optgroups.h"
> +#include "guestfs_protocol.h"
> +
> +#ifdef HAVE_YARA
> +
> +#include <yara.h>
> +
> +#define CLEANUP_DESTROY_YARA_COMPILER                           \
> +  __attribute__((cleanup(cleanup_destroy_yara_compiler)))
> +
> +struct write_callback_data {
> +  int fd;
> +  uint64_t written;
> +};
> +
> +/* Yara compiled rules. */
> +static YR_RULES *rules = NULL;
> +static bool initialized = false;
> +
> +static int compile_rules_file (const char *, const char *);
> +static void compile_error_callback (int, const char *, int, const char *, void *);
> +static void cleanup_destroy_yara_compiler (void *ptr);
> +
> +/* Has one FileIn parameter.
> + * Takes optional arguments, consult optargs_bitmask.
> + */
> +int
> +do_yara_load (const char *namespace)
> +{
> +  int ret = 0;
> +  CLEANUP_CLOSE int fd = -1;
> +  char tmpfile[] = "/tmp/yaraXXXXXX";
> +
> +  fd = mkstemp (tmpfile);
> +  if (fd == -1) {
> +    reply_with_perror ("mkstemp");
> +    return -1;
> +  }
> +
> +  ret = upload_to_fd (fd);
> +  if (ret < 0) {
> +    unlink (tmpfile);
> +    return -1;
> +  }
> +
> +  /* Initialize yara only once. */
> +  if (!initialized) {
> +    ret = yr_initialize ();
> +    if (ret != ERROR_SUCCESS) {
> +      reply_with_error ("failed initializing yara");
> +      unlink (tmpfile);
> +      return -1;
> +    }
> +
> +    initialized = true;
> +  }
> +
> +  /* Clear namespace if no optional parameter is given. */
> +  if (!(optargs_bitmask & GUESTFS_YARA_LOAD_NAMESPACE_BITMASK))
> +    namespace = NULL;
> +
> +  /* Try to load the rules as compiled.
> +   * If their are in source code format, compile them first.
> +   */
> +  ret = yr_rules_load (tmpfile, &rules);
> +  if (ret == ERROR_INVALID_FILE)
> +    ret = compile_rules_file (tmpfile, namespace);
> +
> +  unlink (tmpfile);
> +
> +  return (ret == ERROR_SUCCESS) ? 0 : -1;
> +}
> +
> +/* Compile source code rules and load them.
> + * Return ERROR_SUCCESS on success, Yara error code type on error.
> + */
> +static int
> +compile_rules_file (const char *rules_path, const char *namespace)
> +{
> +  int ret = 0;
> +  CLEANUP_FCLOSE FILE *rule_file = NULL;
> +  CLEANUP_DESTROY_YARA_COMPILER YR_COMPILER *compiler = NULL;
> +
> +  ret = yr_compiler_create (&compiler);
> +  if (ret != ERROR_SUCCESS) {
> +    reply_with_error ("yr_compiler_create");
> +    return ret;
> +  }
> +
> +  yr_compiler_set_callback (compiler, compile_error_callback, NULL);
> +
> +  rule_file = fopen (rules_path, "r");
> +  if (rule_file == NULL) {
> +    reply_with_error ("unable to open rules file");
> +    return ret;
> +  }
> +
> +  ret = yr_compiler_add_file (compiler, rule_file, namespace, NULL);
> +  if (ret > 0)
> +    return ret;
> +
> +  ret = yr_compiler_get_rules (compiler, &rules);
> +  if (ret == ERROR_INSUFICIENT_MEMORY) {
> +    errno = ENOMEM;
> +    reply_with_perror ("yr_compiler_get_rules");
> +  }
> +
> +  return ret;
> +}
> +
> +/* Yara compilation error callback.
> + * Reports back the compilation error message.
> + * Prints compilation warnings if verbose.
> + */
> +static void
> +compile_error_callback(int level, const char *name, int line,
> +                       const char *message, void *data)
> +{
> +  if (level == YARA_ERROR_LEVEL_ERROR)
> +    reply_with_error ("Yara error (line %d): %s", line, message);
> +  else if (verbose)
> +    fprintf (stderr, "Yara warning (line %d): %s\n", line, message);
> +}
> +
> +/* Clean up yara handle on daemon exit. */
> +void yara_finalize (void) __attribute__((destructor));
> +
> +void
> +yara_finalize (void)
> +{
> +  int ret = 0;
> +
> +  if (!initialized)
> +    return;
> +
> +  if (rules != NULL) {
> +    yr_rules_destroy (rules);
> +    rules = NULL;
> +  }
> +
> +  ret = yr_finalize ();
> +  if (ret != ERROR_SUCCESS)
> +    perror ("yr_finalize");
> +
> +  initialized = false;
> +}
> +
> +static void
> +cleanup_destroy_yara_compiler (void *ptr)
> +{
> +  YR_COMPILER *compiler = * (YR_COMPILER **) ptr;
> +
> +  if (compiler != NULL)
> +    yr_compiler_destroy (compiler);
> +}
> +
> +int
> +optgroup_libyara_available (void)
> +{
> +  return 1;
> +}
> +
> +#else   /* !HAVE_YARA */
> +
> +OPTGROUP_YARA_NOT_AVAILABLE
> +
> +#endif  /* !HAVE_YARA */
> diff --git a/generator/Makefile.am b/generator/Makefile.am
> index cb69fe831..0f7fc289b 100644
> --- a/generator/Makefile.am
> +++ b/generator/Makefile.am
> @@ -43,6 +43,8 @@ sources = \
>  	actions_properties_deprecated.mli \
>  	actions_tsk.ml \
>  	actions_tsk.mli \
> +	actions_yara.ml \
> +	actions_yara.mli \
>  	bindtests.ml \
>  	bindtests.mli \
>  	c.ml \
> @@ -130,6 +132,7 @@ objects = \
>  	actions_properties.cmo \
>  	actions_properties_deprecated.cmo \
>  	actions_tsk.cmo \
> +	actions_yara.cmo \
>  	actions.cmo \
>  	structs.cmo \
>  	fish_commands.cmo \
> diff --git a/generator/actions.ml b/generator/actions.ml
> index fa0e6568a..4df3b2a32 100644
> --- a/generator/actions.ml
> +++ b/generator/actions.ml
> @@ -50,7 +50,8 @@ let daemon_functions =
>    Actions_core_deprecated.daemon_functions @
>    Actions_debug.daemon_functions @
>    Actions_hivex.daemon_functions @
> -  Actions_tsk.daemon_functions
> +  Actions_tsk.daemon_functions @
> +  Actions_yara.daemon_functions
> 
>  (* Some post-processing of the basic lists of actions. *)
> 
> diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml
> index b3be31996..d50cc9efa 100644
> --- a/generator/proc_nr.ml
> +++ b/generator/proc_nr.ml
> @@ -479,6 +479,7 @@ let proc_nr = [
>  469, "aug_transform";
>  470, "internal_find_inode";
>  471, "mksquashfs";
> +472, "yara_load";
>  ]
> 
>  (* End of list.  If adding a new entry, add it at the end of the list
> diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
> index 8fa8599d3..b0ebf15d9 100644
> --- a/gobject/Makefile.inc
> +++ b/gobject/Makefile.inc
> @@ -111,7 +111,8 @@ guestfs_gobject_headers= \
>    include/guestfs-gobject/optargs-umount_local.h \
>    include/guestfs-gobject/optargs-xfs_admin.h \
>    include/guestfs-gobject/optargs-xfs_growfs.h \
> -  include/guestfs-gobject/optargs-xfs_repair.h
> +  include/guestfs-gobject/optargs-xfs_repair.h \
> +  include/guestfs-gobject/optargs-yara_load.h
> 
>  guestfs_gobject_sources= \
>    src/session.c \
> @@ -203,4 +204,5 @@ guestfs_gobject_sources= \
>    src/optargs-umount_local.c \
>    src/optargs-xfs_admin.c \
>    src/optargs-xfs_growfs.c \
> -  src/optargs-xfs_repair.c
> +  src/optargs-xfs_repair.c \
> +  src/optargs-yara_load.c
> diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR
> index c305aa5ae..68cfb10d1 100644
> --- a/lib/MAX_PROC_NR
> +++ b/lib/MAX_PROC_NR
> @@ -1 +1 @@
> -471
> +472
> --
> 2.11.0

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine.  Supports Linux and Windows.
http://people.redhat.com/~rjones/virt-df/




More information about the Libguestfs mailing list