oath-toolkit-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [OATH-Toolkit-help] pskc_build_xml() use-after-free


From: Simon Josefsson
Subject: Re: [OATH-Toolkit-help] pskc_build_xml() use-after-free
Date: Thu, 14 Aug 2014 13:37:43 +0200
User-agent: Gnus/5.130011 (Ma Gnus v0.11) Emacs/24.3 (gnu/linux)

Thanks for the bug report!

I'm a little uncertain how well the proposed patch works.  What happens
if you call pskc_build_xml() multiple times?  Wouldn't there be many
xmlDoc pointers around?  And consequently potentially stale pointers if
any of them would be free'd?

/Simon

David Woodhouse <address@hidden> writes:

> When we parse a PSKC file with pskc_parse_from_memory() and subsequently
> process the xmlDoc with parse_keycontainer(), we build up a bunch of
> pointers from the container to the 'static' strings within the xmlDoc.
>
> Then we call pskc_build_xml() which builds a *new* xmlDoc and frees the
> old one. Leaving lots and lots of stale pointers to the memory we just
> freed.
>
> https://bugzilla.redhat.com/show_bug.cgi?id=1129491
>
> The best answer is to fix those stale pointers. We could possibly do
> that by calling parse_keycontainer() again in a new 'reparse' mode so
> that it doesn't reallocate things (and so that existing pointers remain
> valid). There's half an attempt at that in
> https://bugzilla.redhat.com/show_bug.cgi?id=1129491#c1
>
> Alternatively, we could set the fields in the data structures *as* we
> build up the new xmlDoc. But that has issues if we get a failure when
> building the new xmlDoc and we'd need to roll back. At least with the
> former option we could be fairly sure that parse_keycontainer() really
> *shouldn't* fail on the xmlDoc that we just created.
>
> The third and by far the simplest approach, although less efficient, is
> just to keep the original xmlDoc around for the entire lifetime of the
> container. That's what this patch does:
>
> diff --git a/libpskc/build.c b/libpskc/build.c
> index 8f0840f..c3e84ad 100644
> --- a/libpskc/build.c
> +++ b/libpskc/build.c
> @@ -510,7 +510,7 @@ pskc_build_xml (pskc_t * container, char **out, size_t * 
> len)
>  
>    xmlDocSetRootElement (doc, keycont);
>  
> -  if (container->xmldoc)
> +  if (container->xmldoc && container->xmldoc != container->original_xmldoc)
>      xmlFreeDoc (container->xmldoc);
>    container->xmldoc = doc;
>    doc = NULL;
> diff --git a/libpskc/internal.h b/libpskc/internal.h
> index 674625d..9b36e28 100644
> --- a/libpskc/internal.h
> +++ b/libpskc/internal.h
> @@ -103,7 +103,7 @@ struct pskc_key
>  struct pskc
>  {
>    /* raw XML */
> -  xmlDocPtr xmldoc;
> +  xmlDocPtr xmldoc, original_xmldoc;
>    /* Is there a Signature element in xmldoc? */
>    int signed_p;
>  
> diff --git a/libpskc/parser.c b/libpskc/parser.c
> index 47f8bd6..d75e5ac 100644
> --- a/libpskc/parser.c
> +++ b/libpskc/parser.c
> @@ -677,6 +677,8 @@ pskc_done (pskc_t * container)
>      return;
>  
>    xmlFreeDoc (container->xmldoc);
> +  if (container->original_xmldoc != container->xmldoc)
> +       xmlFreeDoc (container->original_xmldoc);
>  
>    for (i = 0; i < container->nkeypackages; i++)
>      {
> @@ -717,7 +719,7 @@ pskc_parse_from_memory (pskc_t * container, size_t len, 
> const char *buffer)
>    if (xmldoc == NULL)
>      return PSKC_XML_ERROR;
>  
> -  container->xmldoc = xmldoc;
> +  container->original_xmldoc = container->xmldoc = xmldoc;
>  
>    root = xmlDocGetRootElement (xmldoc);
>    parse_keycontainer (container, root, &rc);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]