diff --git a/code_sign/code_sign_ext.c b/code_sign/code_sign_ext.c index afe042278473faa5d1b794d8c8ec62856332e1be..16abbaf803ceb3eb8429e090f4e0c99f35ceaf34 100644 --- a/code_sign/code_sign_ext.c +++ b/code_sign/code_sign_ext.c @@ -24,10 +24,14 @@ static inline int check_code_sign_descriptor(const struct inode *inode, if (!desc->cs_version) return 0; - - if (desc->__reserved1 || - memchr_inv(desc->__reserved2, 0, sizeof(desc->__reserved2))) + + // when calc pgtypeinfo_size, trans bit size to byte size + u32 pgtypeinfo_size_bytes = le32_to_cpu(desc->pgtypeinfo_size) / 8; + if (le64_to_cpu(desc->pgtypeinfo_off) > le64_to_cpu(desc->data_size) - pgtypeinfo_size_bytes) { + code_sign_log_error("Wrong offset: %llu (pgtypeinfo_off) > %llu (data_size) - %u (pgtypeinfo_size)", + le64_to_cpu(desc->pgtypeinfo_off), le64_to_cpu(desc->data_size), pgtypeinfo_size_bytes); return -EINVAL; + } if (le64_to_cpu(desc->data_size) > inode->i_size) { code_sign_log_error("Wrong data_size: %llu (desc) > %lld (inode)", @@ -67,11 +71,11 @@ void code_sign_before_measurement(void *_desc, int *ret) { struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); - if (desc->cs_version) { - // replace version with cs_version - desc->version = desc->cs_version; + if (desc->cs_version == 1) { + *ret = desc->cs_version; desc->cs_version = 0; - *ret = desc->version; + } else { + *ret = desc->cs_version; } } @@ -79,7 +83,7 @@ void code_sign_after_measurement(void *_desc, int version) { struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); - if (version) { + if (version == 1) { // restore cs_version desc->cs_version = desc->version; desc->version = version; diff --git a/xpm/validator/elf_code_segment_info.c b/xpm/validator/elf_code_segment_info.c index dbbb1a0f95cbe39ff57681071be2f61237a477ea..385ad3c863fab2707fc29676e836d1a36966b3aa 100644 --- a/xpm/validator/elf_code_segment_info.c +++ b/xpm/validator/elf_code_segment_info.c @@ -225,7 +225,7 @@ static int get_elf64_info(struct elfhdr *elf_ehdr, struct elf_info *elf_info) return 0; } -static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info) +static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info, bool *skip) { uint16_t type; struct elfhdr *elf_ehdr = &elf_info->elf_ehdr; @@ -235,8 +235,11 @@ static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_i if (ret < 0) return ret; - if (memcmp(elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0) - return -ENOEXEC; + if (memcmp(elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0) { + // when the file is not an ELF file, skip checking + *skip = true; + return 0; + } type = elf16_get_value(elf_ehdr, elf_ehdr->e_type); if (type != ET_EXEC && type != ET_DYN) @@ -287,16 +290,52 @@ static int find_elf_code_segment_info(const char *phdr_info, struct elf_info *el return 0; } +static int handle_skip_case(struct file *file, struct exec_file_signature_info **code_segment_info) { + struct exec_file_signature_info *tmp_info = NULL; + if (*code_segment_info == NULL) { + tmp_info = kzalloc(sizeof(struct exec_file_signature_info), GFP_KERNEL); + if (tmp_info == NULL) { + return -ENOMEM; + } + } else { + tmp_info = *code_segment_info; + } + + if (tmp_info->code_segments == NULL) { + tmp_info->code_segments = kzalloc(sizeof(struct exec_segment_info), GFP_KERNEL); + if (tmp_info->code_segments == NULL) { + if (*code_segment_info == NULL) { + kfree(tmp_info); + tmp_info = NULL; + } + return -ENOMEM; + } + tmp_info->code_segment_count = 1; + } + + tmp_info->code_segments[0].file_offset = 0; + tmp_info->code_segments[0].size = file_inode(file)->i_size; + + if (*code_segment_info == NULL) { + *code_segment_info = tmp_info; + } + return 0; +} + int parse_elf_code_segment_info(struct file *file, struct exec_file_signature_info **code_segment_info) { const char *phdr_info; struct elf_info elf_info = {0}; int ret; - - ret = elf_check_and_get_code_segment_offset(file, &elf_info); + bool skip = false; + ret = elf_check_and_get_code_segment_offset(file, &elf_info, &skip); if (ret < 0) return ret; + + if (skip) { + return handle_skip_case(file, code_segment_info); + } phdr_info = kzalloc(elf_info.e_phsize, GFP_KERNEL); if (phdr_info == NULL)