|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 22/22] libxc: check blob size before proceeding in xc_dom_check_gzip
Andrew Cooper writes ("Re: [PATCH 22/22] libxc: check blob size before
proceeding in xc_dom_check_gzip"):
> On 07/06/13 19:27, Ian Jackson wrote:
> > + if ( ziplen < 6 )
> > + /* too small */
> > + return 0;
> > +
> > if ( strncmp(blob, "\037\213", 2) )
> > /* not gzipped */
> > return 0;
>
> The above change is certainly good and correct.
>
> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Thanks. I'll leave off your Reviewed-by in my copy of the series
until we've resolved these comments.
> I do however have concerns about the rest of the function, immediately
> after the context. I spot any other specific security related issues,
> but would appreciate comments/thoughts as to whether these should be
> part of this patch or part of a subsequent set of bugfix patches.
I think it would be best to do all needed fixes to xc_dom_check_gzip
(and perhaps related functions) in one patch, if they're not intricate.
> > gzlen = blob + ziplen - 4;
>
> Arithmatic on a void pointer (blob), and a possibility to overflow,
> although this seems unlikely given that it would have to pass
> xc_dom_malloc_filemap() in the first place. There is a GNU extention
> which allows this line to Do The Right Thing, despite violating the C spec.
This code already relies on the GNU extension to do arithmetic on a
void pointer. This is defined to do the same thing as arithmetic on a
char*, and is safe under the same conditions as the char* arithmetic.
In this case (it's left associative) this expression computes
(blob + ziplen) - 4
Now, blob + ziplen is safe because that's the input image size. Ie,
it's a pointer to the end of the image, which one is permitted to
compute.
Since ziplen >= 6 (because of the earlier test) it is then safe to
retreat by 4 bytes.
> > unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0];
> > if ( (unziplen < 0) || (unziplen > XC_DOM_DECOMPRESS_MAX) )
>
> unziplen is unsigned, so (unziplen < 0) is necessarily false.
Yes, but I don't intend to change this, obviously.
> > {
> > xc_dom_printf
> > (xch,
> > "%s: size (zip %zd, unzip %zd) looks insane, skip gunzip",
> > __FUNCTION__, ziplen, unziplen);
>
> ziplen and unziplen are both unsigned, so the format string should be
> %zu instead.
xc_dom_printf uses stdarg to get the arguments. Given %zd it will use
va_arg(,int). The requirement for va_arg is that the actual promoted
argument type and the specified type are "compatible" (C99 7.15.1.1
para 2). `int' and `unsigned' are indeed not compatible. So this has
undefined behaviour.
However I do not propose to try to audit our entire codebase for calls
to print a signed integer with %x (which has, technically, undefined
behaviour if the value is negative). Instead, I propose that we
declare that we require of the C implementation that it tolerate use
of va_arg where the actual and supplied types are not compatible but
do pass the strict aliasing rules.
As a justification for this I observe that gcc's format string warning
system tolerates passing wrong-signedness arguments to printf %d etc.
> While XC_DOM_DECOMPRESS_MAX is set to a default of 1GB, if it is
> changes, unziplen + 16 can overflow.
This should be dealt with by a comment near its definition. TBH IMO
if anyone defines it to >= nearly 4G they deserve to lose.
Ian.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |