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

Re: [Xen-devel] [PATCH v3] xen/tools: Introduce QNX IFS loader



On Mon, 2014-09-22 at 21:12 +0300, Oleksandr Tyshchenko wrote:
> This patch was developed according to instruction:
> http://www.qnx.com/developers/docs/6.4.1/neutrino/building/load_process.html
> 
> Add ability to load QNX IFS image. The loader probe function
> based on "Writing an IPL Program" howto from qnx.com
> and performs image validation and startup entry point location.
> Because of the fact that the image is already in place some
> customizations have been done. Also in case of multiple images
> (very seldom case) only the first image will be loaded.
> 
> There are some restrictions:
> 1. The base address of the image (image attribute) and the location
>    of RAM in system must be synchronized with RAM base address in Xen.
> 2. The QNX IFS image must be created as a simple binary image.

It might be nice (eventually, not necessarily now) to add something to
the wiki or the docs/ subtree which describes how to build a suitable
QNX binary.

> Change-Id: Id125d6eae5847698fb5734c7f28451f5b752062f

What is this?

[...]
> +    v_start = rambase + 0x8000;
> +    if ( dom->kernel_size > UINT64_MAX - v_start )
> +    {
> +        xc_dom_printf(dom->xch, "%s: QNX IFS is too big", __FUNCTION__);
> +        return -EINVAL;
> +    }

This check should be in the parse callback.

> +
> +    /*
> +     * Performs a check for a valid OS signature. We assume that nothing
> +     * preceded by startup header because we expect a simple binary image.
> +     */
> +    startup_hdr = (struct startup_header *)dom->kernel_blob;
> +    if ( startup_hdr->signature != STARTUP_HDR_SIGNATURE )
> +    {
> +        xc_dom_printf(dom->xch, "%s: image is not a QNX IFS", __FUNCTION__);
> +        return -EINVAL;
> +    }
> +
> +    /* Performs a final check for a valid image size */
> +    if ( (startup_hdr->stored_size + startup_hdr->preboot_size) != 
> dom->kernel_size )

A suitably large stored_size or preboot_size will potentially overflow
the addition and the result could be arranged to be == kernel_size.

Since stored_size and preboot_size are 32- and 16-bit it is (I think)
sufficient to cast to a 64bit type for the addition. Perhaps one way
which is nice and clear in terms of reviewing for security would be 
        uint64_t total_size;
        
        ...
        
        total_size += startup_hdr->stored_size;
        total_size += startup_hdr->preboot_size;
        if ( total_size != dom->kernel_size )
                ...
                
BTW, you might want to check > dom->kernel_size to allow for smaller
images?

> +    {
> +        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong size", __FUNCTION__);
> +        return -EINVAL;
> +    }
> +
> +    /* Performs a checksums on the startup and the OS image filesystem */
> +    if ( (calc_checksum((uint32_t *)startup_hdr, startup_hdr->startup_size) 
> != 0) ||
> +         (calc_checksum((uint32_t *)startup_hdr + 
> startup_hdr->startup_size/4,
> +          startup_hdr->stored_size - startup_hdr->startup_size) != 0) )

You haven't validated startup_size yet, so you can't trust it to not
overrun the buffer. And you need to be careful with that subtraction,
probably starting with validating that one is larger than the other.

You don't see to use preboot_size for anything, perhaps you meant to
range check startup_size above instead?

> +    {
> +        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong checksum", 
> __FUNCTION__);
> +        return -EINVAL;
> +    }
> +
> +    /* Performs a sanity check for a valid startup entry point */
> +    v_end = v_start + dom->kernel_size;
> +    if ( (startup_hdr->startup_vaddr < v_start) ||
> +         (startup_hdr->startup_vaddr > v_end) )
> +    {
> +        xc_dom_printf(dom->xch, "%s: QNX IFS has wrong startup entry point", 
> __FUNCTION__);
> +        return -EINVAL;
> +    }

I think this check can also move to parse time. (It may not matter but
the other loaders don't rely on rambase_pfn in the probe function and
I'd like to be consistent if possible).

> +
> +    dom->startup_vaddr = startup_hdr->startup_vaddr;

and having move the above I think you can then just assign virt_entry
directly from startup_hdr in the parse function. Since you've validated
the header in the probe function parse can just use it.

> +static int xc_dom_parse_qnx_ifs(struct xc_dom_image *dom)
> +{
> +    uint64_t v_start, v_end;
> +    uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
> +
> +    DOMPRINTF_CALLED(dom->xch);
> +
> +    /* Do not load kernel at the very first RAM address */
> +    v_start = rambase + 0x8000;
> +    v_end = v_start + dom->kernel_size;

[...] put the checks which I called about above here.

> +    /* find kernel segment */
> +    dom->kernel_seg.vstart = v_start;
> +    dom->kernel_seg.vend   = v_end;
> +
> +    dom->parms.virt_entry = dom->startup_vaddr;
> +    dom->parms.virt_base = rambase;
> +
> +    dom->guest_type = "xen-3.0-armv7l";
> +    DOMPRINTF("%s: %s: RAM starts at %"PRI_xen_pfn,
> +              __FUNCTION__, dom->guest_type, dom->rambase_pfn);
> +    DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
> +              __FUNCTION__, dom->guest_type,
> +              dom->kernel_seg.vstart, dom->kernel_seg.vend);
> +
> +    return 0;
> +}

[...]

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.