Discussion:
[PATCH 1/7] uImage: fix realloc() pointer confusion
David Woodhouse
2017-03-08 22:41:08 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

We carefully avoid the realloc() API trap by *not* using the
'ptr = realloc(ptr, new_size)' idiom which can lead to leaks on
failure. Very commendable, even though all we're going to do is
exit() on failure so it wouldn't have mattered.

What *does* matter is that we then ask zlib to continue
decompression... just past the end of the *old* buffer that just
got freed. Oops.

Apparently nobody has *ever* tested this code by booting a uImage
with a compressed payload larger than 10MiB.

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
kexec/kexec-uImage.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
index 5e24629..667cd93 100644
--- a/kexec/kexec-uImage.c
+++ b/kexec/kexec-uImage.c
@@ -210,9 +210,9 @@ static int uImage_gz_load(const unsigned char *buf, off_t len,
return -1;
}

+ uncomp_buf = new_buf;
strm.next_out = uncomp_buf + mem_alloc - inc_buf;
strm.avail_out = inc_buf;
- uncomp_buf = new_buf;
} else {
printf("Error during decompression %d\n", ret);
return -1;
--
2.9.3
David Woodhouse
2017-03-08 22:41:09 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
kexec/kexec-uImage.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
index 667cd93..49f266a 100644
--- a/kexec/kexec-uImage.c
+++ b/kexec/kexec-uImage.c
@@ -236,7 +236,7 @@ int uImage_load(const unsigned char *buf, off_t len, struct Image_info *image)
{
const struct image_header *header = (const struct image_header *)buf;
const unsigned char *img_buf = buf + sizeof(struct image_header);
- off_t img_len = header->ih_size;
+ off_t img_len = be32_to_cpu(header->ih_size);

/*
* Prevent loading a modified image.
--
2.9.3
David Woodhouse
2017-03-08 22:41:10 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
include/image.h | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/include/image.h b/include/image.h
index e742aae..8e9d81e 100644
--- a/include/image.h
+++ b/include/image.h
@@ -79,6 +79,13 @@
#define IH_ARCH_BLACKFIN 16 /* Blackfin */
#define IH_ARCH_AVR32 17 /* AVR32 */
#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */
+#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */
+#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */
+#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */
+#define IH_ARCH_ARM64 22 /* ARM64 */
+#define IH_ARCH_ARC 23 /* Synopsys DesignWare ARC */
+#define IH_ARCH_X86_64 24 /* AMD x86_64, Intel and Via */
+#define IH_ARCH_XTENSA 25 /* Xtensa */

/*
* Image Types
--
2.9.3
David Woodhouse
2017-03-08 22:41:11 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

This was only ever used on PPC, where they are equivalent and we
never saw the resulting -Wpointer-sign warnings.

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
include/kexec-uImage.h | 4 ++--
kexec/arch/ppc/kexec-uImage-ppc.c | 2 +-
kexec/kexec-uImage.c | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/kexec-uImage.h b/include/kexec-uImage.h
index 4725157..483b578 100644
--- a/include/kexec-uImage.h
+++ b/include/kexec-uImage.h
@@ -2,7 +2,7 @@
#define __KEXEC_UIMAGE_H__

struct Image_info {
- const unsigned char *buf;
+ const char *buf;
off_t len;
unsigned int base;
unsigned int ep;
@@ -11,5 +11,5 @@ struct Image_info {
int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch);
int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch);
int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch);
-int uImage_load(const unsigned char *buf, off_t len, struct Image_info *info);
+int uImage_load(const char *buf, off_t len, struct Image_info *info);
#endif
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index c89a1a7..5eec6e4 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -55,7 +55,7 @@ char *slurp_ramdisk_ppc(const char *filename, off_t *r_size)
{
struct Image_info img;
off_t size;
- const unsigned char *buf = slurp_file(filename, &size);
+ const char *buf = slurp_file(filename, &size);
int rc;

/* Check if this is a uImage RAMDisk */
diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
index 49f266a..2740a26 100644
--- a/kexec/kexec-uImage.c
+++ b/kexec/kexec-uImage.c
@@ -136,7 +136,7 @@ int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch)
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */

-static int uImage_gz_load(const unsigned char *buf, off_t len,
+static int uImage_gz_load(const char *buf, off_t len,
struct Image_info *image)
{
int ret;
@@ -225,14 +225,14 @@ static int uImage_gz_load(const unsigned char *buf, off_t len,
return 0;
}
#else
-static int uImage_gz_load(const unsigned char *UNUSED(buf), off_t UNUSED(len),
+static int uImage_gz_load(const char *UNUSED(buf), off_t UNUSED(len),
struct Image_info *UNUSED(image))
{
return -1;
}
#endif

-int uImage_load(const unsigned char *buf, off_t len, struct Image_info *image)
+int uImage_load(const char *buf, off_t len, struct Image_info *image)
{
const struct image_header *header = (const struct image_header *)buf;
const unsigned char *img_buf = buf + sizeof(struct image_header);
--
2.9.3
David Woodhouse
2017-03-08 22:41:13 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
kexec/arch/arm64/Makefile | 3 +++
kexec/arch/arm64/kexec-arm64.c | 1 +
kexec/arch/arm64/kexec-arm64.h | 4 ++++
kexec/arch/arm64/kexec-uImage-arm64.c | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 42 insertions(+)
create mode 100644 kexec/arch/arm64/kexec-uImage-arm64.c

diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
index 74b677f..a931f0e 100644
--- a/kexec/arch/arm64/Makefile
+++ b/kexec/arch/arm64/Makefile
@@ -12,8 +12,11 @@ arm64_KEXEC_SRCS += \
kexec/arch/arm64/crashdump-arm64.c \
kexec/arch/arm64/kexec-arm64.c \
kexec/arch/arm64/kexec-elf-arm64.c \
+ kexec/arch/arm64/kexec-uImage-arm64.c \
kexec/arch/arm64/kexec-image-arm64.c

+arm64_UIMAGE = kexec/kexec-uImage.c
+
arm64_ARCH_REUSE_INITRD =
arm64_ADD_SEGMENT =
arm64_VIRT_TO_PHYS =
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 04fd396..c822939 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -40,6 +40,7 @@ const struct arch_map_entry arches[] = {
struct file_type file_type[] = {
{"vmlinux", elf_arm64_probe, elf_arm64_load, elf_arm64_usage},
{"Image", image_arm64_probe, image_arm64_load, image_arm64_usage},
+ {"uImage", uImage_arm64_probe, uImage_arm64_load, uImage_arm64_usage},
};

int file_types = sizeof(file_type) / sizeof(file_type[0]);
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index bd4c20e..bf724ef 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -30,6 +30,10 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size);
int image_arm64_load(int argc, char **argv, const char *kernel_buf,
off_t kernel_size, struct kexec_info *info);
void image_arm64_usage(void);
+int uImage_arm64_probe(const char *buf, off_t len);
+int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void uImage_arm64_usage(void);

off_t initrd_base;
off_t initrd_size;
diff --git a/kexec/arch/arm64/kexec-uImage-arm64.c b/kexec/arch/arm64/kexec-uImage-arm64.c
new file mode 100644
index 0000000..022d7ee
--- /dev/null
+++ b/kexec/arch/arm64/kexec-uImage-arm64.c
@@ -0,0 +1,34 @@
+/*
+ * uImage support added by David Woodhouse <***@infradead.org>
+ */
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <image.h>
+#include <kexec-uImage.h>
+#include "../../kexec.h"
+#include "kexec-arm64.h"
+
+int uImage_arm64_probe(const char *buf, off_t len)
+{
+ return uImage_probe_kernel(buf, len, IH_ARCH_ARM64);
+}
+
+int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ struct Image_info img;
+ int ret;
+
+ ret = uImage_load(buf, len, &img);
+ if (ret)
+ return ret;
+
+ return image_arm64_load(argc, argv, img.buf, img.len, info);
+}
+
+void uImage_arm64_usage(void)
+{
+ printf(
+" An ARM64 U-boot uImage file, compressed or not, big or little endian.\n\n");
+}
--
2.9.3
David Woodhouse
2017-03-08 22:41:12 UTC
Permalink
From: David Woodhouse <***@amazon.co.uk>

... and friends. Again, PPC never cared about the difference, while
ARM had to add an explicit cast to work around it, which we can remove
now.

Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
include/kexec-uImage.h | 6 +++---
kexec/arch/arm/kexec-uImage-arm.c | 3 +--
kexec/kexec-uImage.c | 10 +++++-----
3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/include/kexec-uImage.h b/include/kexec-uImage.h
index 483b578..983d63f 100644
--- a/include/kexec-uImage.h
+++ b/include/kexec-uImage.h
@@ -8,8 +8,8 @@ struct Image_info {
unsigned int ep;
};

-int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch);
-int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch);
-int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch);
+int uImage_probe(const char *buf, off_t len, unsigned int arch);
+int uImage_probe_kernel(const char *buf, off_t len, unsigned int arch);
+int uImage_probe_ramdisk(const char *buf, off_t len, unsigned int arch);
int uImage_load(const char *buf, off_t len, struct Image_info *info);
#endif
diff --git a/kexec/arch/arm/kexec-uImage-arm.c b/kexec/arch/arm/kexec-uImage-arm.c
index 8e0a9ac..03c2f4d 100644
--- a/kexec/arch/arm/kexec-uImage-arm.c
+++ b/kexec/arch/arm/kexec-uImage-arm.c
@@ -11,8 +11,7 @@

int uImage_arm_probe(const char *buf, off_t len)
{
- return uImage_probe_kernel((const unsigned char *)buf, len,
- IH_ARCH_ARM);
+ return uImage_probe_kernel(buf, len, IH_ARCH_ARM);
}

int uImage_arm_load(int argc, char **argv, const char *buf, off_t len,
diff --git a/kexec/kexec-uImage.c b/kexec/kexec-uImage.c
index 2740a26..eeee4be 100644
--- a/kexec/kexec-uImage.c
+++ b/kexec/kexec-uImage.c
@@ -24,7 +24,7 @@
*
* Returns 0 if this is not a uImage
*/
-int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
+int uImage_probe(const char *buf, off_t len, unsigned int arch)
{
struct image_header header;
#ifdef HAVE_LIBZ
@@ -109,7 +109,7 @@ int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch)
* 1 - If the image is not a uImage.
*/

-int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch)
+int uImage_probe_kernel(const char *buf, off_t len, unsigned int arch)
{
int type = uImage_probe(buf, len, arch);
if (type < 0)
@@ -118,7 +118,7 @@ int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch)
return !(type == IH_TYPE_KERNEL || type == IH_TYPE_KERNEL_NOLOAD);
}

