[Libguestfs] [PATCH v2 4/6] New API: internal_yara_scan

Pino Toscano ptoscano at redhat.com
Tue Nov 22 09:04:04 UTC 2016


On Wednesday, 9 November 2016 22:38:55 CET Matteo Cafasso wrote:
> The internal_yara_scan runs the Yara engine with the previously loaded
> rules against the given file.
> 
> For each rule matching against the scanned file, a struct containing
> the file name and the rule identifier is returned.
> 
> The gathered list of yara_detection structs is serialised into XDR format
> and written to a file.
> 
> Signed-off-by: Matteo Cafasso <noxdafox at gmail.com>
> ---
>  daemon/yara.c                            | 87 ++++++++++++++++++++++++++++++++
>  generator/actions.ml                     | 10 ++++
>  generator/structs.ml                     |  9 ++++
>  gobject/Makefile.inc                     |  2 +
>  java/Makefile.inc                        |  1 +
>  java/com/redhat/et/libguestfs/.gitignore |  1 +
>  src/MAX_PROC_NR                          |  2 +-
>  7 files changed, 111 insertions(+), 1 deletion(-)
> 
> diff --git a/daemon/yara.c b/daemon/yara.c
> index fe1f69a..8e7d328 100644
> --- a/daemon/yara.c
> +++ b/daemon/yara.c
> @@ -52,6 +52,8 @@ static int upload_rules_file (char *);
>  static int compile_rules_file (const char *);
>  static int write_callback (void *, const void *, size_t);
>  static void compile_error_callback (int, const char *, int, const char *, void *);
> +static int yara_rules_callback (int , void *, void *);
> +static int send_detection_info (const char *, YR_RULE *);
>  
>  /* Has one FileIn parameter. */
>  int
> @@ -107,6 +109,39 @@ do_yara_destroy (void)
>    return 0;
>  }
>  
> +/* Has one FileOut parameter. */
> +int
> +do_internal_yara_scan (const char *path)
> +{
> +  int ret = 0;
> +  CLEANUP_CLOSE int fd = 0;

This must be initialized as -1, otherwise the CLEANUP_CLOSE handler
will close the fd 0, which is stdin of the daemon.

> +
> +  if (rules == NULL) {
> +    reply_with_error ("no yara rules loaded");
> +    return -1;
> +  }
> +
> +  CHROOT_IN;
> +  fd = open (path, O_RDONLY|O_CLOEXEC);
> +  CHROOT_OUT;
> +
> +  if (fd < 0) {
> +    reply_with_perror ("%s", path);
> +    yr_finalize ();

I don't think that's the right place for yr_finalize.

> +    return -1;
> +  }
> +
> +  reply (NULL, NULL);  /* Reply message. */
> +
> +  ret = yr_rules_scan_fd (rules, fd, 0, yara_rules_callback, (void *) path, 0);
> +  if (ret == ERROR_SUCCESS)
> +    ret = send_file_end (0);  /* File transfer end. */
> +  else
> +    send_file_end (1);  /* Cancel file transfer. */
> +
> +  return 0;
> +}
> +
>  /* Upload rules file on a temporary file.
>   * Return 0 on success, -1 on error.
>   */
> @@ -209,6 +244,58 @@ compile_error_callback(int level, const char *name, int line,
>      fprintf (stderr, "(%d): Yara warning: %s\n", line, message);
>  }
>  
> +/* Yara scan callback, called by yr_rules_scan_file.
> + * Return 0 on success, -1 on error.
> + */
> +static int
> +yara_rules_callback (int code, void *message, void *data)
> +{
> +  int ret = 0;
> +
> +  if (code == CALLBACK_MSG_RULE_MATCHING)
> +    ret = send_detection_info ((const char *)data, (YR_RULE *) message);
> +
> +  return (ret == 0) ? CALLBACK_CONTINUE : CALLBACK_ERROR;
> +}
> +
> +/* Serialize file path and rule name and send it out.
> + * Return 0 on success, -1 on error.
> + */
> +static int
> +send_detection_info (const char *name, YR_RULE *rule)
> +{
> +  XDR xdr;
> +  int ret = 0;
> +  size_t len = 0;
> +  struct guestfs_int_yara_detection detection;
> +  CLEANUP_FREE char *buf = NULL, *fname = NULL;

fname is not used here -- I suggest passing --enable-werror to
autogen.sh or configure, so any compiler warning is turned to error.

> +
> +  detection.name = (char *) name;
> +  detection.rule = (char *) rule->identifier;
> +
> +  /* Serialize detection struct. */
> +  buf = malloc (GUESTFS_MAX_CHUNK_SIZE);
> +  if (buf == NULL) {
> +    perror ("malloc");
> +    return -1;
> +  }
> +
> +  xdrmem_create (&xdr, buf, GUESTFS_MAX_CHUNK_SIZE, XDR_ENCODE);
> +
> +  ret = xdr_guestfs_int_yara_detection (&xdr, &detection);
> +  if (ret == 0) {
> +    perror ("xdr_guestfs_int_yara_detection");
> +    return -1;
> +  }
> +
> +  len = xdr_getpos (&xdr);
> +
> +  xdr_destroy (&xdr);
> +
> +  /* Send serialised tsk_detection out. */

Typo in comment.

> +  return send_file_write (buf, len);
> +}
> +
>  /* Clean up yara handle on daemon exit. */
>  void yara_finalize (void) __attribute__((destructor));
>  void
> diff --git a/generator/actions.ml b/generator/actions.ml
> index 152c651..d9006f2 100644
> --- a/generator/actions.ml
> +++ b/generator/actions.ml
> @@ -13280,6 +13280,16 @@ Previously loaded rules will be destroyed." };
>      shortdesc = "destroy previously loaded yara rules";
>      longdesc = "\
>  Destroy previously loaded Yara rules in order to free libguestfs resources." };
> +
> +  { defaults with
> +    name = "internal_yara_scan"; added = (1, 35, 15);
> +    style = RErr, [Pathname "path"; FileOut "filename";], [];
> +    proc_nr = Some 473;
> +    visibility = VInternal;
> +    optional = Some "libyara";
> +    shortdesc = "scan a file with the loaded yara rules";
> +    longdesc = "Internal function for yara_scan." };
> +
>  ]
>  
>  (* Non-API meta-commands available only in guestfish.
> diff --git a/generator/structs.ml b/generator/structs.ml
> index 029bc3a..3fa2ebc 100644
> --- a/generator/structs.ml
> +++ b/generator/structs.ml
> @@ -468,6 +468,15 @@ let structs = [
>      ];
>      s_camel_name = "TSKDirent" };
>  
> +  (* Yara detection information. *)
> +  { defaults with
> +    s_name = "yara_detection";
> +    s_cols = [
> +    "name", FString;
> +    "rule", FString;

yara_load supports loading rules already compiled, which could have a
namespace set -- I guess it should be reported here as well.

That triggers another question: should the yara support allow to load
more rules one after each other (with namespaces as well), instead of
just one?

Thanks,
-- 
Pino Toscano
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20161122/06d9749e/attachment.sig>


More information about the Libguestfs mailing list