Browse Source

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

fslongjin 2 years ago
parent
commit
b708443d68
1 changed files with 16 additions and 7 deletions
  1. 16 7
      kernel/process/process.c

+ 16 - 7
kernel/process/process.c

@@ -257,16 +257,23 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
         int64_t remain_file_size = phdr->p_filesz;
         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)
         {
             // kdebug("loading...");
             int64_t map_size = 0;
-
-            if (remain_mem_size > PAGE_2M_SIZE / 2)
+            if (remain_mem_size >= PAGE_2M_SIZE)
             {
-
                 uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
                 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);
@@ -275,6 +282,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
                     free_pages(Phy_to_2M_Page(pa), 1);
                 else
                     mm_map_vma(vma, pa);
+                io_mfence();
                 memset((void *)virt_base, 0, 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));
                     else
                         mm_map_vma(vma, paddr);
+                    io_mfence();
                     memset((void *)(virt_base + off), 0, PAGE_4K_SIZE);
                 }
             }
 
             pos = filp->file_ops->lseek(filp, pos, SEEK_SET);
             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;
-                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)
@@ -464,7 +473,7 @@ exec_failed:;
 ul initial_kernel_thread(ul arg)
 {
     // kinfo("initial proc running...\targ:%#018lx", arg);
-    
+
     ahci_init();
     fat32_init();
     rootfs_umount();