fix: 规范告警清零

Close #I7GNQH

Signed-off-by: zhushengle <zhushengle@huawei.com>
Change-Id: I985717fda8845c311fe2cbbacf10cf7b513112d8
This commit is contained in:
zhushengle
2023-06-28 11:47:04 +08:00
parent 829014ab7c
commit 6b8ff51ead
2 changed files with 115 additions and 80 deletions
+55 -41
View File
@@ -171,16 +171,63 @@ static int get_elf64_code_segment(struct elf64_phdr *elf_phdr, struct elf_info *
return 0;
}
static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info)
static int get_elf32_info(struct elfhdr *elf_ehdr, struct elf_info *elf_info)
{
struct elf32_hdr *elf32_ehdr;
struct elf64_hdr *elf64_ehdr;
uint32_t e32_phoff;
uint32_t e32_phsize;
uint16_t e_ehsize;
elf_info->type = ELFCLASS32;
elf32_ehdr = (struct elf32_hdr *)elf_ehdr;
e_ehsize = elf16_get_value(elf_ehdr, elf32_ehdr->e_ehsize);
if (e_ehsize != sizeof(struct elf32_hdr))
return -ENOEXEC;
elf_info->e_phnum = elf16_get_value(elf_ehdr, elf32_ehdr->e_phnum);
e32_phsize = sizeof(struct elf32_phdr) * elf_info->e_phnum;
if (e32_phsize == 0 || e32_phsize > ELF_PHNUM_MAX_SIZE)
return -ENOEXEC;
e32_phoff = elf32_get_value(elf_ehdr, elf32_ehdr->e_phoff);
if (e32_phoff + e32_phsize < e32_phoff)
return -ENOEXEC;
elf_info->e_phsize = e32_phsize;
elf_info->e_phoff = e32_phoff;
return 0;
}
static int get_elf64_info(struct elfhdr *elf_ehdr, struct elf_info *elf_info)
{
struct elf64_hdr *elf64_ehdr;
uint64_t e64_phoff;
uint64_t e64_phsize;
uint16_t type;
uint16_t e_ehsize;
elf_info->type = ELFCLASS64;
elf64_ehdr = (struct elf64_hdr *)elf_ehdr;
e_ehsize = elf16_get_value(elf_ehdr, elf64_ehdr->e_ehsize);
if (e_ehsize != sizeof(struct elf64_hdr))
return -ENOEXEC;
elf_info->e_phnum = elf16_get_value(elf_ehdr, elf64_ehdr->e_phnum);
e64_phsize = sizeof(struct elf64_phdr) * elf_info->e_phnum;
if (e64_phsize == 0 || e64_phsize > ELF_PHNUM_MAX_SIZE)
return -ENOEXEC;
e64_phoff = elf64_get_value(elf_ehdr, elf64_ehdr->e_phoff);
if (e64_phoff + e64_phsize < e64_phoff)
return -ENOEXEC;
elf_info->e_phsize = e64_phsize;
elf_info->e_phoff = e64_phoff;
return 0;
}
static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info)
{
uint16_t type;
struct elfhdr *elf_ehdr = &elf_info->elf_ehdr;
int ret;
@@ -195,46 +242,13 @@ static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_i
if (type != ET_EXEC && type != ET_DYN)
return -ENOEXEC;
if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS32) {
elf_info->type = ELFCLASS32;
elf32_ehdr = (struct elf32_hdr *)elf_ehdr;
e_ehsize = elf16_get_value(elf_ehdr, elf32_ehdr->e_ehsize);
if (e_ehsize != sizeof(struct elf32_hdr))
return -ENOEXEC;
if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS32)
return get_elf32_info(elf_ehdr, elf_info);
elf_info->e_phnum = elf16_get_value(elf_ehdr, elf32_ehdr->e_phnum);
e32_phsize = sizeof(struct elf32_phdr) * elf_info->e_phnum;
if (e32_phsize == 0 || e32_phsize > ELF_PHNUM_MAX_SIZE)
return -ENOEXEC;
if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS64)
return get_elf64_info(elf_ehdr, elf_info);
e32_phoff = elf32_get_value(elf_ehdr, elf32_ehdr->e_phoff);
if (e32_phoff + e32_phsize < e32_phoff)
return -ENOEXEC;
elf_info->e_phsize = e32_phsize;
elf_info->e_phoff = e32_phoff;
} else if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS64) {
elf_info->type = ELFCLASS64;
elf64_ehdr = (struct elf64_hdr *)elf_ehdr;
e_ehsize = elf16_get_value(elf_ehdr, elf64_ehdr->e_ehsize);
if (e_ehsize != sizeof(struct elf64_hdr))
return -ENOEXEC;
elf_info->e_phnum = elf16_get_value(elf_ehdr, elf64_ehdr->e_phnum);
e64_phsize = sizeof(struct elf64_phdr) * elf_info->e_phnum;
if (e64_phsize == 0 || e64_phsize > ELF_PHNUM_MAX_SIZE)
return -ENOEXEC;
e64_phoff = elf64_get_value(elf_ehdr, elf64_ehdr->e_phoff);
if (e64_phoff + e64_phsize < e64_phoff)
return -ENOEXEC;
elf_info->e_phsize = e64_phsize;
elf_info->e_phoff = e64_phoff;
} else
return -ENOEXEC;
return 0;
return -ENOEXEC;
}
static int find_elf_code_segment_info(const char *phdr_info, struct elf_info *elf_info,
+60 -39
View File
@@ -21,6 +21,12 @@ static DEFINE_RWLOCK(fs_verity_tree_lock);
static struct rb_root fs_verity_tree = RB_ROOT;
static int fs_verity_node_count;
struct verity_info {
struct rb_root *root;
rwlock_t *lock;
int *node_count;
};
static int check_exec_file_is_verity(struct file *file)
{
return FILE_SIGNATURE_DM_VERITY;
@@ -164,10 +170,9 @@ static void test_print_elf_code_segment_info(struct file *file, const struct exe
if (IS_ERR(ret_path))
return;
for (i = 0; i < file_info->code_segment_count; i++) {
for (i = 0; i < file_info->code_segment_count; i++)
pr_info("[exec signature segment] %s -> offset: 0x%llx size: 0x%lx\n",
ret_path, file_info->code_segments->file_offset, file_info->code_segments->size);
}
code_segment_test_count = 100;
}
@@ -194,41 +199,71 @@ static void rm_code_segment_info(void)
write_unlock(&fs_verity_tree_lock);
}
static int get_verity_info(int type, struct verity_info *verity)
{
if (type == FILE_SIGNATURE_DM_VERITY) {
verity->root = &dm_verity_tree;
verity->lock = &dm_verity_tree_lock;
verity->node_count = &dm_verity_node_count;
return 0;
}
if (type == FILE_SIGNATURE_FS_VERITY) {
verity->lock = &fs_verity_tree_lock;
verity->root = &fs_verity_tree;
verity->node_count = &fs_verity_node_count;
return 0;
}
return -EINVAL;
}
static void insert_new_signature_info(struct inode *file_node, int type,
struct verity_info *verity, struct exec_file_signature_info *new_info, struct exec_file_signature_info **old_info)
{
new_info->type = type;
new_info->inode = (uintptr_t)file_node;
RB_CLEAR_NODE(&new_info->rb_node);
if ((*old_info) != NULL) {
write_lock(verity->lock);
rb_erase_node(verity->root, verity->node_count, *old_info);
(*old_info)->type |= FILE_SIGNATURE_DELETE;
write_unlock(verity->lock);
if (atomic_sub_return(1, &(*old_info)->reference) <= 0) {
kfree(*old_info);
*old_info = NULL;
}
}
write_lock(verity->lock);
*old_info = rb_add_node(verity->root, verity->node_count, new_info);
write_unlock(verity->lock);
}
static int get_elf_code_segment_info(struct file *file, bool is_exec, int type,
struct exec_file_signature_info **code_segment_info)
{
int ret;
struct rb_root *root;
rwlock_t *verity_lock;
int *node_count;
struct verity_info verity;
struct inode *file_node;
struct exec_file_signature_info *new_info;
struct exec_file_signature_info *tmp_info;
struct exec_file_signature_info *old_info;
if (type == FILE_SIGNATURE_DM_VERITY) {
root = &dm_verity_tree;
verity_lock = &dm_verity_tree_lock;
node_count = &dm_verity_node_count;
} else if (type == FILE_SIGNATURE_FS_VERITY) {
verity_lock = &fs_verity_tree_lock;
root = &fs_verity_tree;
node_count = &fs_verity_node_count;
} else {
if (get_verity_info(type, &verity) < 0)
return -EINVAL;
}
file_node = file_inode(file);
if (file_node == NULL)
return -EINVAL;
read_lock(verity_lock);
tmp_info = rb_search_node(root, (uintptr_t)file_node);
read_unlock(verity_lock);
if (tmp_info != NULL) {
if (is_exec && tmp_info->code_segments == NULL)
read_lock(verity.lock);
old_info = rb_search_node(verity.root, (uintptr_t)file_node);
read_unlock(verity.lock);
if (old_info != NULL) {
if (is_exec && old_info->code_segments == NULL)
goto need_parse;
*code_segment_info = tmp_info;
*code_segment_info = old_info;
return 0;
}
@@ -248,24 +283,10 @@ need_parse:
#endif
}
new_info->type = type;
new_info->inode = (uintptr_t)file_node;
RB_CLEAR_NODE(&new_info->rb_node);
if (tmp_info != NULL) {
write_lock(verity_lock);
rb_erase_node(root, node_count, tmp_info);
tmp_info->type |= FILE_SIGNATURE_DELETE;
write_unlock(verity_lock);
if (atomic_sub_return(1, &tmp_info->reference) <= 0)
kfree(tmp_info);
}
write_lock(verity_lock);
tmp_info = rb_add_node(root, node_count, new_info);
write_unlock(verity_lock);
if (tmp_info != NULL) {
insert_new_signature_info(file_node, type, &verity, new_info, &old_info);
if (old_info != NULL) {
kfree(new_info);
new_info = tmp_info;
new_info = old_info;
}
*code_segment_info = new_info;
return 0;