[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