Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d091007 in mainline


Ignore:
Timestamp:
2021-06-04T16:58:15Z (6 months ago)
Author:
Martin Decky <martin@…>
Branches:
master
Children:
3c8c580
Parents:
da15002
Message:

Detect a compressed component by GZIP signature, not file extension

Location:
boot/generic
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • boot/generic/include/gzip.h

    rda15002 rd091007  
    3030#define LIBCOMPRESS_GZIP_H_
    3131
     32#include <stdbool.h>
    3233#include <stddef.h>
    33 size_t gzip_size(const void *, size_t);
     34
     35extern bool gzip_check(const void *, size_t);
     36extern size_t gzip_size(const void *, size_t);
    3437extern int gzip_expand(const void *, size_t, void *, size_t);
    3538
  • boot/generic/src/gzip.c

    rda15002 rd091007  
    6363} __attribute__((packed)) gzip_footer_t;
    6464
    65 size_t gzip_size(const void *src, size_t srclen)
     65/** Check GZIP signature
     66 *
     67 * Checks whether the source buffer start with a GZIP signature.
     68 *
     69 * @param[in] src    Source data buffer.
     70 * @param[in] srclen Source buffer size (bytes).
     71 *
     72 * @return True if GZIP signature found.
     73 * @return False if no GZIP signature found.
     74 *
     75 */
     76bool gzip_check(const void *src, size_t srclen)
    6677{
     78        if ((srclen < (sizeof(gzip_header_t) + sizeof(gzip_footer_t))))
     79                return false;
     80
    6781        gzip_header_t header;
    68         gzip_footer_t footer;
    69 
    70         if ((srclen < sizeof(header)) || (srclen < sizeof(footer)))
    71                 return 0;
    72 
    7382        memcpy(&header, src, sizeof(header));
    74         memcpy(&footer, src + srclen - sizeof(footer), sizeof(footer));
    7583
    7684        if ((header.id1 != GZIP_ID1) ||
     
    7886            (header.method != GZIP_METHOD_DEFLATE) ||
    7987            ((header.flags & (~GZIP_FLAGS_MASK)) != 0))
     88                return false;
     89
     90        return true;
     91}
     92
     93/** Get uncompressed size
     94 *
     95 * Note that the uncompressed size is read from the GZIP footer
     96 * (and not calculated by acutally decompressing the GZip archive).
     97 * Thus the source of the GZip archive needs to be trusted.
     98 *
     99 * @param[in]  src    Source data buffer.
     100 * @param[out] srclen Source buffer size (bytes).
     101 *
     102 * @return Uncompressed size.
     103 *
     104 */
     105size_t gzip_size(const void *src, size_t srclen)
     106{
     107        if (!gzip_check(src, srclen))
    80108                return 0;
     109
     110        gzip_footer_t footer;
     111        memcpy(&footer, src + srclen - sizeof(footer), sizeof(footer));
    81112
    82113        return uint32_t_le2host(footer.size);
     
    85116/** Expand GZIP compressed data
    86117 *
    87  * The routine allocates the output buffer based
    88  * on the size encoded in the input stream. This
     118 * The routine compares the output buffer size with
     119 * the size encoded in the input stream. This
    89120 * effectively limits the size of the uncompressed
    90121 * data to 4 GiB (expanding input streams that actually
     
    108139int gzip_expand(const void *src, size_t srclen, void *dest, size_t destlen)
    109140{
     141        if (!gzip_check(src, srclen))
     142                return EINVAL;
     143
     144        /* Decode header and footer */
     145
    110146        gzip_header_t header;
     147        memcpy(&header, src, sizeof(header));
     148
    111149        gzip_footer_t footer;
    112 
    113         if ((srclen < sizeof(header)) || (srclen < sizeof(footer)))
    114                 return EINVAL;
    115 
    116         /* Decode header and footer */
    117 
    118         memcpy(&header, src, sizeof(header));
    119150        memcpy(&footer, src + srclen - sizeof(footer), sizeof(footer));
    120 
    121         if ((header.id1 != GZIP_ID1) ||
    122             (header.id2 != GZIP_ID2) ||
    123             (header.method != GZIP_METHOD_DEFLATE) ||
    124             ((header.flags & (~GZIP_FLAGS_MASK)) != 0))
    125                 return EINVAL;
    126151
    127152        if (destlen != uint32_t_le2host(footer.size))
  • boot/generic/src/payload.c

    rda15002 rd091007  
    6161{
    6262        char *e = (char *) ext(s);
    63         if (e != NULL && str_cmp(e, ".gz") == 0)
     63        if ((e != NULL) && (str_cmp(e, ".gz") == 0))
    6464                *e = '\0';
    65 }
    66 
    67 static bool isgzip(const char *s)
    68 {
    69         const char *e = ext(s);
    70         return e != NULL && str_cmp(e, ".gz") == 0;
    7165}
    7266
     
    8276{
    8377        const char *name;
    84         const uint8_t *data;
    8578        size_t packed_size;
    86         size_t unpacked_size;
    8779
    8880        if (!tar_info(*cstart, cend, &name, &packed_size))
    8981                return false;
    9082
    91         data = *cstart + TAR_BLOCK_SIZE;
     83        const uint8_t *data = *cstart + TAR_BLOCK_SIZE;
    9284        *cstart += TAR_BLOCK_SIZE + ALIGN_UP(packed_size, TAR_BLOCK_SIZE);
    9385
    94         bool gz = isgzip(name);
    95 
    96         unpacked_size = gz ? gzip_size(data, packed_size) : packed_size;
     86        bool gz = gzip_check(data, packed_size);
     87        size_t unpacked_size = gz ? gzip_size(data, packed_size) : packed_size;
    9788
    9889        /* Components must be page-aligned. */
     
    156147        while (tar_info(start, payload_end, &name, &packed_size)) {
    157148                sz = ALIGN_UP(sz, PAGE_SIZE);
    158                 if (isgzip(name))
     149                if (gzip_check(start + TAR_BLOCK_SIZE, packed_size))
    159150                        sz += gzip_size(start + TAR_BLOCK_SIZE, packed_size);
    160151                else
Note: See TracChangeset for help on using the changeset viewer.