ç§ã¯ã©ããããããã1 MBã®å©çšå¯èœãªã¡ã¢ãªã§100äžã®æŽæ°ããœãŒãããã¿ã¹ã¯ã«åãçµãããšã«ããŸããã ãããããã®åã«ãããã°ã©ã ã§äœ¿çšå¯èœãªã¡ã¢ãªã®éãå¶éããæ¹æ³ãèããªããã°ãªããŸããã§ããã ãããç§ãæãã€ãããã®ã§ãã
ããã»ã¹ä»®æ³ã¡ã¢ãª
ã¡ã¢ãªãå¶éããããŸããŸãªæ¹æ³ã«çªå
¥ããåã«ãããã»ã¹ã®ä»®æ³ã¡ã¢ãªãã©ã®ããã«æ©èœããããç¥ãå¿
èŠããããŸãã ãã®ãããã¯ã«é¢ããæè¯ã®èšäºã¯ã
ãã¡ã¢ãªå
ã®ããã°ã©ã ã®æ§é ãã§ãã
ãã®èšäºãèªãã åŸãã¡ã¢ãªãå¶éããããã®2ã€ã®ãªãã·ã§ã³ãæäŸã§ããŸããä»®æ³ã¢ãã¬ã¹ã¹ããŒã¹ãåæžããããããŒãããªã¥ãŒã ãåæžããŸãã
æåïŒã¢ãã¬ã¹ç©ºéã®éãæžããã ããã¯éåžžã«åçŽã§ãããå®å
šã«æ£ããããã§ã¯ãããŸããã ãã¹ãŠã®ã¹ããŒã¹ã1 MBã«æžããããšã¯ã§ããŸãã-ã«ãŒãã«ãšã©ã€ãã©ãªãŒã«ååãªã¹ããŒã¹ããããŸããã
2çªç®ïŒããŒãã®ããªã¥ãŒã ãæžãããŸãã ããã¯ããã»ã©ç°¡åã§ã¯ãªããéåžžã¯èª°ãè¡ããŸãããããã¯ããªã³ã«ã䜿çšãã倧éšããéããŠããå©çšã§ããªãããã§ãã ããããç§ãã¡ã®ã¿ã¹ã¯ã«ãšã£ãŠãããã¯ããé©åãªãªãã·ã§ã³ã§ãã
ãŸããã©ã€ãã©ãªããã³ã·ã¹ãã ã³ãŒã«ãã€ã³ã¿ãŒã»ããããŠã¡ã¢ãªäœ¿çšéã远跡ãããããµã³ãããã¯ã¹ããšãã¥ã¬ãŒãããã³å°å
¥ããŠããã°ã©ã ç°å¢ãå€æŽãããªã©ãä»ã®æ¹æ³ãæ€èšããŸãã
ãã¹ãã®ããã«ãbig_allocãšåŒã°ããå°ããªããã°ã©ã ã䜿çšããŸãããã®ããã°ã©ã ã¯ã100 MiBãé
眮ããŠãããªãªãŒã¹ããŸãã
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // 1000 100 KiB = 100 000 KiB = 100 MiB #define NALLOCS 1000 #define ALLOC_SIZE 1024*100 // 100 KiB int main(int argc, const char *argv[]) { int i = 0; int **pp; bool failed = false; pp = malloc(NALLOCS * sizeof(int *)); for(i = 0; i < NALLOCS; i++) { pp[i] = malloc(ALLOC_SIZE); if (!pp[i]) { perror("malloc"); printf(" %d \n", i); failed = true; break; } // , copy-on-write. memset(pp[i], 0xA, 100); printf("pp[%d] = %p\n", i, pp[i]); } if (!failed) printf(" %d \n", NALLOCS * ALLOC_SIZE); for(i = 0; i < NALLOCS; i++) { if (pp[i]) free(pp[i]); } free(pp); return 0; }
ãã¹ãŠã®ãœãŒã¹ã¯
githubã«ãããŸãã
éç
å€ãUNIXããã«ãŒã¯ãã¡ã¢ãªãå¶éããå¿
èŠããããšãã«ããã«æãåºããŸãã ããã¯ãããã°ã©ã ã®ãªãœãŒã¹ãå¶éã§ããbashã®ãŠãŒãã£ãªãã£ã§ãã å®éãããã¯setrlimitãžã®ã€ã³ã¿ãŒãã§ãŒã¹ã§ãã
ããã°ã©ã ã®ã¡ã¢ãªéã«å¶éãèšå®ã§ããŸãã
$ ulimit -m 1024
ç§ãã¡ã¯ãã§ãã¯ããŸãïŒ
$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7802 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) 1024 open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 1024 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
1024 kb-1 MiBã®å¶éãèšå®ããŸããã ããããããã°ã©ã ãå®è¡ããããšãããšããšã©ãŒãªãã§æ©èœããŸãã 1024 kbã®å¶éã«ãããããããããã°ã©ã ã4872 kbã»ã©ãããããšã¯æããã§ãã
ãã®çç±ã¯ãLinuxãå³ããå¶éãèšå®ããŠããªãããã§ãç·ã¯æ¬¡ã®ããã«è¿°ã¹ãŠããŸã
ulimit [-HSTabcdefilmnpqrstuvx [limit]] ... -m The maximum resident set size (many systems do not honor this limit)
ulimit -dãªãã·ã§ã³ããããŸããããã
ã¯æ©èœãã
ã¯ãã§ãããmmapãåå ã§æ©èœããŸããïŒãªã³ã«ãŒã®ã»ã¯ã·ã§ã³ãåç
§ïŒã
QEMU
ãœãããŠã§ã¢ç°å¢ãæäœããã«ã¯ãQEMUãæé©ã§ãã ä»®æ³ã¢ãã¬ã¹ç©ºéãå¶éããããã®âRãªãã·ã§ã³ããããŸãã ããããå°ããããå€ã«å¶éããããšã¯ã§ããŸãã-libcãšã«ãŒãã«ã¯é©åããŸããã
èŠãŠïŒ
$ qemu-i386 -R 1048576 ./big_alloc big_alloc: error while loading shared libraries: libc.so.6: failed to map segment from shared object: Cannot allocate memory
ããã§ã-R 1048576ã¯ãä»®æ³ã¢ãã¬ã¹ã¹ããŒã¹ããšã«1 MiBãæ®ããŸãã
ãã®ããã«ã¯ã20 MBã®ãªãŒããŒãåãå¿
èŠããããŸãã ããã«ïŒ
$ qemu-i386 -R 20M ./big_alloc malloc: Cannot allocate memory Failed after 100 allocations
100åã®å埩ïŒ10 MBïŒåŸã«åæ¢ããŸãã
äžè¬çã«ãQEMUã¯äŸç¶ãšããŠå¶éæ¹æ³ã®ãªãŒããŒã§ããã-Rå€ããããã ãã§ååã§ãã
ã³ã³ãã
å¥ã®ãªãã·ã§ã³ã¯ãã³ã³ããã§ããã°ã©ã ãå®è¡ãããªãœãŒã¹ãå¶éããããšã§ãã ãããè¡ãã«ã¯ã次ã®ããšãã§ããŸãã
- ããã€ãã®ããã«ãŒã䜿çšãã
- lxcããã±ãŒãžã®ãŠãŒã¶ãŒã¢ãŒãããŒã«ã䜿çšãã
- libvirtã䜿çšããŠã¹ã¯ãªãããèšè¿°ããŸãã
- ä»ã®äœã...
ãã ããcgroupsãšããLinuxãµãã·ã¹ãã ã䜿çšãããšããªãœãŒã¹ãå¶éãããŸãã çŽæ¥ãã¬ã€ããããšãã§ããŸãããlxcã䜿çšããããšããå§ãããŸãã dockerã䜿çšãããã®ã§ããã64ããããã·ã³ã§ã®ã¿æ©èœããŸãã
LXCã¯LinuXã³ã³ããã§ãã ããã¯ãã«ãŒãã«æ©èœã管çããã³ã³ãããäœæããããã®ãŠãŒã¶ãŒã¹ããŒã¹ã®ããŒã«ãšã©ã€ãã©ãªã®ã»ããã§ã-ã¢ããªã±ãŒã·ã§ã³ãŸãã¯ã·ã¹ãã å
šäœã®åé¢ãããå®å
šãªç°å¢ã
ã«ãŒãã«é¢æ°ã¯æ¬¡ã®ãšããã§ãã
- å¶åŸ¡ã°ã«ãŒãïŒcgroupsïŒ
- ã«ãŒãã«åå空é
- chroot
- ã«ãŒãã«æ©èœ
- SELinuxãAppArmor
- Seccompããªã·ãŒ
ããã¥ã¡ã³ãã¯ã
ãªããµã€ããŸãã¯
èè
ã®ããã°ã§èŠã€ããããšãã§ããŸãã
ã³ã³ããã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããã«ã¯ãlxc-execute configãæäŸããå¿
èŠããããŸããããã§ãã³ã³ããã®ãã¹ãŠã®èšå®ãæå®ããŸãã / usr / share / doc / lxc / examplesã®ãµã³ãã«ããéå§ã§ããŸãã ç·ã¯lxc-macvlan.confããå§ããããšããå§ãããŸãã å§ããŸãããïŒ
ããŸãããïŒ
cgroupã§ã¡ã¢ãªãå¶éããŸãããã LXCã§ã¯ãã¡ã¢ãªå¶éãèšå®ããããšã«ãããcgroupã³ã³ããã®ã¡ã¢ãªãµãã·ã¹ãã ãæ§æã§ããŸãã ãã©ã¡ãŒã¿ã¯
RedHatã®ããã¥ã¡ã³ãã«èšèŒãããŠã
ãŸã ã ç§ãèŠã€ãã2ïŒ
- memory.limit_in_bytes-ãã¡ã€ã«ãã£ãã·ã¥ãå«ããŠãŒã¶ãŒã¡ã¢ãªã®æ倧éãèšå®ããŸã
- memory.memsw.limit_in_bytes-ã¡ã¢ãªãŒãšã¹ã¯ããã®åèšã®æ倧éãèšå®ããŸã
lxc-my.confã«è¿œå ãããã®ïŒ
lxc.cgroup.memory.limit_in_bytes = 2M lxc.cgroup.memory.memsw.limit_in_bytes = 2M
以äžãéå§ããŸãã
æ²é»-ã©ããããèšæ¶ãå°ãªãããã ã·ã§ã«ããå®è¡ããŠã¿ãŸããã
bashã¯èµ·åããŸããã§ããã / bin / shãè©ŠããŠã¿ãŸãããïŒ
ãããŠãdmesgã§ã¯ãããã»ã¹ã®èŒãããæ»ã远跡ã§ããŸãã
[15447.035569] big_alloc invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=0 ... [15447.035779] Task in /lxc/foo [15447.035785] killed as a result of limit of [15447.035789] /lxc/foo [15447.035795] memory: usage 3072kB, limit 3072kB, failcnt 127 [15447.035800] memory+swap: usage 3072kB, limit 3072kB, failcnt 0 [15447.035805] kmem: usage 0kB, limit 18014398509481983kB, failcnt 0 [15447.035808] Memory cgroup stats for /lxc/foo: cache:32KB rss:3040KB rss_huge:0KB mapped_file:0KB writeback:0KB swap:0KB inactive_anon:1588KB active_anon:1448KB inactive_file:16KB active_file:16KB unevictable:0KB [15447.035836] [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name [15447.035963] [ 9225] 0 9225 942 308 10 0 0 init.lxc [15447.035971] [ 9228] 0 9228 833 698 6 0 0 sh [15447.035978] [ 9252] 0 9252 16106 843 36 0 0 big_alloc [15447.035983] Memory cgroup out of memory: Kill process 9252 (big_alloc) score 1110 or sacrifice child [15447.035990] Killed process 9252 (big_alloc) total-vm:64424kB, anon-rss:2396kB, file-rss:976kB
big_allocããmallocã®å€±æãšäœ¿çšå¯èœãªã¡ã¢ãªã®éã«é¢ãããšã©ãŒã¡ãã»ãŒãžã¯åä¿¡ããŸããã§ããããã³ã³ããã䜿çšããŠã¡ã¢ãªãå¶éããããšã«æåããããã§ãã ä»ã®ãšãããããã«ã€ããŠè©³ããèŠãŠãããŸããã
ãªã³ã«ãŒ
ãã€ããªã€ã¡ãŒãžãå€æŽããŠã䜿çšå¯èœãªããŒãã¹ããŒã¹ãå¶éããŠã¿ãŸãããã ã¬ã€ã¢ãŠãã¯ãããã°ã©ã ãæ§ç¯ããæåŸã®ã¹ãããã§ãã ãã®ããã«ããªã³ã«ãŒãšãã®ã¹ã¯ãªããã䜿çšãããŸãã ã¹ã¯ãªããã¯ãã¡ã¢ãªå
ã®ããã°ã©ã ã»ã¯ã·ã§ã³ã®èª¬æã§ãããããããçš®é¡ã®å±æ§ããã®ä»ã®ãã®ã§ãã
ãã«ãã¹ã¯ãªããã®äŸïŒ
ENTRY(main) SECTIONS { . = 0x10000; .text : { *(.text) } . = 0x8000000; .data : { *(.data) } .bss : { *(.bss) } }
ãããã¯çŸåšã®äœçœ®ã瀺ããŸãã ããšãã°ã.textã»ã¯ã·ã§ã³ã¯0Ã10000ã§å§ãŸãã次ã«0Ã8000000ã§å§ãŸã次ã®2ã€ã®ã»ã¯ã·ã§ã³ããããŸãïŒ.dataãš.bssã ãšã³ããªãã€ã³ããã¡ã€ã³ã§ãã
ãã¹ãŠãã¯ãŒã«ã§ãããå®éã®ããã°ã©ã ã§ã¯æ©èœããŸããã Cããã°ã©ã ã§èšè¿°ããäž»ãªé¢æ°ã¯ãå®éã«åŒã³åºãããæåã®é¢æ°ã§ã¯ãããŸããã æåã«ãå€ãã®åæåãšæ¶å»ãè¡ãããŸãã ãã®ã³ãŒãã¯Cã©ã³ã¿ã€ã ã©ã€ãã©ãªïŒcrtïŒã«å«ãŸããŠããã/ usr / libã®crtïŒ.oã©ã€ãã©ãªã«é
åžãããŸãã
詳现ã¯ãgcc âvãå®è¡ããŠç¢ºèªã§ããŸãã æåã«ãcclãåŒã³åºããã¢ã»ã³ãã©ã³ãŒããäœæããasãä»ããŠãªããžã§ã¯ããã¡ã€ã«ã«å€æããæåŸã«collect2ã䜿çšããŠELFãšãšãã«ãã¹ãŠãåéããŸãã collect2-ldã©ãããŒã ãªããžã§ã¯ããã¡ã€ã«ãš5ã€ã®è¿œå ã©ã€ãã©ãªãåãå
¥ããŠãæçµçãªãã€ããªã€ã¡ãŒãžãäœæããŸãã
/usr/lib/gcc/i686-redhat-linux/4.8.3/./././crt1.o /usr/lib/gcc/i686-redhat-linux/4.8.3/./././crti.o /usr/lib/gcc/i686-redhat-linux/4.8.3/crtbegin.o /tmp/ccEZwSgF.o <- /usr/lib/gcc/i686-redhat-linux/4.8.3/crtend.o /usr/lib/gcc/i686-redhat-linux/4.8.3/./././crtn.o
ãããã¯ãã¹ãŠéåžžã«è€éãªãããç¬èªã®ã¹ã¯ãªãããäœæãã代ããã«ãããã©ã«ãã®ãªã³ã«ãŒã¹ã¯ãªãããç·šéããŸãã -Wlã-verboseãgccã«æž¡ããŠååŸããŸãã
gcc big_alloc.c -o big_alloc -Wl,-verbose
次ã«ããããå€æŽããæ¹æ³ã«ã€ããŠèããŠã¿ãŸãããã ããã©ã«ãã§ãã€ããªãã©ã®ããã«æ§ç¯ãããããèŠãŠã¿ãŸãããã ã³ã³ãã€ã«ãã.dataã»ã¯ã·ã§ã³ã®ã¢ãã¬ã¹ãæ¢ããŸãã objdump -h big_allocã®åºåã¯æ¬¡ã®ãšããã§ãã
Sections: Idx Name Size VMA LMA File off Algn ... 12 .text 000002e4 080483e0 080483e0 000003e0 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE ... 23 .data 00000004 0804a028 0804a028 00001028 2**2 CONTENTS, ALLOC, LOAD, DATA 24 .bss 00000004 0804a02c 0804a02c 0000102c 2**2 ALLOC
.textã.dataãããã³.bssã»ã¯ã·ã§ã³ã¯ãçŽ128 MiBã«ãããŸãã
gdbã§ã¹ã¿ãã¯ãã©ãã«ãããèŠãŠã¿ãŸãããïŒ
[restrict-memory]$ gdb big_alloc ... Reading symbols from big_alloc...done. (gdb) break main Breakpoint 1 at 0x80484fa: file big_alloc.c, line 12. (gdb) r Starting program: /home/avd/dev/restrict-memory/big_alloc Breakpoint 1, main (argc=1, argv=0xbffff164) at big_alloc.c:12 12 int i = 0; Missing separate debuginfos, use: debuginfo-install glibc-2.18-16.fc20.i686 (gdb) info registers eax 0x1 1 ecx 0x9a8fc98f -1701852785 edx 0xbffff0f4 -1073745676 ebx 0x42427000 1111650304 esp 0xbffff0a0 0xbffff0a0 ebp 0xbffff0c8 0xbffff0c8 esi 0x0 0 edi 0x0 0 eip 0x80484fa 0x80484fa <main+10> eflags 0x286 [ PF SF IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
espã¯0xbffff0a0ãæããŸããããã¯çŽ3 GiBã§ãã ãããã£ãŠãçŽ2.9 GiBã®æããããŸãã
çŸå®ã®äžçã§ã¯ãã¹ã¿ãã¯ã®æäžäœã¢ãã¬ã¹ã¯ã©ã³ãã ã§ãããããšãã°åºåã§èŠãããšãã§ããŸãïŒ
ç¥ã£ãŠããããã«ãããŒãã¯.dataã®æåŸããã¹ã¿ãã¯ã«åãã£ãŠå¢å ããŸãã .dataã»ã¯ã·ã§ã³ãã§ããã ãé«ã移åãããšã©ããªããŸããïŒ
ã¹ã¿ãã¯ã®åã®2 MiBã«ããŒã¿ã»ã°ã¡ã³ããé
眮ããŸãããã ã¹ã¿ãã¯ã®ããããåãã2 MiBãåŒããŸãïŒ
0xbffff0a0-0x200000 = 0xbfdff0a0
.dataã§å§ãŸããã¹ãŠã®ã»ã¯ã·ã§ã³ã次ã®ã¢ãã¬ã¹ã«ã·ããããŸãã
. = 0xbfdff0a0 .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) }
ã³ã³ãã€ã«ããŸãïŒ
$ gcc big_alloc.c -o big_alloc -Wl,-T hack.lst
-Wlããã³-T hack.lstãªãã·ã§ã³ã¯ãhack.lstãã¹ã¯ãªãããšããŠäœ¿çšãããããªã³ã«ãŒã«æ瀺ããŸãã
ã¿ã€ãã«ãèŠãŠã¿ãŸãããïŒ
: Idx Name Size VMA LMA File off Algn ... 23 .data 00000004 bfdff0a0 bfdff0a0 000010a0 2**2 CONTENTS, ALLOC, LOAD, DATA 24 .bss 00000004 bfdff0a4 bfdff0a4 000010a4 2**2 ALLOC
ããã§ããããŒã¿ã¯ã¡ã¢ãªã«ä¿åãããŸãã ã©ããã£ãŠïŒ mallocã«ãã£ãŠè¿ããããã€ã³ã¿ãŒã®å€ã確èªããããšãããšãé
眮ã¯.dataã»ã¯ã·ã§ã³ã®çµãããã0xbf8b7000ã®ãããªã¢ãã¬ã¹ã§å§ãŸããåŸã
ã«ãã€ã³ã¿ãŒãå¢ãããŠããããã®åŸ0xb5e76000ã®ãããªäœãã¢ãã¬ã¹ã«æ»ããŸãã æãæé·ããŠããããã«èŠããŸãã
èããŠã¿ãã°ãäœãå€ãªããšã¯ãããŸããã glibcã®ãœãŒã¹ã確èªãããšãããbrkã倱æãããšmmapã䜿çšãããããšãããããŸããã ãã®ãããglibcã¯ã«ãŒãã«ã«ããŒãžãé
眮ããããã«èŠæ±ããã«ãŒãã«ã¯ããã»ã¹ã«ä»®æ³ã¡ã¢ãªã«å€§éã®ç©Žãããããšã確èªãã空ã®å Žæã®1ã€ã«ããŒãžãé
眮ããŸãã
straceã§big_allocãå®è¡ãããšãçè«ã確èªãããŸããã éåžžã®ãã€ããªãèŠãŠãã ããïŒ
brk(0) = 0x8135000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77df000 mmap2(NULL, 95800, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c7000 mmap2(0x4226d000, 1825436, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x4226d000 mmap2(0x42425000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b8000) = 0x42425000 mmap2(0x42428000, 10908, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42428000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77c6000 mprotect(0x42425000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0x42269000, 4096, PROT_READ) = 0 munmap(0xb77c7000, 95800) = 0 brk(0) = 0x8135000 brk(0x8156000) = 0x8156000 brk(0) = 0x8156000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77de000 brk(0) = 0x8156000 brk(0x8188000) = 0x8188000 brk(0) = 0x8188000 brk(0x81ba000) = 0x81ba000 brk(0) = 0x81ba000 brk(0x81ec000) = 0x81ec000 ... brk(0) = 0x9c19000 brk(0x9c4b000) = 0x9c4b000 brk(0) = 0x9c4b000 brk(0x9c7d000) = 0x9c7d000 brk(0) = 0x9c7d000 brk(0x9caf000) = 0x9caf000 ... brk(0) = 0xe29c000 brk(0xe2ce000) = 0xe2ce000 brk(0) = 0xe2ce000 brk(0xe300000) = 0xe300000 brk(0) = 0xe300000 brk(0) = 0xe300000 brk(0x8156000) = 0x8156000 brk(0) = 0x8156000 +++ exited with 0 +++
ãããŠä»ãå€æŽããããã®ã®ããã«ïŒ
brk(0) = 0xbf896000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb778f000 mmap2(NULL, 95800, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7777000 mmap2(0x4226d000, 1825436, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x4226d000 mmap2(0x42425000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b8000) = 0x42425000 mmap2(0x42428000, 10908, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x42428000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7776000 mprotect(0x42425000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0x42269000, 4096, PROT_READ) = 0 munmap(0xb7777000, 95800) = 0 brk(0) = 0xbf896000 brk(0xbf8b7000) = 0xbf8b7000 brk(0) = 0xbf8b7000 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb778e000 brk(0) = 0xbf8b7000 brk(0xbf8e9000) = 0xbf8e9000 brk(0) = 0xbf8e9000 brk(0xbf91b000) = 0xbf91b000 brk(0) = 0xbf91b000 brk(0xbf94d000) = 0xbf94d000 brk(0) = 0xbf94d000 brk(0xbf97f000) = 0xbf97f000 ... brk(0) = 0xbff8e000 brk(0xbffc0000) = 0xbffc0000 brk(0) = 0xbffc0000 brk(0xbfff2000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7676000 brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7576000 brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7476000 brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7376000 ... brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb1c76000 brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb1b76000 brk(0) = 0xbffc0000 brk(0xbfffa000) = 0xbffc0000 mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb1a76000 brk(0) = 0xbffc0000 brk(0) = 0xbffc0000 brk(0) = 0xbffc0000 ... brk(0) = 0xbffc0000 brk(0) = 0xbffc0000 brk(0) = 0xbffc0000 +++ exited with 0 +++
ã«ãŒãã«ãããŒãžã空ã®ã¹ããŒã¹ã«é
眮ãããããããŒãé åãæžããããã«.dataã»ã¯ã·ã§ã³ãã¹ã¿ãã¯ã«ã·ããããŠãæå³ããããŸããã
ãµã³ãããã¯ã¹
ããã°ã©ã ã¡ã¢ãªãå¶éãããã1ã€ã®æ¹æ³ã¯ããµã³ãããã¯ã¹åã§ãã ãšãã¥ã¬ãŒã·ã§ã³ãšã®éãã¯ãäœããšãã¥ã¬ãŒããããããã°ã©ã ã®åäœã®äžéšãåã«ç£èŠããã³å¶åŸ¡ããããšã§ãã ãã«ãŠã§ã¢ãåé¢ããŠåæããã·ã¹ãã ã«æªåœ±é¿ãäžããªãããã«ãããšãã«ãã»ãã¥ãªãã£ç 究ã§ãã䜿çšãããŸãã
LD_PRELOADã䜿çšããããªãã¯
LD_PRELOADã¯ç¹å¥ãªç°å¢å€æ°ã§ããã次ã®ãããªåçãªãªã³ã«ãŒã«ããªããŒããããã©ã€ãã©ãªãåªå
çã«äœ¿çšãããŸãã libcã ã¡ãªã¿ã«ããã®ããªãã¯ã¯
äžéšã®ãã«ãŠã§ã¢ã§ã䜿çšãã
ãŠããŸã ã
ç§ã¯ãmalloc / freeåŒã³åºããã€ã³ã¿ãŒã»ããããã¡ã¢ãªãŒãåŠçããå¶éã«éãããšãã«ENOMEMãè¿ãåçŽãªãµã³ãããã¯ã¹ãäœæããŸããã
ãããè¡ãããã«ãmalloc / freeãäžå¿ã«å®è£
ããå
±æã©ã€ãã©ãªãäœæããmallocã®éã ãã«ãŠã³ã¿ãŒãå¢ãããfreeãåŒã³åºããããšãã«æžãããŸãã LD_PRELOADãä»ããŠããªããŒããããŸãã
ç§ã®mallocå®è£
ïŒ
void *malloc(size_t size) { void *p = NULL; if (libc_malloc == NULL) save_libc_malloc(); if (mem_allocated <= MEM_THRESHOLD) { p = libc_malloc(size); } else { errno = ENOMEM; return NULL; } if (!no_hook) { no_hook = 1; account(p, size); no_hook = 0; } return p; }
libc_malloc-libcããã®å
ã®mallocãžã®ãã€ã³ã¿ãŒã ã¹ããªãŒã å
ã®no_hookããŒã«ã«ãã©ã°ã ããã¯ã§mallocã䜿çšããååž°åŒã³åºããé¿ããããã«äœ¿çšãããŸãã
mallocã¯ã
uthashã©ã€ãã©ãªãŒã«ãã£ãŠã¢ã«ãŠã³ãé¢æ°ã§æé»çã«äœ¿çšãããŸãã ããã·ã¥ããŒãã«ã䜿çšããçç± freeãåŒã³åºããšãã¯ãã€ã³ã¿ãæž¡ãã ãã§ãfreeã®å
éšã§ã¯å²ãåœãŠãããã¡ã¢ãªéãããããªãããã§ãã ãããã£ãŠãããŒãã€ã³ã¿ãŒãšå€ã®åœ¢åŒã§å²ãåœãŠãããã¡ã¢ãªã®éãæã€ããŒãã«ããããŸãã ãããç§ãmallocã§è¡ãããšã§ãã
struct malloc_item *item, *out; item = malloc(sizeof(*item)); item->p = ptr; item->size = size; HASH_ADD_PTR(HT, p, item); mem_allocated += size; fprintf(stderr, "Alloc: %p -> %zu\n", ptr, size);
mem_allocatedã¯ãmallocã®å¶éãšæ¯èŒãããéçå€æ°ã§ãã
ä»ããç¡æã§é»è©±ãããšã次ã®ããšãèµ·ãããŸãïŒ
struct malloc_item *found; HASH_FIND_PTR(HT, &ptr, found); if (found) { mem_allocated -= found->size; fprintf(stderr, "Free: %p -> %zu\n", found->p, found->size); HASH_DEL(HT, found); free(found); } else { fprintf(stderr, "Freeing unaccounted allocation %p\n", ptr); }
ã¯ããmem_allocatedãæžãããŸãã
ãããŠãæè¯ã®éšåã¯ãããæ©èœããããšã§ãã
[restrict-memory]$ LD_PRELOAD=./libmemrestrict.so ./big_alloc pp[0] = 0x25ac210 pp[1] = 0x25c5270 pp[2] = 0x25de2d0 pp[3] = 0x25f7330 pp[4] = 0x2610390 pp[5] = 0x26293f0 pp[6] = 0x2642450 pp[7] = 0x265b4b0 pp[8] = 0x2674510 pp[9] = 0x268d570 pp[10] = 0x26a65d0 pp[11] = 0x26bf630 pp[12] = 0x26d8690 pp[13] = 0x26f16f0 pp[14] = 0x270a750 pp[15] = 0x27237b0 pp[16] = 0x273c810 pp[17] = 0x2755870 pp[18] = 0x276e8d0 pp[19] = 0x2787930 pp[20] = 0x27a0990 malloc: Cannot allocate memory Failed after 21 allocations
GitHubã®å®å
šãªã©ã€ãã©ãªã³ãŒã
LD_PRELOADã¯ã¡ã¢ãªãå¶éããåªããæ¹æ³ã§ããããšãããããŸãã
ptrace
ptraceã¯ããµã³ãããã¯ã¹ãæ§ç¯ããå¥ã®æ¹æ³ã§ãã ããã¯ãå¥ã®ããã»ã¹ã®å®è¡ãå¶åŸ¡ã§ããã·ã¹ãã ã³ãŒã«ã§ãã ããŸããŸãªPOSIX OSã«çµã¿èŸŒãŸããŠããŸãã
ããã¯ãstraceãltraceãããã³ã»ãŒãã¹ãŠã®ãµã³ãããã¯ã¹ããã°ã©ã ïŒsystraceãsydboxãmboxãgdbãå«ããããã¬ãŒïŒãªã©ã®ãã¬ãŒãµãŒã®åºç€ã§ãã
ptraceã§ããŒã«ãäœæããŸããã brkåŒã³åºãã远跡ããå
ã®ãã¬ãŒã¯å€ãšæ¬¡ã®brkåŒã³åºãã§èšå®ãããæ°ããå€ã®éã®è·é¢ã枬å®ããŸãã
ããã°ã©ã ã¯2ã€ã®ããã»ã¹ãåå²ããŠéå§ããŸãã 芪-ãã¬ãŒãµãŒãããã³å-ãã¬ãŒãµãŒã åããã»ã¹ã§ã¯ãptraceïŒPTRACE_TRACEMEïŒãåŒã³åºããŠããexecvãåŒã³åºããŸãã 芪ã§ã¯ãptraceïŒPTRACE_SYSCALLïŒã䜿çšããŠsyscallã§åæ¢ããåããã®brkåŒã³åºããé€å€ããŠãããå¥ã®ptraceïŒPTRACE_SYSCALLïŒã䜿çšããŠbrkããè¿ãããå€ãååŸããŸãã
brkãæå®ãããå€ãè¶
ãããšã-ENOMEMãbrkã®æ»ãå€ãšããŠèšå®ããŸãã ããã¯eaxã¬ãžã¹ã¿ã§èšå®ãããŠãããããptraceïŒPTRACE_SETREGSïŒã§äžæžãããŸãã æãããããéšåã¯æ¬¡ã®ãšããã§ãã
ãŸããlibcã«ã¯brkã§åé¡ãçºçããå Žåã«ããããåŒã³åºãã®ã«ååãªé è³ããããããmmap / mmap2ãžã®åŒã³åºããã€ã³ã¿ãŒã»ããããŸãã ãã®ãããã»ãããã€ã³ããè¶
ããŠmmapåŒã³åºãã衚瀺ãããããENOMEMã§ãããäžæããŸãã
ããŸãããïŒ
[restrict-memory]$ ./ptrace-restrict ./big_alloc pp[0] = 0x8958fb0 pp[1] = 0x8971fb8 pp[2] = 0x898afc0 pp[3] = 0x89a3fc8 pp[4] = 0x89bcfd0 pp[5] = 0x89d5fd8 pp[6] = 0x89eefe0 pp[7] = 0x8a07fe8 pp[8] = 0x8a20ff0 pp[9] = 0x8a39ff8 pp[10] = 0x8a53000 pp[11] = 0x8a6c008 pp[12] = 0x8a85010 pp[13] = 0x8a9e018 pp[14] = 0x8ab7020 pp[15] = 0x8ad0028 pp[16] = 0x8ae9030 pp[17] = 0x8b02038 pp[18] = 0x8b1b040 pp[19] = 0x8b34048 pp[20] = 0x8b4d050 malloc: Cannot allocate memory Failed after 21 allocations
ããããç§ã¯ããã奜ãã§ã¯ãããŸããã ABIã«é¢é£ä»ããããŠããŸãã ããã§ã¯ã64ããããã·ã³ã§eaxã®ä»£ããã«raxã䜿çšããå¿
èŠããããããå¥ã®ããŒãžã§ã³ãäœæããããïŒifdefã䜿çšãããã-m32ãªãã·ã§ã³ã匷å¶çã«äœ¿çšããå¿
èŠããããŸãã ãããŠãã»ãšãã©ã®å Žåãç°ãªãABIãæã€ä»ã®POSIXã®ãããªã·ã¹ãã ã§ã¯åäœããŸããã
ä»ã®æ¹æ³
ä»ã«äœãã§ããŸããïŒãããã®ãªãã·ã§ã³ã¯ããŸããŸãªçç±ã§æåŠãããŸããïŒïŒ
åç
§è³æ