[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