diff options
| author | Michael Brown | 2025-04-22 13:13:22 +0200 |
|---|---|---|
| committer | Michael Brown | 2025-04-22 13:32:12 +0200 |
| commit | c059b341707863f8ecc4ecde75dd608dda72fdad (patch) | |
| tree | a3d99be7a70692ba478268018db620a3de2b1c28 /src/image | |
| parent | [image] Remove userptr_t from image definition (diff) | |
| download | ipxe-c059b341707863f8ecc4ecde75dd608dda72fdad.tar.gz ipxe-c059b341707863f8ecc4ecde75dd608dda72fdad.tar.xz ipxe-c059b341707863f8ecc4ecde75dd608dda72fdad.zip | |
[deflate] Remove userptr_t from decompression code
Simplify the deflate, zlib, and gzip decompression code by assuming
that all content is fully accessible via pointer dereferences.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/image')
| -rw-r--r-- | src/image/gzip.c | 92 | ||||
| -rw-r--r-- | src/image/png.c | 7 | ||||
| -rw-r--r-- | src/image/zlib.c | 27 |
3 files changed, 64 insertions, 62 deletions
diff --git a/src/image/gzip.c b/src/image/gzip.c index 116d912d7..b72c3243e 100644 --- a/src/image/gzip.c +++ b/src/image/gzip.c @@ -24,10 +24,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdlib.h> +#include <string.h> #include <errno.h> #include <assert.h> #include <ipxe/deflate.h> -#include <ipxe/uaccess.h> #include <ipxe/image.h> #include <ipxe/zlib.h> #include <ipxe/gzip.h> @@ -46,83 +46,92 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * @ret rc Return status code */ static int gzip_extract ( struct image *image, struct image *extracted ) { - struct gzip_header header; - struct gzip_extra_header extra; - struct gzip_crc_header crc; - struct gzip_footer footer; - struct deflate_chunk in; - unsigned int strings; - size_t offset; + const struct gzip_header *header; + const struct gzip_extra_header *extra; + const struct gzip_crc_header *crc; + const struct gzip_footer *footer; + const void *data; + size_t extra_len; + size_t string_len; size_t len; - off_t nul; + unsigned int strings; int rc; /* Sanity check */ - assert ( image->len >= ( sizeof ( header ) + sizeof ( footer ) ) ); + assert ( image->len >= ( sizeof ( *header ) + sizeof ( *footer ) ) ); + data = image->data; + len = image->len; /* Extract footer */ - len = ( image->len - sizeof ( footer ) ); - copy_from_user ( &footer, image->data, len, sizeof ( footer ) ); + assert ( len >= sizeof ( *footer ) ); + len -= sizeof ( *footer ); + footer = ( data + len ); /* Extract fixed header */ - copy_from_user ( &header, image->data, 0, sizeof ( header ) ); - offset = sizeof ( header ); - assert ( offset <= ( image->len - sizeof ( footer ) ) ); + assert ( len >= sizeof ( *header ) ); + header = data; + data += sizeof ( *header ); + len -= sizeof ( *header ); /* Skip extra header, if present */ - if ( header.flags & GZIP_FL_EXTRA ) { - copy_from_user ( &extra, image->data, offset, - sizeof ( extra ) ); - offset += sizeof ( extra ); - offset += le16_to_cpu ( extra.len ); - if ( offset > len ) { + if ( header->flags & GZIP_FL_EXTRA ) { + if ( len < sizeof ( *extra ) ) { DBGC ( image, "GZIP %p overlength extra header\n", image ); return -EINVAL; } + extra = data; + data += sizeof ( *extra ); + len -= sizeof ( *extra ); + extra_len = le16_to_cpu ( extra->len ); + if ( len < extra_len ) { + DBGC ( image, "GZIP %p overlength extra header\n", + image ); + return -EINVAL; + } + data += extra_len; + len -= extra_len; } - assert ( offset <= ( image->len - sizeof ( footer ) ) ); /* Skip name and/or comment, if present */ strings = 0; - if ( header.flags & GZIP_FL_NAME ) + if ( header->flags & GZIP_FL_NAME ) strings++; - if ( header.flags & GZIP_FL_COMMENT ) + if ( header->flags & GZIP_FL_COMMENT ) strings++; while ( strings-- ) { - nul = memchr_user ( image->data, offset, 0, ( len - offset ) ); - if ( nul < 0 ) { + string_len = strnlen ( data, len ); + if ( string_len == len ) { DBGC ( image, "GZIP %p overlength name/comment\n", image ); return -EINVAL; } - offset = ( nul + 1 /* NUL */ ); + data += ( string_len + 1 /* NUL */ ); + len -= ( string_len + 1 /* NUL */ ); } - assert ( offset <= ( image->len - sizeof ( footer ) ) ); /* Skip CRC, if present */ - if ( header.flags & GZIP_FL_HCRC ) { - offset += sizeof ( crc ); - if ( offset > len ) { + if ( header->flags & GZIP_FL_HCRC ) { + if ( len < sizeof ( *crc ) ) { DBGC ( image, "GZIP %p overlength CRC header\n", image ); return -EINVAL; } + data += sizeof ( *crc ); + len -= sizeof ( *crc ); } - /* Initialise input chunk */ - deflate_chunk_init ( &in, ( image->data + offset ), 0, len ); - /* Presize extracted image */ if ( ( rc = image_set_len ( extracted, - le32_to_cpu ( footer.len ) ) ) != 0 ) { + le32_to_cpu ( footer->len ) ) ) != 0 ) { DBGC ( image, "GZIP %p could not presize: %s\n", image, strerror ( rc ) ); return rc; } /* Decompress image (expanding if necessary) */ - if ( ( rc = zlib_deflate ( DEFLATE_RAW, &in, extracted ) ) != 0 ) { + if ( ( rc = zlib_deflate ( DEFLATE_RAW, data, len, + extracted ) ) != 0 ) { DBGC ( image, "GZIP %p could not decompress: %s\n", image, strerror ( rc ) ); return rc; @@ -138,19 +147,18 @@ static int gzip_extract ( struct image *image, struct image *extracted ) { * @ret rc Return status code */ static int gzip_probe ( struct image *image ) { - struct gzip_header header; - struct gzip_footer footer; + const struct gzip_header *header; + const struct gzip_footer *footer; /* Sanity check */ - if ( image->len < ( sizeof ( header ) + sizeof ( footer ) ) ) { + if ( image->len < ( sizeof ( *header ) + sizeof ( *footer ) ) ) { DBGC ( image, "GZIP %p image too short\n", image ); return -ENOEXEC; } + header = image->data; /* Check magic header */ - copy_from_user ( &header.magic, image->data, 0, - sizeof ( header.magic ) ); - if ( header.magic != cpu_to_be16 ( GZIP_MAGIC ) ) { + if ( header->magic != cpu_to_be16 ( GZIP_MAGIC ) ) { DBGC ( image, "GZIP %p invalid magic\n", image ); return -ENOEXEC; } diff --git a/src/image/png.c b/src/image/png.c index d5cf7fd8f..8b432e01a 100644 --- a/src/image/png.c +++ b/src/image/png.c @@ -336,13 +336,12 @@ static int png_palette ( struct image *image, struct png_context *png, */ static int png_image_data ( struct image *image, struct png_context *png, size_t len ) { - struct deflate_chunk in; int rc; /* Deflate this chunk */ - deflate_chunk_init ( &in, image->data, png->offset, - ( png->offset + len ) ); - if ( ( rc = deflate_inflate ( &png->deflate, &in, &png->raw ) ) != 0 ) { + if ( ( rc = deflate_inflate ( &png->deflate, + ( image->data + png->offset ), + len, &png->raw ) ) != 0 ) { DBGC ( image, "PNG %s could not decompress: %s\n", image->name, strerror ( rc ) ); return rc; diff --git a/src/image/zlib.c b/src/image/zlib.c index a42c47e1b..d7deee88b 100644 --- a/src/image/zlib.c +++ b/src/image/zlib.c @@ -27,7 +27,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <errno.h> #include <assert.h> #include <ipxe/deflate.h> -#include <ipxe/uaccess.h> #include <ipxe/image.h> #include <ipxe/zlib.h> @@ -41,11 +40,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * Extract compressed data to image * * @v format Compression format code - * @v in Compressed input chunk + * @v data Compressed input data + * @v len Length of compressed input data * @v extracted Extracted image * @ret rc Return status code */ -int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in, +int zlib_deflate ( enum deflate_format format, const void *data, size_t len, struct image *extracted ) { struct deflate *deflate; struct deflate_chunk out; @@ -64,14 +64,12 @@ int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in, /* (Re)initialise decompressor */ deflate_init ( deflate, format ); - /* (Re)initialise input chunk */ - in->offset = 0; - /* Initialise output chunk */ deflate_chunk_init ( &out, extracted->data, 0, extracted->len ); /* Decompress data */ - if ( ( rc = deflate_inflate ( deflate, in, &out ) ) != 0 ) { + if ( ( rc = deflate_inflate ( deflate, data, len, + &out ) ) != 0 ) { DBGC ( extracted, "ZLIB %p could not decompress: %s\n", extracted, strerror ( rc ) ); goto err_inflate; @@ -116,14 +114,11 @@ int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in, * @ret rc Return status code */ static int zlib_extract ( struct image *image, struct image *extracted ) { - struct deflate_chunk in; int rc; - /* Initialise input chunk */ - deflate_chunk_init ( &in, image->data, 0, image->len ); - /* Decompress image */ - if ( ( rc = zlib_deflate ( DEFLATE_ZLIB, &in, extracted ) ) != 0 ) + if ( ( rc = zlib_deflate ( DEFLATE_ZLIB, image->data, image->len, + extracted ) ) != 0 ) return rc; return 0; @@ -136,17 +131,17 @@ static int zlib_extract ( struct image *image, struct image *extracted ) { * @ret rc Return status code */ static int zlib_probe ( struct image *image ) { - union zlib_magic magic; + const union zlib_magic *magic; /* Sanity check */ - if ( image->len < sizeof ( magic ) ) { + if ( image->len < sizeof ( *magic ) ) { DBGC ( image, "ZLIB %p image too short\n", image ); return -ENOEXEC; } + magic = image->data; /* Check magic header */ - copy_from_user ( &magic, image->data, 0, sizeof ( magic ) ); - if ( ! zlib_magic_is_valid ( &magic ) ) { + if ( ! zlib_magic_is_valid ( magic ) ) { DBGC ( image, "ZLIB %p invalid magic data\n", image ); return -ENOEXEC; } |
