首页
社区
课程
招聘
[旧帖] MmCreateVirtualMappingUnsafe这个内核函数有bug(见我的注释) 0.00雪花
发表于: 2012-5-15 19:00 3468

[旧帖] MmCreateVirtualMappingUnsafe这个内核函数有bug(见我的注释) 0.00雪花

2012-5-15 19:00
3468
NTSTATUS
NTAPI
MmCreateVirtualMappingUnsafe(PEPROCESS Process,
                             PVOID Address,
                             ULONG flProtect,
                             PPFN_TYPE Pages,
                             ULONG PageCount)
{
   ULONG Attributes;
   PVOID Addr;
   ULONG i;
   ULONG oldPdeOffset, PdeOffset;
   BOOLEAN NoExecute = FALSE;

   DPRINT("MmCreateVirtualMappingUnsafe(%x, %x, %x, %x (%x), %d)\n",
          Process, Address, flProtect, Pages, *Pages, PageCount);

   if (Process == NULL)
   {
      if (Address < MmSystemRangeStart)
      {
         DPRINT1("No process\n");
         KEBUGCHECK(0);
      }
      if (PageCount > 0x10000 ||
      (ULONG_PTR) Address / PAGE_SIZE + PageCount > 0x100000)
      {
         DPRINT1("Page count to large\n");
     KEBUGCHECK(0);
      }
   }
   else
   {
      if (Address >= MmSystemRangeStart)
      {
         DPRINT1("Setting kernel address with process context\n");
         KEBUGCHECK(0);
      }
      if (PageCount > (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE ||
      (ULONG_PTR) Address / PAGE_SIZE + PageCount >
      (ULONG_PTR)MmSystemRangeStart / PAGE_SIZE)
      {
         DPRINT1("Page Count to large\n");
     KEBUGCHECK(0);
      }
   }

   Attributes = ProtectToPTE(flProtect);
   if (Attributes & 0x80000000)
   {
      NoExecute = TRUE;
   }
   Attributes &= 0xfff;
   if (Address >= MmSystemRangeStart)
   {
      Attributes &= ~PA_USER;
      if (Ke386GlobalPagesEnabled)
      {
     Attributes |= PA_GLOBAL;
      }
   }
   else
   {
      Attributes |= PA_USER;
   }

   Addr = Address;
   //上面可看可不看,看下面
   if (Ke386Pae)
   {
       ....//此处是支持Pae情况暂且不考虑      
   }
   else
   {
      PULONG Pt = NULL;
      ULONG Pte;
      oldPdeOffset = ADDR_TO_PDE_OFFSET(Addr) + 1;
      for (i = 0; i < PageCount; i++, Addr = (PVOID)((ULONG_PTR)Addr + PAGE_SIZE))
      {
         if (!(Attributes & PA_PRESENT) && Pages(i)!= 0))//((i)方括号显示不出)这个条件中要是是0号页面就不满足条件不出错误无论在内存标志存在与否
         {
            DPRINT1("Setting physical address but not allowing access at address "
                    "0x%.8X with attributes %x/%x.\n",
                    Addr, Attributes, flProtect);
            KEBUGCHECK(0);
         }
         PdeOffset = ADDR_TO_PDE_OFFSET(Addr);
         if (oldPdeOffset != PdeOffset)
         {
            MmUnmapPageTable(Pt);
        Pt = MmGetPageTableForProcess(Process, Addr, TRUE);
        if (Pt == NULL)
        {
           KEBUGCHECK(0);
        }
         }
         else
         {
            Pt++;
         }
         oldPdeOffset = PdeOffset;

         Pte = *Pt;
         MmMarkPageMapped(Pages(i));//此处如果是0号页面仍然增加mappingcount和refcount吗
         if (PAGE_MASK((Pte)) != 0 && !((Pte) & PA_PRESENT))//此处如果是0号页面就不会错误
         {
            KEBUGCHECK(0);
         }
         if (PAGE_MASK((Pte)) != 0)
         {
            MmMarkPageUnmapped(PTE_TO_PFN((Pte)));//此处如果是0号页面就不会减少
                                                 //mapcount和refcount与上面的Pages(i)的情况是否矛盾
         }
     (void)InterlockedExchangeUL(Pt, PFN_TO_PTE(Pages(i)) | Attributes);//0号页面可以被替换映射或者替换已有映射吗
         if (Address < MmSystemRangeStart &&
         ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable != NULL &&
             Attributes & PA_PRESENT)
         {
            PUSHORT Ptrc;

            Ptrc = ((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;

            Ptrc[ADDR_TO_PAGE_TABLE(Addr)]++;
         }
         //上面这个if语句块貌似没有我写的下面这个(/*...*/)注释括起来的if语句块合理些
  /*if((Address<MmSystemRangeStart)&&(((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable!=NULL))
      {
          PUSHORT ptrc=((PMADDRESS_SPACE)&Process->VadRoot)->PageTableRefCountTable;
         if((Attributes&PA_PRESENT)&&(!(pte & PA_PRESENT)))
         {
            ptrc[ADDR_TO_PAGE_TABLE(Addr)]++;
         }
        else if((!(Attributes&PA_PRESENT))&&(pte & PA_PRESENT))
        {
           ptrc[ADDR_TO_PAGE_TABLE(Addr)]--;
        }
    }//貌似上面我写的这个比原来的合理些*/
         if (Pte != 0)
         {
            if (Address > MmSystemRangeStart ||
                (Pt >= (PULONG)PAGETABLE_MAP && Pt < (PULONG)PAGETABLE_MAP + 1024*1024))
            {
               MiFlushTlb(Pt, Address);//还有这儿,如何失效别的进程的用户空间地址的块表中
                             //相应的页面映射表项呢
            }
         }
      }
      if (Addr > Address)
      {
         MmUnmapPageTable(Pt);
      }
   }
   return(STATUS_SUCCESS);
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 384
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
mark...
2012-5-15 22:23
0
游客
登录 | 注册 方可回帖
返回
//