Implement CRC calculation of input sections

This commit is contained in:
Mario Hüttel 2022-10-20 21:36:54 +02:00
parent 57be15d909
commit c8da6e4f4c
3 changed files with 117 additions and 15 deletions

View File

@ -20,6 +20,7 @@ struct elf_section {
struct elfpatch { struct elfpatch {
uint32_t magic; uint32_t magic;
int fd; int fd;
bool readonly;
Elf *elf; Elf *elf;
GElf_Ehdr ehdr; GElf_Ehdr ehdr;
int class; int class;
@ -218,7 +219,7 @@ static int elf_patch_update_info(elfpatch_handle_t *ep)
return 0; return 0;
} }
elfpatch_handle_t *elf_patch_open(const char *path) elfpatch_handle_t *elf_patch_open(const char *path, bool readonly)
{ {
struct elfpatch *ep; struct elfpatch *ep;
@ -229,13 +230,14 @@ elfpatch_handle_t *elf_patch_open(const char *path)
ep = (struct elfpatch *)calloc(1u, sizeof(struct elfpatch)); ep = (struct elfpatch *)calloc(1u, sizeof(struct elfpatch));
ep->magic = ELFPATCH_MAGIC; ep->magic = ELFPATCH_MAGIC;
ep->readonly = readonly;
ep->fd = open(path, O_RDWR, 0); ep->fd = open(path, readonly ? O_RDONLY : O_RDWR, 0);
if (ep->fd < 0) { if (ep->fd < 0) {
print_err("Error opening file: %s\n", path); print_err("Error opening file: %s\n", path);
goto free_struct; goto free_struct;
} }
ep->elf = elf_begin(ep->fd, ELF_C_RDWR, NULL); ep->elf = elf_begin(ep->fd, readonly ? ELF_C_READ : ELF_C_RDWR, NULL);
if (!ep->elf) { if (!ep->elf) {
print_err("[LIBELF] %s\n", elf_errmsg(-1)); print_err("[LIBELF] %s\n", elf_errmsg(-1));
goto close_fd; goto close_fd;

View File

@ -14,7 +14,7 @@ enum granularity {
}; };
elfpatch_handle_t *elf_patch_open(const char *path); elfpatch_handle_t *elf_patch_open(const char *path, bool readonly);
/** /**
* @brief Check if a section is present in file * @brief Check if a section is present in file

122
main.c
View File

@ -27,6 +27,7 @@
#include <linklist-lib/singly-linked-list.h> #include <linklist-lib/singly-linked-list.h>
#include <patchelfcrc/reporting.h> #include <patchelfcrc/reporting.h>
#include <patchelfcrc/elfpatch.h> #include <patchelfcrc/elfpatch.h>
#include <fort.h>
const char *argp_program_bug_address = "<mario [dot] huettel [at] linux [dot] com>"; const char *argp_program_bug_address = "<mario [dot] huettel [at] linux [dot] com>";
@ -232,11 +233,101 @@ static void free_cmd_args(struct command_line_options *opts)
opts->section_list = NULL; opts->section_list = NULL;
} }
/**
* @brief check_all_sections_present
* @param ep
* @param list
* @return -1 if no sections are provided. 0 if all sections are present. -2 if setions cannot be found
*/
static int check_all_sections_present(elfpatch_handle_t *ep, SlList *list)
{
SlList *iter;
const char *sec_name;
int ret = 0;
if (!ep)
return -1001;
if (!list) {
print_err("No input sections specified.\n")
return -1;
}
for (iter = list; iter; iter = sl_list_next(iter)) {
sec_name = (const char *)iter->data;
if (!sec_name)
continue;
if (elf_patch_check_for_section(ep, sec_name)) {
print_err("Cannot find section '%s'\n", sec_name);
ret = -2;
} else {
print_debug("Input section '%s': found\n", sec_name);
}
}
return ret;
}
/**
* @brief Compute CRCs over the sections in @p list
* @param ep Elf patch
* @param list List of section names to patch
* @param opts Command line options. Used for CRC generation
* @param[out] crcs Array of output CRCs. Must be large enough to hold all elements
* @return 0 if successful
*/
static int compute_crcs(elfpatch_handle_t *ep, SlList *list, const struct command_line_options *opts, uint32_t *crcs)
{
SlList *iter;
const char *sec_name;
int ret = 0;
struct crc_calc _crc;
struct crc_calc * const crc = &_crc;
unsigned int idx;
/* Construct the CRC */
crc_init(crc, &opts->crc);
for (iter = list, idx = 0; iter; iter = sl_list_next(iter), idx++) {
crc_reset(crc);
sec_name = (const char *)iter->data;
if (elf_patch_compute_crc_over_section(ep, sec_name, crc, opts->granularity, opts->little_endian)) {
print_err("Error during CRC calculation. Exiting.\n");
ret = -1;
break;
}
crc_finish_calc(crc);
crcs[idx] = crc_get_value(crc);
}
return ret;
}
static void print_crcs(SlList *list, const uint32_t *crcs)
{
SlList *iter;
unsigned int idx;
const char *sec_name;
ft_table_t *table;
table = ft_create_table();
/* Write header */
ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
ft_write_ln(table, "Section", "CRC");
for (iter = list, idx = 0; iter; iter = sl_list_next(iter), idx++) {
sec_name = (const char *)iter->data;
ft_printf_ln(table, "%s|0x%x", sec_name, crcs[idx]);
}
print_debug("Calculated CRCs:\n%s\n", ft_to_string(table));
ft_destroy_table(table);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct crc_calc crc;
struct command_line_options cmd_opts; struct command_line_options cmd_opts;
elfpatch_handle_t *ep; elfpatch_handle_t *ep;
int ret = 0;
uint32_t *crcs;
prepare_default_opts(&cmd_opts); prepare_default_opts(&cmd_opts);
parse_cmdline_options(&argc, &argv, &cmd_opts); parse_cmdline_options(&argc, &argv, &cmd_opts);
@ -262,26 +353,35 @@ int main(int argc, char **argv)
goto free_cmds; goto free_cmds;
} }
/* Build the CRC */
crc_init(&crc, &cmd_opts.crc);
/* Prepare libelf for use with the latest ELF version */ /* Prepare libelf for use with the latest ELF version */
elf_version(EV_CURRENT); elf_version(EV_CURRENT);
/* Open the ELF file */ /* Open the ELF file */
ep = elf_patch_open(cmd_opts.elf_path); ep = elf_patch_open(cmd_opts.elf_path, cmd_opts.dry_run);
if (!ep) {
ret = -2;
goto free_cmds;
}
/* TODO: Implement this correctly! */ /* Check if all sections are present */
elf_patch_compute_crc_over_section(ep, ".text", &crc, cmd_opts.granularity, cmd_opts.little_endian); if (check_all_sections_present(ep, cmd_opts.section_list)) {
ret = -2;
goto free_cmds;
}
/* Compute CRCs over sections */
crcs = (uint32_t *)malloc(sl_list_length(cmd_opts.section_list) * sizeof(uint32_t));
compute_crcs(ep, cmd_opts.section_list, &cmd_opts, crcs);
if (reporting_get_verbosity()) {
print_crcs(cmd_opts.section_list, crcs);
}
elf_patch_close_and_free(ep); elf_patch_close_and_free(ep);
printf("CRC is: 0x%08x\n", crc_get_value(&crc));
crc_destroy(&crc);
free_cmds: free_cmds:
free_cmd_args(&cmd_opts); free_cmd_args(&cmd_opts);
return 0; return ret;
} }