Skip to content

Commit fd3e8e4

Browse files
committed
rimage: harden image detection and validate re-sign output
Avoid false-positive CPD header detection when re-signing by validating CSE header candidates before accepting them. Make verification failures propagate as non-zero return values and ensure resources are cleaned up on all paths. After re-signing, verify the generated image immediately and remove the output file if verification fails to prevent leaving broken artifacts. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent a1c1f84 commit fd3e8e4

1 file changed

Lines changed: 44 additions & 4 deletions

File tree

tools/rimage/src/manifest.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <unistd.h>
1313
#include <errno.h>
1414
#include <string.h>
15+
#include <stdbool.h>
1516
#include <time.h>
1617
#include <sys/time.h>
1718

@@ -26,6 +27,29 @@
2627
#include <rimage/misc_utils.h>
2728
#include <rimage/hash.h>
2829

30+
static bool cse_header_is_valid(const struct image *image, const void *buffer, size_t size)
31+
{
32+
if (image->adsp->man_v2_5 || image->adsp->man_ace_v1_5) {
33+
const struct CsePartitionDirHeader_v2_5 *cse_hdr = buffer;
34+
35+
return cse_hdr->header_marker == CSE_HEADER_MAKER &&
36+
cse_hdr->nb_entries == MAN_CSE_PARTS &&
37+
cse_hdr->header_length >= sizeof(*cse_hdr) &&
38+
size >= sizeof(*cse_hdr);
39+
}
40+
41+
if (image->adsp->man_v1_5 || image->adsp->man_v1_8) {
42+
const struct CsePartitionDirHeader *cse_hdr = buffer;
43+
44+
return cse_hdr->header_marker == CSE_HEADER_MAKER &&
45+
cse_hdr->nb_entries == MAN_CSE_PARTS &&
46+
cse_hdr->header_length >= sizeof(*cse_hdr) &&
47+
size >= sizeof(*cse_hdr);
48+
}
49+
50+
return false;
51+
}
52+
2953
static int man_open_rom_file(struct image *image)
3054
{
3155
uint32_t size;
@@ -1644,7 +1668,7 @@ int man_write_fw_ace_v1_5(struct image *image)
16441668
int verify_image(struct image *image)
16451669
{
16461670
FILE *in_file;
1647-
int ret;
1671+
int ret = -EINVAL;
16481672
void *buffer;
16491673
size_t size, read, i;
16501674

@@ -1680,7 +1704,7 @@ int verify_image(struct image *image)
16801704
}
16811705
for (i = 0; i + sizeof(uint32_t) <= size; i += sizeof(uint32_t)) {
16821706
/* find CSE header marker "$CPD" */
1683-
if (*(uint32_t *)(buffer + i) == CSE_HEADER_MAKER) {
1707+
if (cse_header_is_valid(image, buffer + i, size - i)) {
16841708
image->fw_image = buffer + i;
16851709
/* size of the image from the CSE header to the end of the
16861710
* file, used by v1.5 verification and the signed-payload
@@ -1706,6 +1730,7 @@ int verify_image(struct image *image)
17061730
image->verify_file);
17071731
ret = -EINVAL;
17081732
out:
1733+
free(buffer);
17091734
fclose(in_file);
17101735
/* propagate verification result so callers (and the exit code) can
17111736
* detect a failed/missing verification instead of always seeing success
@@ -1751,7 +1776,7 @@ int resign_image(struct image *image)
17511776

17521777
for (i = 0; i + sizeof(uint32_t) <= size; i += sizeof(uint32_t)) {
17531778
/* find CSE header marker "$CPD" */
1754-
if (*(uint32_t *)(buffer + i) == CSE_HEADER_MAKER) {
1779+
if (cse_header_is_valid(image, buffer + i, size - i)) {
17551780
image->fw_image = buffer + i;
17561781
break;
17571782
}
@@ -1813,7 +1838,22 @@ int resign_image(struct image *image)
18131838
goto out;
18141839
}
18151840

1816-
man_write_fw_mod(image);
1841+
ret = man_write_fw_mod(image);
1842+
if (ret < 0)
1843+
goto out;
1844+
1845+
if (fclose(image->out_fd)) {
1846+
ret = file_error("unable to close file after signing", image->out_file);
1847+
goto out;
1848+
}
1849+
image->out_fd = NULL;
1850+
1851+
/* validate the re-signed output with the same private key */
1852+
image->verify_file = image->out_file;
1853+
ret = verify_image(image);
1854+
image->verify_file = NULL;
1855+
if (ret < 0)
1856+
unlink(image->out_file);
18171857

18181858
out:
18191859
free(buffer);

0 commit comments

Comments
 (0)