-int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch)
+int uImage_probe_ramdisk(const char *buf, off_t len, unsigned int arch)
{
int type = uImage_probe(buf, len, arch);

@@ -220,7 +220,7 @@ static int uImage_gz_load(const char *buf, off_t len,
} while (1);

inflateEnd(&strm);
- image->buf = uncomp_buf;
+ image->buf = (char *)uncomp_buf;
image->len = mem_alloc - strm.avail_out;
return 0;
}
@@ -235,7 +235,7 @@ static int uImage_gz_load(const char *UNUSED(buf), off_t UNUSED(len),
int uImage_load(const char *buf, off_t len, struct Image_info *image)
{
const struct image_header *header = (const struct image_header *)buf;
- const unsigned char *img_buf = buf + sizeof(struct image_header);
+ const char *img_buf = buf + sizeof(struct image_header);
off_t img_len = be32_to_cpu(header->ih_size);

/*
--
2.9.3
David Woodhouse
2017-03-08 22:41:14 UTC
Permalink
From: Khem Raj <***@gmail.com>

loff_t is guarded with _GNU_SOURCE on some C library implementations
e.g. musl since this type is not defined by POSIX. Define _GNU_SOURCE to
include this define, it should help compiling on musl while nothing
changes for glibc based systems since there _GNU_SOURCE is already
defined

Signed-off-by: Khem Raj <***@gmail.com>
Signed-off-by: David Woodhouse <***@amazon.co.uk>
---
vmcore-dmesg/vmcore-dmesg.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/vmcore-dmesg/vmcore-dmesg.c b/vmcore-dmesg/vmcore-dmesg.c
index 0364636..a8f56df 100644
--- a/vmcore-dmesg/vmcore-dmesg.c
+++ b/vmcore-dmesg/vmcore-dmesg.c
@@ -1,4 +1,5 @@
#define _XOPEN_SOURCE 600
+#define _GNU_SOURCE
#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#include <endian.h>
--
2.9.3
Simon Horman
2017-03-13 09:03:49 UTC
Permalink
Thanks, series applied.

Loading...