Implement CRC calculation of input sections
This commit is contained in:
		| @@ -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; | ||||||
|   | |||||||
| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								main.c
									
									
									
									
									
								
							| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user