bugfix: 解决了为应用程序映射elf的过程中,由于地址未对齐而导致的可能的内存越界问题

This commit is contained in:
fslongjin 2022-09-16 21:40:18 +08:00
parent 2d1af61813
commit b708443d68

View File

@ -257,16 +257,23 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
int64_t remain_file_size = phdr->p_filesz; int64_t remain_file_size = phdr->p_filesz;
pos = phdr->p_offset; pos = phdr->p_offset;
uint64_t virt_base = phdr->p_vaddr; uint64_t virt_base = 0;
uint64_t beginning_offset = 0; // 由于页表映射导致的virtbase与实际的p_vaddr之间的偏移量
if (remain_mem_size >= PAGE_2M_SIZE) // 接下来存在映射2M页的情况因此将vaddr按2M向下对齐
virt_base = phdr->p_vaddr & PAGE_2M_MASK;
else // 接下来只有4K页的映射
virt_base = phdr->p_vaddr & PAGE_4K_MASK;
beginning_offset = phdr->p_vaddr - virt_base;
remain_mem_size += beginning_offset;
while (remain_mem_size > 0) while (remain_mem_size > 0)
{ {
// kdebug("loading..."); // kdebug("loading...");
int64_t map_size = 0; int64_t map_size = 0;
if (remain_mem_size >= PAGE_2M_SIZE)
if (remain_mem_size > PAGE_2M_SIZE / 2)
{ {
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
struct vm_area_struct *vma = NULL; struct vm_area_struct *vma = NULL;
int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma);
@ -275,6 +282,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
free_pages(Phy_to_2M_Page(pa), 1); free_pages(Phy_to_2M_Page(pa), 1);
else else
mm_map_vma(vma, pa); mm_map_vma(vma, pa);
io_mfence();
memset((void *)virt_base, 0, PAGE_2M_SIZE); memset((void *)virt_base, 0, PAGE_2M_SIZE);
map_size = PAGE_2M_SIZE; map_size = PAGE_2M_SIZE;
} }
@ -293,16 +301,17 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
kfree(phys_2_virt(paddr)); kfree(phys_2_virt(paddr));
else else
mm_map_vma(vma, paddr); mm_map_vma(vma, paddr);
io_mfence();
memset((void *)(virt_base + off), 0, PAGE_4K_SIZE); memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
} }
} }
pos = filp->file_ops->lseek(filp, pos, SEEK_SET); pos = filp->file_ops->lseek(filp, pos, SEEK_SET);
int64_t val = 0; int64_t val = 0;
if (remain_file_size != 0) if (remain_file_size > 0)
{ {
int64_t to_trans = (remain_file_size > PAGE_2M_SIZE) ? PAGE_2M_SIZE : remain_file_size; int64_t to_trans = (remain_file_size > PAGE_2M_SIZE) ? PAGE_2M_SIZE : remain_file_size;
val = filp->file_ops->read(filp, (char *)virt_base, to_trans, &pos); val = filp->file_ops->read(filp, (char *)(virt_base + beginning_offset), to_trans, &pos);
} }
if (val < 0) if (val < 0)