乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      為什么我不能在64位內(nèi)核上mmap(MAP_FIXED)32位Linux進(jìn)程中的最高虛擬頁面?

       印度阿三17 2019-06-27

      Linux上嘗試在用戶空間中測試Is it allowed to access memory that spans the zero boundary in x86?時(shí),我寫了一個(gè)32位測試程序,試圖映射32位虛擬地址空間的低頁和高頁.

      回聲0 |后sudo tee / proc / sys / vm / mmap_min_addr,我可以映射零頁面,但我不知道為什么我不能映射-4096,即(void *)0xfffff000,最高頁面.為什么mmap2((void *) – 4096)返回-ENOMEM?

      strace ./a.out 
      execve("./a.out", ["./a.out"], 0x7ffe08827c10 /* 65 vars */) = 0
      strace: [ Process PID=1407 runs in 32 bit mode. ]
      ....
      mmap2(0xfffff000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
      mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0
      

      另外,什么檢查在linux/mm/mmap.c拒絕它,為什么這樣設(shè)計(jì)呢?這是確保創(chuàng)建指向one-past-an-object的指針不是wrap around and break pointer comparisons的一部分,因?yàn)镮SO C和C允許創(chuàng)建指向一個(gè)接一個(gè)的結(jié)尾的指針,但不允許創(chuàng)建指向?qū)ο笾獾闹羔?

      我在64位內(nèi)核(Arch Linux上的4.12.8-2-ARCH)下運(yùn)行,因此32位用戶空間可以提供整個(gè)4GiB. (與64位內(nèi)核上的64位代碼不同,或者與32位內(nèi)核不同,其中2:2或3:1用戶/內(nèi)核拆分會使高頁成為內(nèi)核地址.)

      我沒有試過一個(gè)最小的靜態(tài)可執(zhí)行文件(沒有CRT啟動或libc,只是asm),因?yàn)槲艺J(rèn)為這不會有所作為. CRT啟動系統(tǒng)調(diào)用中沒有一個(gè)看起來可疑.

      在斷點(diǎn)處停止時(shí),我檢查了/ proc / PID / maps.首頁尚未使用.堆棧包括第二高頁面,但首頁未映射.

      00000000-00001000 rw-p 00000000 00:00 0             ### the mmap(0) result
      08048000-08049000 r-xp 00000000 00:15 3120510                 /home/peter/src/SO/a.out
      08049000-0804a000 r--p 00000000 00:15 3120510                 /home/peter/src/SO/a.out
      0804a000-0804b000 rw-p 00001000 00:15 3120510                 /home/peter/src/SO/a.out
      f7d81000-f7f3a000 r-xp 00000000 00:15 1511498                 /usr/lib32/libc-2.25.so
      f7f3a000-f7f3c000 r--p 001b8000 00:15 1511498                 /usr/lib32/libc-2.25.so
      f7f3c000-f7f3d000 rw-p 001ba000 00:15 1511498                 /usr/lib32/libc-2.25.so
      f7f3d000-f7f40000 rw-p 00000000 00:00 0 
      f7f7c000-f7f7e000 rw-p 00000000 00:00 0 
      f7f7e000-f7f81000 r--p 00000000 00:00 0                       [vvar]
      f7f81000-f7f83000 r-xp 00000000 00:00 0                       [vdso]
      f7f83000-f7fa6000 r-xp 00000000 00:15 1511499                 /usr/lib32/ld-2.25.so
      f7fa6000-f7fa7000 r--p 00022000 00:15 1511499                 /usr/lib32/ld-2.25.so
      f7fa7000-f7fa8000 rw-p 00023000 00:15 1511499                 /usr/lib32/ld-2.25.so
      fffdd000-ffffe000 rw-p 00000000 00:00 0                       [stack]
      

      是否有VMA區(qū)域沒有顯示在仍然說服內(nèi)核拒絕該地址的地圖中?我查看了linux / mm / mmapc中ENOMEM的出現(xiàn)次數(shù),但是要閱讀的代碼很多,所以也許我錯過了一些東西.保留一定范圍的高地址,還是因?yàn)樗挥诙褩E赃叺臇|西?

      以其他順序進(jìn)行系統(tǒng)調(diào)用沒有幫助(但是PAGE_ALIGN和類似的宏都是小心寫入的,以避免在屏蔽之前環(huán)繞,所以這不太可能.)

      完整源代碼,使用gcc -O3 -fno-pie -no-pie -m32 address-wrap.c編譯:

      #include <sys/mman.h>
      
      //void *mmap(void *addr, size_t len, int prot, int flags,
      //           int fildes, off_t off);
      
      int main(void) {
          volatile unsigned *high =
              mmap((void*)-4096L, 4096, PROT_READ | PROT_WRITE,
                   MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS,
                   -1, 0);
          volatile unsigned *zeropage =
              mmap((void*)0, 4096, PROT_READ | PROT_WRITE,
                   MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS,
                   -1, 0);
      
      
          return (high == MAP_FAILED) ? 2 : *high;
      }
      

      (我省略了試圖deref(int *) – 2的部分,因?yàn)樗皇窃趍map失敗時(shí)的段錯誤.)

      解決方法:

      mmap函數(shù)最終調(diào)用do_mmapdo_brk_flags來完成滿足內(nèi)存分配請求的實(shí)際工作.這些函數(shù)依次調(diào)用get_unmapped_area.在該函數(shù)中進(jìn)行檢查以確保不能分配超出用戶地址空間限制的內(nèi)存,該限制由TASK_SIZE定義.我引用代碼:

       * There are a few constraints that determine this:
       *
       * On Intel CPUs, if a SYSCALL instruction is at the highest canonical
       * address, then that syscall will enter the kernel with a
       * non-canonical return address, and SYSRET will explode dangerously.
       * We avoid this particular problem by preventing anything executable
       * from being mapped at the maximum canonical address.
       *
       * On AMD CPUs in the Ryzen family, there's a nasty bug in which the
       * CPUs malfunction if they execute code from the highest canonical page.
       * They'll speculate right off the end of the canonical space, and
       * bad things happen.  This is worked around in the same way as the
       * Intel problem.
      
      #define TASK_SIZE_MAX   ((1UL << __VIRTUAL_MASK_SHIFT) - PAGE_SIZE)
      
      #define IA32_PAGE_OFFSET    ((current->personality & ADDR_LIMIT_3GB) ?                     0xc0000000 : 0xFFFFe000)
      
      #define TASK_SIZE       (test_thread_flag(TIF_ADDR32) ? IA32_PAGE_OFFSET : TASK_SIZE_MAX)
      

      在具有48位虛擬地址空間的處理器上,__ VIRTUAL_MASK_SHIFT為47.

      請注意,TASK_SIZE的指定取決于當(dāng)前進(jìn)程是32位32位,64位32位,64位64位.對于32位進(jìn)程,保留兩個(gè)頁面;一個(gè)用于vsyscall page,另一個(gè)用作防護(hù)頁面.實(shí)質(zhì)上,vsyscall頁面無法取消映射,因此用戶地址空間的最高地址實(shí)際上是0xFFFFe000.對于64位進(jìn)程,保留一個(gè)保護(hù)頁面.這些頁面僅保留在64位Intel和AMD處理器上,因?yàn)閮H在這些處理器上使用SYSCALL機(jī)制.

      以下是在get_unmapped_area中執(zhí)行的檢查:

      if (addr > TASK_SIZE - len)
           return -ENOMEM;
      
      來源:https://www./content-3-273251.html

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多