[PATCH] vfprintf: validate nargs and maybe allocate from heap

Andreas Jaeger aj@suse.com
Fri Mar 2 15:58:00 GMT 2012


On 02/16/2012 05:16 PM, Kees Cook wrote:
> The nargs value can overflow when doing allocations, allowing arbitrary
> memory writes via format strings, bypassing _FORTIFY_SOURCE:
> http://www.phrack.org/issues.html?issue=67&id=9

So a security issue - can we get this fixed quickly, please? I'd like to 
ping for a review and commit!


Kees, thanks for the patch.

 > [...]
> diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
> index 863cd5d..022e72b 100644
> --- a/stdio-common/vfprintf.c
> +++ b/stdio-common/vfprintf.c
 > [...]
> @@ -1698,13 +1702,33 @@ do_positional:
>
>       /* Determine the number of arguments the format string consumes.  */
>       nargs = MAX (nargs, max_ref_arg);
> +    bytes_per_arg = sizeof (*args_value) + sizeof (*args_size)
> +                    + sizeof (*args_type);
> +
> +    /* Check for potential integer overflow.  */
> +    if (nargs>  SIZE_MAX / bytes_per_arg)
> +      {
> +         done = -1;
> +         goto all_done;
> +      }
>
>       /* Allocate memory for the argument descriptions.  */
> -    args_type = alloca (nargs * sizeof (int));
> +    if (__libc_use_alloca (nargs * bytes_per_arg))
> +        args_value = alloca (nargs * bytes_per_arg);
> +    else
> +      {
> +        args_value = args_malloced = malloc (nargs * bytes_per_arg);
> +        if (args_value == NULL)
> +          {
> +            done = -1;
> +            goto all_done;
> +          }
> +      }
> +
> +    args_size =&args_value[nargs].pa_int;
> +    args_type =&args_size[nargs];

don't you have an off-by-one error here? You allocate nargs arguments 
and access [nargs]

>       memset (args_type, s->_flags2&  _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
> -	    nargs * sizeof (int));
> -    args_value = alloca (nargs * sizeof (union printf_arg));
> -    args_size = alloca (nargs * sizeof (int));
> +	    nargs * sizeof (*args_type));
>
>       /* XXX Could do sanity check here: If any element in ARGS_TYPE is
>          still zero after this loop, format is invalid.  For now we
> @@ -1973,8 +1997,8 @@ do_positional:
>     }
>
>   all_done:
> -  if (__builtin_expect (workstart != NULL, 0))
> -    free (workstart);
> +  free (args_malloced);
> +  free (workstart);
>     /* Unlock the stream.  */
>     _IO_funlockfile (s);
>     _IO_cleanup_region_end (0);

Andreas
-- 
  Andreas Jaeger aj@{suse.com,opensuse.org} Twitter/Identica: jaegerandi
   SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
    GF: Jeff Hawn,Jennifer Guild,Felix Imendörffer,HRB16746 (AG Nürnberg)
     GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126



More information about the Libc-alpha mailing list