cuidaniu
驱动牛犊
驱动牛犊
  • 注册日期2005-08-22
  • 最后登录2012-05-23
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1370回复:1

MmCreateVirtualMappingUnsafe这个内核函数是否有bug(见我的注释)

楼主#
更多 发布于:2012-05-15 18:28
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);
}
 
 
 
AioliaSky
驱动牛犊
驱动牛犊
  • 注册日期2012-06-14
  • 最后登录2012-10-25
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望141点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2012-06-14 01:46
没有导出的函数,也没有文档
肯定不安全
游客

返回顶部