==Phrack Inc.== Volume 0x0b, Issue 0x39, Phile #0x09 of 0x12 |=---------------------=[ Once upon a free()... ]=-----------------------=| |=-----------------------------------------------------------------------=| |=--------------=[ anonymous ]=-------------=| |=-------------=[ Ãʹú ¹ø¿ª : Null@Root(Nanu9,River,Bear) ]=-------------=| |=------------=[ ÀÇ¿ª : amadoh4ck ]=-------------=| Unix systemÀÇ C Ç¥ÁØ ¶óÀ̺귯¸®¿¡´Â ¸Þ¸ð¸®ÀÇ °¡º¯·®À» µ¿ÀûÀ¸·Î ´Ù·ç´Â ÇÔ¼öµéÀÌ ÀÖ´Ù. ÇÁ·Î±×·¥µéÀº ÀÌ ÇÔ¼öµéÀ» ÀÌ¿ëÇÏ¿© ½Ã½ºÅÛÀ¸·ÎºÎÅÍ µ¿ÀûÀ¸·Î ¸Þ¸ð¸®¸¦ ÇÒ´ç ¹ÞÀ» ¼ö ÀÖ´Ù. OS(¿î¿µÃ¼Á¦)´Â "heap"À̶ó°í ¾Ë·ÁÁø ¸Þ¸ð¸® chunkÀÇ Å©±â¸¦ ¹Ù²Ü ¼ö ÀÖ´Â system callÀ» Á¦°øÇÑ´Ù. ÀÌ°ÍÀº "brk"¶ó´Â system callÀÌ´Ù. ÀÌ system call À§¿¡ malloc ÀÎÅÍÆäÀ̽º°¡ ÀÖ´Ù. Áï, mallocÀº "brk" system call°ú ÀÀ¿ëÇÁ·Î±×·¥ »çÀÌÀÇ °èÃþ(layer)À» Á¦°øÇÏ´Â °ÍÀÌ´Ù. mallocÀº ÀÀ¿ëÇÁ·Î±×·¥ÀÇ ¿ä ±¸¿¡ ÀÇÇØ ÇϳªÀÇ Å« ºí·ÏÀ» ´õ ÀÛÀº chunk·Î µ¿ÀûÀ¸·Î ºÐ¸®ÇÏ°í, Á¦°ÅÇÒ ¼ö ÀÖ´Ù. ¶ÇÇÑ, ÀÌ·± µ¿ÀÛÀ» ÇÏ´Â µ¿¾È ¹ß»ýÇÒ Áöµµ ¸ð¸£´Â ´ÜÆíÈ­(Á¶°¢È­) Çö»óÀ» ÇÇÇÒ ¼öµµ ÀÖ´Ù. mallocÀº ´ÜÁö µ¿ÀûÀ¸·Î Å©±â°¡ º¯ÇÏ´Â ¼±Çü ÆÄÀÏ ½Ã½ºÅÛ(linear file system) °ú ºñ±³ÇÒ ¼ö ÀÖ´Ù. malloc ÀÎÅÍÆäÀ̽º°¡ °®Ãß¾î¾ß ÇÒ ¸î°¡Áö ¼³°è ¸ñÇ¥´Â ´ÙÀ½°ú °°´Ù. - stability(¾ÈÁ¤¼º) - performance(¼º´É) - avoidance of fragmentation(´ÜÆíÈ­ ¹æÁö) - low space overhead(°ø°£ ¿À¹öÇìµå ÁÙÀÓ) ÇöÀç ¸î°³ÀÇ ÀϹÝÀûÀÎ malloc ±¸ÇöµéÀÌ ÀÖ´Ù. ´ëºÎºÐ °øÅëÀûÀÎ °Í Áß Çϳª°¡ AT&T ¿¡ ÀÇÇØ ±¸ÇöµÈ System V ÀÌ°í, ±× ¿Ü¿¡ GNU C Library ±¸Çö°ú Microsoft ¿î¿µÃ¼Á¦ ÀÇ malloc-similar(RtlHeap*) ÀÎÅÍÆäÀ̽º°¡ ÀÖ´Ù. ¿î¿µÃ¼Á¦º°·Î »ç¿ëÇÏ´Â ¾Ë°í¸®ÁòÀ» ³ªÅ¸³½ Ç¥°¡ ´ÙÀ½°ú °°´Ù. ¾Ë°í¸®Áò | ¿î¿µ üÁ¦ ------------------------+-------------------------------------------------- BSD kingsley | 4.4BSD, AIX (compatibility), Ultrix BSD phk | BSDI, FreeBSD, OpenBSD GNU Lib C (Doug Lea) | Hurd, Linux System V AT&T | Solaris, IRIX Yorktown | AIX (default) RtlHeap* | Microsoft Windows * ------------------------+-------------------------------------------------- ´ëºÎºÐÀÇ malloc ±¸ÇöµéÀÌ À̽Ä(port)µÇ±â ½±°í ¾ÆÅ°ÅØÃÄ¿¡ µ¶¸³ÀûÀ̶ó´Â »ç½ÇÀº Èï¹Ì·Î¿î ÀÏÀÌ´Ù. ÀÌ·¯ÇÑ malloc ±¸ÇöÀÇ ´ëºÎºÐÀÌ 'brk' system callÀ» ÀÌ¿ëÇÏ¿© ¸¸µé¾î Á³´Ù. #defineÀ¸·Î ÀÌ·¯ÇÑ µ¿ÀÛÀ» ¹Ù²Ü ¼ö ÀÖ´Ù. ÇÊÀÚ°¡ ¾Ë°í ÀÖ´Â ±¸Çöµé ¸ðµÎ°¡ ANSI C·Î ¾²¿©Á³°í, ÃÖ¼ÒÈ­ ÇßÀ¸¸ç ¿ÂÀüÇÏ°Ô Äڵ带 üũÇÏÁö ¾Ê¾Ò´Ù. ±×µé ´ëºÎºÐÀÌ °æ°í¿Í ¿©ºÐÀÇ Ã¼Å©¸¦ À§ÇØ Æ¯º°ÇÑ ÄÄÆÄÀÏ Á¤ÀÇ(#define)À» »ç¿ëÇÒ »ÓÀÌ ´Ù. ±×°Í Á¶Â÷ ¼º´ÉÀÇ ÀÌÀ¯·Î ÃÖÁ¾ build¿¡¼­´Â ±âº»ÀûÀ¸·Î ²¨ ³õ´Â´Ù. ±¸Çöµé Áß ¾î¶² °ÍÀº ¹öÆÛ¿À¹öÇ÷ο츦 °¨ÁöÇÒ ¼ö ÀÖµµ·Ï checkÇÏ´Â °Íµéµµ ÀÖ´Ù. ±×·¯³ª, ÀÌ ·¯ÇÑ checkµéµµ °³¹ß °úÁ¤ÀÇ ¿À¹öÇ÷ο츦 °ËÃâÇÒ ¸ñÀûÀÏ »ÓÀÌ°í ÃÖÁ¾ÀûÀÎ ´Ü°èÀÇ exploitÀº ¸·Áö ¸øÇÑ´Ù. Storing management info in-band ´ëºÎºÐÀÇ malloc ±¸ÇöµéÀº ÀÚ½ÅÀÇ °ü¸® Á¤º¸¸¦ ÀúÀåÇÏ°í °øÀ¯ÇÑ´Ù. ÀÌ·¯ÇÑ Á¤º¸¿¡´Â »ç¿ëµÇ°í Àְųª »ç¿ëÀÌ ÇØÁ¦µÈ(free) blockµéÀÇ ¸®½ºÆ®, ¸Þ¸ð¸® blockÀÇ Å©±â, heap ¿µ¿ª ÀÚü¿¡ Æ÷ÇÔµÈ À¯¿ëÇÑ Á¤º¸µéÀÌ ÇØ´çµÈ´Ù. malloc/freeÀÇ ÀüüÀûÀÎ ¾ÆÀ̵ð¾î°¡ ÀÀ¿ëÇÁ·Î±×·¥ÀÇ µ¿Àû ¿ä±¸¿¡ ±âÃʸ¦ µÎ°í Àֱ⠶§¹®¿¡, °ü¸® Á¤º¸ ¶ÇÇÑ ¸¹Àº ÀÚ·á(Á¤º¸)µéÀ» °¡Áö°í ÀÖ´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î, mallocÀº ´ÜÁö ÀÀ¿ëÇÁ·Î±×·¥ÀÌ ¿äûÇÑ ¸Þ¸ð¸®ÀÇ ¾çÀ» ¿¹¾àÇÏ´Â °Íó·³ º¸ÀÌÁö¸¸, ½ÇÁ¦·Î´Â ÀÀ ¿ëÇÁ·Î±×·¥ÀÌ »ç¿ëÇÏ´Â ¸Þ¸ð¸® blockÀÇ ¹Ù·Î ¾Õ°ú µÚ¿¡ °ü¸®Á¤º¸µéÀ» ÀúÀåÇÏ°Ô µÇ´Â °ÍÀÌ´Ù. ÀÀ¿ëÇÁ·Î±×·¥ÀÌ malloc ÀÎÅÍÆäÀ̽º¸¦ ÅëÇØ ¸Þ¸ð¸® ºí·ÏÀ» ¿ä±¸ÇÏ°Ô µÇ¸é ÀÌ°ÍÀº ÈÄ¿¡ ¹öÆÛ¿À¹öÇ÷οì Ãë¾àÁ¡ÀÌ ¹ß»ýµÉ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº chunk µÚÀÇ µ¥ÀÌŸ¸¦ ¹Ù²ÞÀ¸·Î½á °¡´ÉÇÏ°Ô µÈ´Ù. malloc °ü¸® ±¸Á¶Ã¼(management structures)¸¦ ¼öÁ¤ÇÏ´Â °Ô °¡´ÉÇÏ°Ô µÇ´Â °ÍÀÌ´Ù. ÀÌ·¯ÇÑ ¹æ¹ýÀº Solar DesignerÀÇ "wizard-like exploit"¿¡¼­ ¼³¸íµÇ¾ú ´Ù. mallocÀ¸·Î ÇÒ´çµÈ ¹öÆÛÀÇ ¿À¹öÇÃ·Î¿ì °ø°ÝÀÇ ÇÙ½ÉÀº ÀÌ °ü¸® Á¤º¸¸¦ ¼öÁ¤ÇÔÀ¸·Î½á ³ªÁß¿¡ ÀÓÀÇÀÇ ¸Þ¸ð¸®¿¡ ¿À¹ö¶óÀÌÆ®°¡ °¡´ÉÇÏ°Ô µÈ´Ù´Â °ÍÀÌ´Ù. ÀÌ ¹æ¹ýÀ¸·Î, pointerµéÀÌ writable process memory¿¡ µ¤¾î¾²¿© Áö°í, linkage Å×ÀÌ ºíÀ̳ª ÀÀ¿ëÇÁ·Î±×·¥ ·¹º§ µ¥ÀÌŸ, ¸®ÅÏ ¾îµð·¹½ºµîÀÌ ¼öÁ¤ °¡´ÉÇØ Áø´Ù. ÀÌ·¯ÇÑ °ø°ÝÀ» ½ÃµµÇϱâ À§ÇØ ¿ì¸®´Â malloc±¸ÇöÀÇ ³»ºÎ¸¦ ±íÀÌ ÈÈ¾î º¸¾Æ¾ß ÇÑ´Ù. ÀÌ ±â»ç´Â GNU C ¶óÀ̺귯¸®¿Í System V ±¸Çö¿¡ °øÅëÀûÀ¸·Î »ç¿ëµÈ °ÍÀ» ³íÀÇÇÏ°í, ¸®´ª½º, ¼Ö¶ó¸®½º, IRIX ½Ã½ºÅÛÇÏ¿¡¼­ mallocÀ¸·Î ÇÒ´çµÈ ¹öÆÛµéÀ» ¿À¹öÇ÷ο츦 ÀÌ ¿ëÇÏ¿© Á¶ÀÛÇÏ´Â ¹æ¹ýÀ» ¾Ë¾Æº¸·Á ÇÑ´Ù. System V ÀÇ malloc ±¸Çö ======================= IRIX¿Í ¼Ö¶ó¸®½º´Â self-adjusting binary trees¿¡ ±â¹ÝÀ» µÐ ±¸ÇöÀ» »ç¿ëÇÑ´Ù. ÀÌ ±¸ÇöÀÇ ÀÌ·ÐÀû ¹è°æÀº [2]¿¡ ¼³¸íµÇ¾îÁ® ÀÖ´Ù. ÀÌ ±¸ÇöÀÇ ±âº»ÀûÀÎ ¾ÆÀ̵ð¾î´Â °°Àº Å©±âÀÇ malloc chunks list¸¦ binary tree·Î À¯ÁöÇÏ´Â °ÍÀÌ´Ù. ¸¸ÀÏ °°Àº Å©±â·Î µÎ°³ÀÇ chunk¸¦ ÇÒ´çÇÑ´Ù¸é, ±×µéÀº °°Àº ³ëµå ¾È¿¡ ÀÖÀ» °ÍÀÌ°í, ÀÌ ³ëµåÀÇ °°Àº ¸®½ºÆ® ¾È¿¡ ÀÖÀ» °ÍÀÌ´Ù. ±× Æ®¸®´Â Æ®¸® ¿ä¼ÒÀÇ Å©±â¿¡ ÀÇÇؼ­ Á¤·Ä µÇ¾îÁø´Ù. The TREE structure (Æ®¸®±¸Á¶) TREE ±¸Á¶ Á¤ÀÇ´Â mallint.h¾È¿¡¼­ ãÀ» ¼ö ÀÖ´Ù. ÀÌ ÆÄÀÏ¿¡´Â tree¿ä¼Òµé¿¡ ½±°Ô Á¢ ±ÙÇϱâ À§ÇØ »ç¿ëµÇ´Â ¸ÅÅ©·Îµéµµ Æ÷ÇԵǾî ÀÖ´Ù. mallint.h ÆÄÀÏÀº ¼Ö¶ó¸®½º ¿î¿µÃ¼ Á¦ ¹èÆ÷¼Ò½º¿¡¼­ ¹ß°ßÇÒ ¼ö ÀÖ´Ù.[4] ºñ·Ï °°Àº ¼Ò½º±â¹ÝÀÇ IRIX¸¦ °íÄ¥ ¼ö´Â ¾ø¾úÁö ¸¸ ¿©±â¿¡µµ ¿©·¯°¡Áö ºñ½ÁÇÑ Á¡ÀÌ ÀÖ´Ù. ¸î¸î 64ºñÆ® alignment¸¦ Á¦¿ÜÇÏ°í malloc ÀÎÅÍÆäÀ̽º´Â °°Àº ¸Þ¹Ì·Î ·¹À̾ƿô°ú ÇÔ¼öµéÀ» ³»ºÎÀûÀ¸·Î »ý¼ºÇÑ´Ù. ¶ÇÇÑ, ¼Ö¶ó¸® ½º ¼Ò½º¸¦ IRIX ÀͽºÇ÷ÎÀÕÀ» À§ÇØ »ç¿ëÇÒ ¼ö ÀÖ´Ù. °¢ tree element´Â ¿À¹öÇìµå¸¦ ÇÇÇϰųª, alignment¸¦ °­Á¦·Î ¼³Á¤ÇÏ´Â µî °¢°¢ ´Ù¸¥ ¸ñÀûÀ» À§ÇØ »ç¿ëµÉ ¼ö ÀÖµµ·Ï unionÀ¸·Î Á¤ÀǵǾî ÀÖ´Ù. /* the proto-word; size must be ALIGN bytes */ typedef union_w_ { size_t w_i; /* an unsigned int */ struct_t_ *w_p; /* a pointer */ char w_a[ALIGN]; /* to force size */ } WORD; Central TREE structure definition: ÁÖ¿ä Æ®¸® ±¸Á¶ Á¤ÀÇ /* structure of a node in the free tree (free tree¾ÈÀÇ ³ëµå ±¸Á¶) */ typedef struct _t_ { WORD t_s; /* size of this element */ WORD t_p; /* parent node */ WORD t_l; /* left child */ WORD t_r; /* right child */ WORD t_n; /* next in link list */ WORD t_d; /* dummy to reserve space for self_pointer */ } TREE; chunk Çì´õÀÇ t_s ¿ä¼Ò´Â malloc ÇÔ¼ö¸¦ È£ÃâÇÒ ¶§ ¿äûÇÑ Å©±â¸¦ ¹Ý¿Ã¸²ÇÑ °ªÀÌ´Ù. ÀÌ Å©±â´Â Ç×»ó word ´ÜÀ§·Î ¹Ý¿Ã¸²µÇ±â ¶§¹®¿¡ t_s ¿ä¼ÒÀÇ ÇÏÀ§ 2ºñÆ®´Â »ç¿ëµÇÁö ¾Ê´Â´Ù. ÀÌ 2ºñÆ®´Â ÀϹÝÀûÀ¸·Î Ç×»ó 0°ªÀ» °¡Áø´Ù. 0 ´ë½Å¿¡ ´Ù¸¥ °ªÀÌ ¿Â´ÙÇصµ ±× °ªÀº Å©±â¿Í´Â ¹«°üÇÑ Àǹ̸¦ °¡Áø´Ù. ±× °ªÀº flag ¿ä¼Ò·Î½á »ç¿ëµÇ¾î Áø´Ù. malloc.c ¼Ò½º·Î ºÎÅÍ ¾Æ·¡¿Í °°Àº »ç½ÇÀ» ¾Ë ¼ö ÀÖ´Ù. BIT0: 1Àº ºí·ÏÀÌ »ç¿ëµÇ°í ÀÖÀ» ¶§, 0Àº freeÀÏ ¶§ BIT1: ºí·ÏÀÌ »ç¿ëµÇ°í ÀÖ°í, ¿¬¼ÓµÈ ¸Þ¸ð¸®»óÀÇ ÀÌÀü ºí·ÏÀÌ freeÀ̸é ÀÌ ºñÆ®´Â 1ÀÌ´Ù. ±×·¸Áö ¾ÊÀ¸¸é Ç×»ó 0ÀÌ´Ù. TREE Access macros: Tree Á¢±Ù ¸ÅÅ©·Îµé /* usable # of bytes in the block */ #define SIZE(b) (((b)->t_s).w_i) /* free tree pointers */ #define PARENT(b) (((b)->t_p).w_p) #define LEFT(b) (((b)->t_l).w_p) #define RIGHT(b) (((b)->t_r).w_p) /* forward link in lists of small blocks */ #define AFTER(b) (((b)->t_p).w_p) /* forward and backward links for lists in the tree */ #define LINKFOR(b) (((b)->t_n).w_p) #define LINKBAK(b) (((b)->t_p).w_p) ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ´Â ¸ðµç operationÀ» À§ÇØ Á¤·Ä(certain alignment)°ú ÃÖ¼Ò Å©±â°¡ ¾Æ·¡¿Í °°ÀÌ Á¤ÀǵȴÙ. #define WORDSIZE (sizeof(WORD)) #define MINSIZE (sizeof(TREE) - sizeof(WORD)) #define ROUND(s) if (s%WORDSIZE) s += (WORDSIZE-(s%WORDSIZE)) Tree ±¸Á¶´Â ÇÒ´çµÈ chunk °¢°¢ÀÇ ÇÙ½ÉÀûÀÎ ¿ä¼ÒÀÌ´Ù. ÀϹÝÀûÀ¸·Î ¿ÀÁ÷ t_s¿Í t_p ¿ä¼Ò¸¸ÀÌ »ç¿ëµÇ°í »ç¿ëÀÚ data´Â t_l ºÎÅÍ ÀúÀåµÈ´Ù. ³ëµå°¡ freeµÇ¸é ÀÌ°ÍÀÌ ¹Ù ²î°í, data´Â ´õ È¿°úÀûÀ¸·Î free element¸¦ ´Ù·ç±â À§Çؼ­ Àç»ç¿ëµÈ´Ù. chunk´Â ±â¿ï¾îÁø tree(splay tree)¾ÈÀÇ element¸¦ ³ªÅ¸³½´Ù. ´õ ¸¹Àº chunk°¡ freeµÉ ¶§, malloc ±¸ÇöÀº ±×°ÍÀÇ ¿À¸¥ÂÊ ´ÙÀ½¿¡ ÀÖ´Â free chunk¸¦ ÇÕÄ¡·Á°í ÇÑ´Ù. µ¿½Ã¿¡ dangling free tree stat¾È¿¡ ÀÖÀ» ¼ö Àִ ûũ´Â ±â²¯ÇØ¾ß FREESIZE(±âº» 32byte) ¸¸Å­ÀÌ´Ù. ±×°ÍµéÀº ¸ðµÎ 'flist' ¹è¿­¾È¿¡ ÀúÀåµÇ¾îÁø´Ù. ¸®½ºÆ®°¡ ÀÌ¹Ì °¡µæÂ÷ ÀÖ À»¶§ free°¡ ½ÇÇàµÈ´Ù¸é ÀÌ ¸®½ºÆ®¾ÈÀÇ ¿À·¡µÈ element´Â ¶³¾îÁ® ³ª°¡°í realfree (ÇÔ¼ö¸í)·Î µé¾î°¡°Ô µÈ´Ù. ±×¸®°í³ª¼­ ÀÌ °ø°£Àº »õ·Î¿î freed element°¡ Â÷ÁöÇÑ´Ù. free¸¦ À§ÇÑ ¸¹Àº È£ÃâÀÌ ÇÑÁÙ ¾È¿¡¼­ ¹ß»ýÇÒ °æ¿ì ¼Óµµ¸¦ Áõ°¡½ÃÅ°°í defragmention (Á¶°¢È­,´ÜÆíÈ­)À» ÇÇÇϱâ À§Çؼ­ ÀÌ´Ù. ½ÇÁúÀûÀ¸·Î ÇÕº´ÇÏ´Â °úÁ¤Àº realfree¿¡ ÀÇ ÇØ ½ÇÇàµÈ´Ù. ÀÌ°ÍÀº chunk¸¦ root pointer·Î ½ÃÀÛÇÏ´Â central tree¿¡ ³Ö´Â´Ù. Æ®¸® ´Â ±×°ÍµéÀÇ ¿ä¼ÒÀÇ Å©±â¿¡ ÀÇÇؼ­ Á¤·ÄµÇ¾îÁö°í self-balanceing(ÀÚü ±ÕÇüÀâ±â)ÇÑ ´Ù. ÀÌ°ÍÀ» ¼ÒÀ§ splay tree(±â¿ï¾îÁø Æ®¸®)¶ó ÇÑ´Ù. ÀÌ Æ®¸®¾È¿¡¼­ elementµéÀº °Ë »ö¼Óµµ¸¦ ³ôÀ̱â À§ÇØ Æ¯º°ÇÑ ¹æ¹ýÀ¸·Î ¼øȯÇÑ´Ù.(¿¹·Î google.comÀº ´õ ¸¹Àº Á¤º¸¸¦ À§ÇÑ splay treeÀÌ´Ù.) ÀÌ°ÍÀº ´õ ÀÌ»ó ¿©±â¿¡¼­ Áß¿äÇÏÁö ¾Ê´Ù. ±×·¯³ª free chunk ÀÇ µÎ°¡Áö ´Ü°è°¡ ÀÖÀ½À» ±â¾ïÇØ¾ß ÇÑ´Ù. Çϳª´Â 'flist' ¹è¿­ ¾È¿¡¼­ÀÌ°í, ´Ù¸¥ ÇÏ ³ª´Â 'Root'·Î ½ÃÀÛÇÏ´Â Æ®¸®ÀÇ free-element ¾È¿¡¼­ ÀÌ´Ù. ¸Þ¸ð¸®ÀÇ ÀÛÀº chunk¸¦ ÇÒ´çÇϱâ À§ÇÑ Æ¯º°ÇÑ Ã³¸® ·çƾÀÌ ¸î°³ Àִµ¥, ÀÌ°ÍÀº ¿ì¿¬ ÇÏ°Ôµµ 40byteº¸´Ù ÀÛÀº Å©±âÀÏ ¶§ ÀϾ´Ù. À̰͵éÀº ¿©±â¼­ °í·ÁÇÏÁö ¾Ê´Â´Ù. ±× ·¯³ª, ±âº»ÀûÀÎ ¾ÆÀ̵ð¾î´Â tree¾È¿¡ ±×°ÍÀ» µÎ´Â °ÍÀÌ ¾Æ´Ï¶ó extra list¾È¿¡ µÐ´Ù ´Â °ÍÀÌ´Ù. malloc ±â¹ÝÀÇ ¹öÆÛ¿À¹öÇ÷ο츦 ÀͽºÇ÷ÎÀÕ ½ÃÅ°±â À§ÇØ IRIX¿Í ¼Ö¶ó¸®½º¿¡¼­ »ç¿ë ÇÏ´Â º¸´Ù³ªÀº ¹æ¹ýÀÌ ¿©±â ÀÖ´Ù. ÇÑ chunk°¡ realfree µÉ¶§ ÀÌ¿ô chunkµéÀÌ ÀÌ¹Ì realfreeµÈ tree ¾È¿¡ ÀÖ´Â Áö °Ë»ç µÈ´Ù. ¸¸ÀÏ ÀÌ·± °æ¿ì¶ó¸é, ³í¸®ÀûÀ¸·Î µÎ chunk¸¦ ÇÕº´½ÃÅ°°í Å©±â°¡ º¯ÇßÀ¸¹Ç·Î tree¾ÈÀÇ À§Ä¡¸¦ ´Ù½Ã Á¤·ÄÇØ¾ß ÇÑ´Ù. ÀÌ ÇÕº´Ã³¸®´Â nodeµé·Î ±¸¼ºµÈ tree¾È¿¡¼­ÀÇ pointer º´°æÀ» ¼ö¹ÝÇÑ´Ù. ÀÌ ³ëµåµéÀº chunk header ÀÚü·Î Ç¥ÇöµÈ´Ù. ´Ù¸¥ tree element¸¦ À§ÇÑ Æ÷ÀÎÅÍ°¡ ±× °÷(node)¿¡ ÀúÀåµÈ´Ù. ¿ì¸®°¡ ±×°ÍµéÀ» µ¤¾î ¾µ¼ö ÀÖ´Ù¸é, chunk¸¦ ÇÕÄ¥ ¶§ ±× Æ÷ÀÎÅÍ(pointer) ¸¦ ¼öÁ¤ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¿©±â malloc.c ¾È¿¡¼­ ¾î¶»°Ô µÇ´ÂÁö º¸¿©ÁØ´Ù. (ÀÌ°ÍÀº Èï¹Ì·Î¿î ºÎºÐÀ» À§ÇØ ¼öÁ¤µÇ¾ú´Ù.) static void realfree(void *old) { TREE *tp, *sp, *np; size_t ts, size; /* pointer to the block */ tp = BLOCK(old); ts = SIZE(tp); if (!ISBIT0(ts)) return; CLRBITS01(SIZE(tp)); /* ´ÙÀ½ ºí·Ï°ú ÇÕÃÄ Áú ¼ö ÀÖ´Â Áö üũ */ np = NEXT(tp); if (!ISBIT0(SIZE(np))) { if (np != Bottom) t_delete(np); SIZE(tp) += SIZE(np) + WORDSIZE; } NEXT°¡ ÇöÀç chunkÀÇ ¹Ù·Î ´ÙÀ½¿¡ Àִ ûũ¶ó´Â °ÍÀ» ±â¾ïÇÑ´Ù. ±×·¡¼­, ¸Þ¸ð¸® ±¸ Á¶´Â ¾Æ·¡¿Í °°´Ù. tp old np | | | [chunk A header] [chunk A data] | [chunk B of free ....] | chunk boundary ÀϹÝÀûÀÎ °æ¿ì ÀÀ¿ëÇÁ·Î±×·¥Àº ¾î¶² ¿µ¿ªÀ» ÇÒ´ç¹Þ°Ô µÇ°í malloc À¸·Î ºÎÅÍ (old) Æ÷ÀÎÅ͸¦ ¾ò°Ô µÈ´Ù. ±×¸®°í, chunk dataÀÇ ¿À¹öÇ÷ο찡 Çã¿ëµÈ´Ù. ¿ì¸®´Â ¿À¹öÇ÷Π¿ì¿¡ ÀÇÇØ chunk °æ°è¸¦ ³Ñ°í µÚÂÊÀÇ data¿¡ ±â·ÏÇÒ ¼ö ÀÖ°Ô µÈ´Ù. ÀÌ µÚÂÊÀÇ data´Â freeµÇ¾ú°Å³ª »ç¿ëÁßÀÎ chunk ÀÌ´Ù. np = NEXT(tp); ¿ì¸®´Â ¿ÀÁ÷ old µÚÂÊÀÇ data¸¦ ¿À¹öÇÃ·Î¿ì ½Ãų¼ö ÀÖ´Ù. ÇöÀç chunk Çì´õ ÀÚü´Â ¼ö Á¤ÇÒ ¼ö ¾ø´Ù. ±×·¯¹Ç·Î, ¾î¶² ¹æ¹ýÀ¸·Îµµ np Æ÷ÀÎÅÍ¿¡ ¿µÇâÀ» ÁÙ ¼ö ¾ø´Ù. ±×°Í(np Æ÷ÀÎÅÍ)Àº Ç×»ó chunkÀÇ °æ°è¸¦ °¡¸®Å²´Ù. ÀÌÁ¦ ¿ì¸®ÀÇ chunk¿Í ±×°Í µÚÀÇ chunk¸¦ ÇÕÄ¡´Â °Ô °¡´ÉÇÑ Áö °Ë»çÇÏ°Ô µÈ´Ù. ±â¾ïÇØ¾ß ÇÒ °ÍÀº ¿ì¸®°¡ ÇöÀç chunkÀÇ ¿À¸¥ÂÊ chunk¸¦ Á¶ÀýÇÒ ¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. if (!ISBIT0(SIZE(np))) { if (np != Bottom) t_delete(np); SIZE(tp) += SIZE(np) + WORDSIZE; } ¸¸ÀÏ chunk°¡ free°í free element tree¾È¿¡ ÀÖÀ¸¸é BIT0Àº 0ÀÌ´Ù. ¶ÇÇÑ ±×°ÍÀÌ free ÀÌ°í ¸¶Áö¸· chunk(Ưº°ÇÑ Bottom chunk)°¡ ¾Æ´Ï¶ó¸é ±× chunk´Â tree¿¡¼­ Áö¿öÁø´Ù. ±×·± ´ÙÀ½ µÎ°³ÀÇ chunkµéÀÇ Å©±â°¡ ´õÇØÁö°í ³ªÁß¿¡ realfree ÇÔ¼ö¿¡ ÀÇÇØ Àüü ¸® »çÀÌÁîµÈ chunk°¡ tree¾ÈÀ¸·Î ´Ù½Ã µé¾î°¡°Ô µÈ´Ù. Áß¿äÇÑ Á¶°ÇÀÌ Àִµ¥ ±×°ÍÀº ¿À¹öÇ÷οìµÈ chunk°¡ malloc ¿µ¿ª ¾ÈÀÇ ¸¶Áö¸· chunk °¡ ¾Æ´Ï¾î¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù. 1. ¿À¹öÇ÷οìµÈ chunk´Â ¸¶Áö¸· chunk°¡ ¾Æ´Ï¾î¾ß ÇÑ´Ù. ¿©±â¼­ t_delete ÇÔ¼ö°¡ ¾î¶»°Ô ÀÛ¿ëÇÏ´Â Áö º¸ÀÚ. static void t_delete(TREE *op) { TREE *tp, *sp, *gp; /* if this is a non-tree node */ if (ISNOTREE(op)) { tp = LINKBAK(op); if ((sp = LINKFOR(op)) != NULL) LINKBAK(sp) = tp; LINKFOR(tp) = sp; return; } ´Ù¸¥ °æ¿ìµµ ÀÖ´Ù, ÀÌ°ÍÀÌ exploit ÇϱⰡ ½¬¿î °Í ÁßÀÇ ÇϳªÀ̹ǷΠÀÌ°ÍÀ» ¼³¸íÇÏ µµ·Ï ÇÑ´Ù. ³ª´Â ¹ú½á ÀÌ°Í¿¡ ½ÈÁõÀ» ´À²¼±â ¶§¹®¿¡, ¿©±â¿¡ ±× Áß Çϳª¸¦ ¼³¸í¸¸ ÇÒ °ÍÀÌ´Ù. ´Ù¸¥ °Íµé°ú ¸Å¿ì ºñ½ÁÇÏ´Ù. (malloc.c¸¦ ºÁ¶ó.) ISNOTREE´Â TREE±¸Á¶Ã¼ÀÇ 't_l' ¿ä¼Ò¿Í -1À» ºñ±³ÇÑ´Ù. -1Àº non-tree ³ëµå¸¦ À§ÇÑ Æ¯º°ÇÑ Ç¥½Ã·Î(ÀÌÁß¿¬°á ¸®½ºÆ®¸¦ À§ÇØ »ç¿ë) exploit ½ÃÅ°±â¿¡ Ưº°ÇÑ ¹®Á¦´Â ¾ø´Ù. ¾î·µç, ÀÌ°ÍÀº exploitÀ» À§ÇÑ Ã¹¹ø° Á¶°ÇÀÌ´Ù. 2. fake->t_l = -1; ÀÌÁ¦ FOR(t_n)°ú BAK(t_p) »çÀÌ¿¡ ¿¬°á²÷±â°¡ ³¡³µ°í, ´ÙÀ½°ú °°ÀÌ ´Ù½Ã ¾²¿©Áú ¼ö ÀÖ´Ù. t1 = fake->t_p t2 = fake->t_n t2->t_p = t1 t1->t_n = t2 ÀÌ°ÍÀº pseudo-raw-assignment¿¡ ÀÇÇØ µ¿½Ã¿¡ ¾²¿©Áø´Ù. [t_n + (1 * sizeof(WORD))] = t_p [t_p + (4 * sizeof(WORD))] = t_n ÀÌ ¹æ¹ýÀ¸·Î ¿ì¸®´Â ƯÁ¤ ÁÖ¼Ò¿¡ ÀÓÀÇÀÇ ÁÖ¼Ò°ªÀ» ±â·ÏÇÒ ¼ö ÀÖ´Ù. ÀÌ ¹æ¹ýÀ» »ç¿ë Çϱâ·Î ÇÏÀÚ. t_p = retloc - 4 * sizeof(WORD) t_n = retaddr ÀÌ ¹æ¹ýÀ¸·Î retlocÀº retaddr·Î µ¤¾î¾²¿©Áö°í, *(retaddr+8)Àº retlocÀ¸·Î µ¤¾î ¾² ¿© Áú °ÍÀÌ´Ù. ¸¸¾à retaddr¿¡ ½ÇÇàÄڵ尡 ÀÖ´Ù¸é, 8~11¹ÙÀÌÆ® ¸¸Å­ÀÇ ÀÛÀº Á¡ÇÁ°¡ ¹ß»ýÇÒ °ÍÀÌ´Ù. ¶ÇÇÑ, ´õ ³ªÀº °æ¿ì, ÁÖ¼ÒµéÀÌ ¹Ù²î°Ô µÉ °ÍÀÌ´Ù. ¸¶Áö¸·À¸·Î ¿ì¸®´Â ¹öÆÛ¸¦ ´ÙÀ½°ú °°ÀÌ µ¤¾î¾´´Ù. | | chunk boundary Where: t_s = some small size with lower two bits zeroed out t_p = retloc - 4 * sizeof(WORD) t_l = -1 t_r = junk t_n = retaddr t_d = junk ºñ·Ï ¸ðµç µ¥ÀÌŸ°¡ 32bit Æ÷ÀÎÅÍ·Î ÀúÀåµÉ Áö¶óµµ, °¢ ±¸Á¶Ã¼ÀÇ ¿ø½ºµéÀº 8byte¸¦ »ç¿ëÇÑ´Ù´Â »ç½ÇÀ» ÁÖ¸ñÇ϶ó. ÀÌ°ÍÀº °¢°¢ÀÇ ¿ø¼Ò¿¡ ´ëÇؼ­ ÃÖ¼ÒÇÑ ALIGN ¹ÙÀÌÆ®°¡ »ç¿ëµÇµµ·Ï Á¤ÇØÁ® ÀÖ´Â WORD union ¶§¹®ÀÌ´Ù. ALIGNÀº ±âº»ÀûÀ¸·Î 8byte·Î Á¤ÀǵǾî ÀÖ´Ù. ±×·¡¼­ chunk °æ°è µÚÀÇ ½ÇÁ¦ ¿À¹öÇ÷οì´Â ´ÙÀ½°ú °°ÀÌ º¸ÀÏ °ÍÀÌ´Ù. ff ff ff f0 41 41 41 41 ef ff fc e0 41 41 41 41 | ....AAAA....AAAA ff ff ff ff 41 41 41 41 41 41 41 41 41 41 41 41 | ....AAAAAAAAAAAA ef ff fc a8 41 41 41 41 41 41 41 41 41 41 41 41 | ....AAAAAAAAAAAA ¸ðµç 'A' ¹®ÀÚµéÀº ÀÓÀÇ·Î ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. 't_s'´Â NUL ¹ÙÀÌÆ®¸¦ ȸÇÇÇϱâ À§Çؼ­ ÀÛÀº À½¼ö·Î ´ëüµÇ¾ú´Ù. ¸¸¾à ´ç½ÅÀÌ NUL ¹ÙÀÌÆ®¸¦ »ç¿ëÇϱ⠿øÇÑ´Ù¸é, ¾ÆÁÖ ÀûÀº °ÍÀ» ½á¶ó. ±×·¸Áö ¾ÊÀ¸¸é realfreeÇÔ¼ö´Â ³ªÁß¿¡ ±úÁú°ÍÀÌ´Ù. ¹öÆÛ´Â ´ÙÀ½°ú °°ÀÌ µ¤¾î ½áÁø´Ù. [0xeffffce0 + 32] = 0xeffffca8 [0xeffffca8 + 8] = 0xeffffce0 Á» ´õ ÀÚ¼¼ÇÏ°Ô ¾Ë°í ½ÍÀ¸¸é mxp.c ¿¹Á¦Äڵ带 º¸¶ó. IRIX³ª ¼Ö¶ó¸®½º¿¡¼­ malloc ±â¹ÝÀÇ ¹öÆÛ¿À¹öÇ÷οì ÀͽºÇ÷ÎÀÕÀ» ÇÏ·Á¸é ¾Æ·¡ÀÇ ¿ä ¾à³»¿ëÀ» Âü°íÇ϶ó. 1. ¿À¹öÇ÷ο츦 ÇÏ°íÀÚ ÇÏ´Â °Í µÚ¿¡ °¡Â¥ chunk¸¦ »ý¼ºÇÑ´Ù. 2. °¡Â¥ chunk´Â realfree·Î º¸³»Áö°í, ´ç½ÅÀÌ ¿À¹öÇÃ·Î¿ì ½ÃŲ chunk¿Í ÇÕ º´µÈ´Ù. 3. °¡Â¥ chunk°¡ realfree·Î º¸³»Áö±â À§Çؼ­´Â mallocÇÔ¼ö°¡ ´Ù½Ã È£ÃâµÇ°Å ³ª, free()ÇÔ¼ö°¡ ¿©·¯ ¹ø ½ÇÇàµÇ¾î¾ß ÇÑ´Ù. 4. ¿À¹öÇ÷οìµÈ ûũ´Â ¸¶Áö¸· chunk°¡ ¾Æ´Ï¾î¾ß ÇÑ´Ù. (the one before Bottom) 5. Jump-ahead¸¦ shellcode/nop-space ¾Õ¿¡ µ¡ºÙ¿© À߸øµÈ unlink-overwrite ÁÖ¼Ò¸¦ ½ÇÇàÇÏÁö ¾Êµµ·Ï ÇÑ´Ù. 6. ÀÌ·¯ÇÑ t_splay ·çƾÀ» »ç¿ëÇÑ °ø°Ý ¶ÇÇÑ °¡´ÉÇÏ´Ù. ±×·¯¹Ç·Î ´ç½ÅÀÌ ¿© ±â ¼³¸íÇÑ °ø°ÝÀ» »ç¿ëÇÒ ¼ö ¾ø´Ù¸é(0xff¹ÙÀÌÆ®¸¦ ¾µ ¼ö ¾øÀ»¶§), luke ¼Ò½º¸¦ »ç¿ëÇ϶ó. System VÀÇ malloc °ü¸®¹æ¹ý¿£ ¿©·¯°¡Áö ¾Ç¿ë¹æ¹ýÀÌ Á¸ÀçÇϸç, ÀÌ ¹æ¹ýµéÀº GNU ±¸Çö ¿¡¼­º¸´Ù ´õ À¯¿ëÇÏ´Ù. ÀÌ°ÍÀº malloc ÀÚü¸¦ ÀÌÇØÇϱ⠾î·Æ°Ô ¸¸µå´Â µ¿Àû Æ®¸®±¸Á¶ ü¸¦ »ç¿ëÇϱ⠶§¹®ÀÌ´Ù. ¸¸¾à ´ç½ÅÀÌ ¿©±â±îÁö Àоú´Ù¸é, ´ç½Å °íÀ¯ÀÇ malloc ±â¹Ý ¹öÆÛ¿À¹öÇÃ·Î¿ì ¹æ¹ýÀ» ãÀ» ¼ö ÀÖÀ¸¸®¶ó°í È®½ÅÇÑ´Ù. GNU C Library ±¸Çö ================== GNU C ¶óÀ̺귯¸®´Â ¾îÇø®ÄÉÀ̼ÇÀÌ ¿ä±¸ÇÑ ¸Þ¸ð¸® Á¶°¢¿¡ ´ëÇÑ Á¤º¸¸¦ º¸°üÇÏ°í ÀÖ ´Â µ¥, ÀÌ°ÍÀ» chunk¶ó ºÎ¸¥´Ù. ±×°ÍÀº ´ÙÀ½°ú °°´Ù.(malloc.c¿¡¼­ ÀÀ¿ëµÇ¾úÀ½) +---------------------------------------------------+ chunk-> | prev_size | +---------------------------------------------------+ | size | +---------------------------------------------------+ mem -> | data | : ... : +---------------------------------------------------+ nextchunk -> | prev_size ... | : : memÀº pointerÀÌ´Ù. malloc()ÀÇ ¸®ÅÏ°ªÀÌ´Ù. ¸¸¾à ´ç½ÅÀÌ ¾Æ·¡¿Í °°ÀÌ programÇÑ´Ù¸é unsigned char *mem = malloc(16); memÀº ±×¸²ÀÇ Æ÷ÀÎÅÍÀÌ°í, (mem - 8)Àº 'chunk' Æ÷ÀÎÅÍÀÌ´Ù. 'prev_size'´Â Ưº°ÇÑ ±â´ÉÀ» °¡Áö°í ÀÖ´Ù. ¸¸ÀÏ ÇöÀç chunk ¾ÕÀÇ chunk°¡ »ç¿ëµÇÁö ¾Ê´Â´Ù¸é(ÀÌ¹Ì freeµÇ¾ú´Ù¸é), prev_size´Â ±× ÀÌÀü chunkÀÇ Å©±â¸¦ ÀúÀåÇÏ°í ÀÖ´Ù. ±×·¸Áö ¾ÊÀº °æ¿ì(chunk°¡ »ç¿ëÁßÀ̸é)¿¡´Â prev_size´Â ÀÌ°ÍÀÇ 'data'ÀÇ ºÎºÐÀ¸·Î »ç¿ëµÇ¾î 4¹ÙÀÌÆ®¸¦ ÀúÀåÇÑ´Ù. 'size'´Â Ưº°ÇÑ Àǹ̸¦ Áö´Ñ´Ù. ¿¹»óÇÑ´ë·Î ±×°ÍÀº ¸Þ¸ð¸®ÀÇ ÇöÀç ºí·Ï(data ¼½¼Ç)ÀÇ Å©±â¸¦ ÀúÀåÇÑ´Ù. malloc()¸¦ È£ÃâÇϸé, ´ç½ÅÀÌ malloc()¿¡ ³Ñ°ÜÁØ Å©±â¿¡ 4 byte¿Í ´ÙÀ½ ´õºí ¿öµå °æ°èÀÇ Å©±â ¸¸Å­ÀÌ ´õ Ãß°¡µÈ´Ù. ±×·¡¼­ malloc(7)Àº malloc(16)ÀÌ µÇ°í malloc(20)Àº malloc (32)°¡ µÈ´Ù. malloc(0)Àº malloc(8)ÀÌ µÉ °ÍÀÌ´Ù. ÀÌ¿Í °°ÀÌ µ¿ÀÛÇÏ´Â ÀÌÀ¯´Â ³ªÁß ¿¡ ¼³¸íÇÑ´Ù. ÀÌ¿Í °°ÀÌ µ¡ºÙ¿©Áø 4byteÁß ÇÏÀ§ 3ºñÆ®´Â Ç×»ó 0ÀÌ°í, chunkÀÇ ½ÇÁ¦ ±æÀÌ¿¡´Â ¾Æ¹« ¿µÇâÀ» ¹ÌÄ¡Áö ¾Ê´Â´Ù. ´Ù¸¥ ¿ëµµ·Î »ç¿ëµÉ »ÓÀÌ´Ù. À̵éÀº chunkÀÇ Æ¯º°ÇÑ ¼Ó¼ºÀ» ÁöÁ¤Çϱâ À§ÇØ »ç¿ëµÈ´Ù. °¡Àå ÇÏÀ§ºñÆ®´Â PREV_INUSE¶ó°í Çϸç ÀÌÀüÀÇ chunk°¡ »ç ¿ëÁßÀÎÁö ¾Æ´ÑÁö¸¦ Ç¥½ÃÇÑ´Ù. ÀÌ°Í(PREV_INUSE)Àº ´ÙÀ½ chunk°¡ »ç¿ëÁßÀ̸é 1ÀÌ ¼³ Á¤µÈ´Ù. µÎ¹ø° ºñÆ®´Â ¸Þ¸ð¸® ¿µ¿ªÀÌ mmapµÇ¾î ÀÖÀ¸¸é ¼³Á¤µÈ´Ù. ÀÌ·± °æ¿ì´Â Ưº° ÇÑ °æ¿ì·Î ¿ì¸®´Â ½Å°æ¾²Áö ¾Ê´Â´Ù. ¼¼¹ø° ºñÆ®´Â »ç¿ëµÇÁö ¾Ê´Â´Ù. ÇöÀçÀÇ Ã»Å©°¡ »ç¿ëÁßÀÎÁö ¾Æ´ÑÁö¸¦ ½ÃÇèÇϱâ À§Çؼ­, ¿ì¸®´Â ´ÙÀ½ ûũÀÇ size°ª¿¡ ÀÖ´Â PREV_INUSEºñÆ®¸¦ °Ë»çÇØ ºÁ¾ß ÇÑ´Ù. ¿ì¸®°¡ free(mem)À» »ç¿ëÇÏ¿© ûũ¸¦ free()Çϸé, ¸î¸î °Ë»ç¸¦ ÇÑ ÈÄ ¸Þ¸ð¸®°¡ Ç®¸° ´Ù.(release) ¸¸¾à ±× ¸Þ¸ð¸®ÀÇ ÀÌ¿ô ºí·°ÀÌ free µÇ¾ú´Ù¸é(ÀÌ ¿ª½Ã PREV_INUSE ÇÁ·¡ ±×¸¦ °Ë»çÇÏ¿© È®ÀÎ) ±×µéÀº Àç»ç¿ë °¡´ÉÇÑ ºí·ÏÀÇ ¼ö´Â ÁÙÀÌ°í, Å©±â´Â ´Ã¸®±â À§ÇØ ÇÕº´µÈ´Ù. ¸¸¾à ÇÕº´ÀÌ ºÒ°¡´ÉÇÏ¸é ±× ´ÙÀ½ ûũ´Â PREV_INUSEºñÆ®°¡ Ŭ¸®¾î µÇ¾î Ç¥ ½ÃµÇ°í, ûũÀÇ 1 bit¸¦ º¯È¯ÇÑ´Ù. +----------------------------------+ chunk -> | prev_size | +----------------------------------+ | size | +----------------------------------+ mem -> | fd | +----------------------------------+ | bk | +----------------------------------+ | (old memory, can be zero bytes) | : : nextchunk -> | prev_size ... | : : º¸´Ù½ÃÇÇ ¸Þ¸ð¸®¿¡ µÎ°³ÀÇ »õ·Î¿î °ªÀÌ ÀÖ´Ù. ±× °÷Àº ¿¹Àü¿¡ ¿ì¸®°¡ data¸¦ ÀúÀåÇØ µÎ´ø °÷ÀÌ´Ù.('mem' Æ÷ÀÎÅÍ°¡ ÁöÁ¤ÇÏ´Â °÷) ÀÌ µÎ°³ÀÇ °ªÀº 'fd'¿Í 'bk'¶ó°í Çϸç chunkÀÇ ÀÌÀü°ú ÀÌÈĸ¦ °¡¸®Å°´Â Æ÷ÀÎÅ͵éÀÌ´Ù. À̵éÀº ÇÕº´µÇÁö ¾ÊÀº free memory ÀÇ ÀÌÁ߸µÅ©µå¸®½ºÆ®¸¦ °¡¸®Å²´Ù. free°¡ ½ÇÇàµÉ ¶§ ¸¶´Ù, ÀÌ ¸®½ºÆ®°¡ °Ë»çµÇ°í, Åë ÇÕµÇÁö ¾ÊÀº ºí·ÏµéÀÌ ÇÕÃÄÁø´Ù. Àüü ¸Þ¸ð¸®´Â ¾î¶² ÀÓÀÇÀÇ ¸Þ¸ð¸®¸¦ free ½Ãų ¶§ ¸¶´Ù ¸Å¹ø Çϳª·Î ÇÕÄ¡´Â °úÁ¤À» ¹Ýº¹ÇÑ´Ù. mallocÀÇ Å©±â´Â ÀÌ µÎ Æ÷ÀÎÅ͸¦ À§Çؼ­ ÃÖ¼ÒÇÑ 8¹ÙÀÌÆ®À̾î¾ß ÇÑ´Ù. ¸¸ÀÏ 'bk'Æ÷ÀÎ ÅÍ µÚ ¸Þ¸ð¸®¿¡ ¿¹Àü ÀÚ·á°¡ ³²¾Æ ÀÖÀ¸¸é ±× ¸Þ¸ð¸®´Â ´ÙÀ½ mallocÀÌ È£ÃâµÉ ¶§±îÁö »ç¿ëµÇÁö ¾Ê°í ³²¾Æ ÀÖ°Ô µÈ´Ù. ÀÌ °ü¸®¹æ¹ý¿¡¼­ Àç¹ÌÀÖ´Â °ÍÀº ³»ºÎÀÇ ÀüüÁ¤º¸°¡ in-band¿¡ ÀúÀåµÈ´Ù´Â °ÍÀÌ´Ù. -- a clear channeling ¹®Á¦(¹®ÀÚ¿­ ÀÚü°¡ Æ÷¸ä½ºÆ®¸µ ¸í·ÉÀÌ µÇ´Â °ÍÀ̳ª, ºÐ¸®°¡ ´ÉÇÑ ÀüÈ­¼±ÀÇ Á¦¾îä³Î, ¸Þ¸ð¸® ½ºÅó»¿¡ ¸®ÅÏ ¾îµå·¹½º°¡ ÀúÀåµÇ´Â °ÍµîÀÇ ¹®Á¦) ¿ì¸®°¡ ÀÌ ³»ºÎ °ü¸® Á¤º¸¸¦ µ¤¾î ¾µ¼ö ÀÖÀ¸¹Ç·Î, ¸¸¾à mallocÀ¸·Î ÇÒ´çµÈ ¿µ¿ªÀ» µ¤ ¾î ¾´´Ù¸é, µ¤¾î ¾´ ÀÌÈÄ ÀÌ°ÍÀÌ ¾î¶»°Ô 󸮵Ǵ Áö »ìÆì º¸¾Æ¾ß ÇÑ´Ù. Á¤»óÀûÀÎ ÇÁ ·Î±×·¥¿¡¼± ¸ðµç mallocµÈ ¿µ¿ªÀº ´Ù½Ã freeµÇ´Âµ¥, ¿ì¸®´Â malloc.c ÆÄÀÏ ¾È¿¡ ÀÖ´Â chunk_free() ÇÔ¼ö¸¦ »ìÆ캸ÀÚ. static void chunk_free(arena *ar_ptr, mchunkptr p) { size_t hd = p->size; /* its head field */ size_t sz; /* its size */ int idx; /* its bin index */ mchunkptr next; /* next contiguous chunk */ size_t nextsz; /* its size */ size_t prevsz; /* size of previous contiguous chunk */ mchunkptr bck; /* misc temp for linking */ mchunkptr fwd; /* misc temp for linking */ int islr; /* track whether merging with last_remainder */ check_inuse_chunk(ar_ptr, p); sz = hd & ~PREV_INUSE; next = chunk_at_offset(p, sz); nextsz = chunksize(next); mallocÀº ûũ¸¦ 'arenas'¶ó°í ºÒ¸®´Â Ưº°ÇÑ ±¸Á¶Ã¼¸¦ ÀÌ¿ëÇÏ¿© °ü¸®ÇÑ´Ù. Arenas´Â ÀÌÁ¦ ÇöÀçûũ°¡ 'top'ûũÀÇ °æ°è·Î Á÷Á¢ free µÉ ¼ö ÀÖ´ÂÁö °Ë»çÇÑ´Ù. 'top'ûũ´Â 'arenas'¿¡¼­ ¾ðÁ¦³ª ¸Þ¸ð¸®Ã»Å©ÀÇ °¡Àå À§¿¡ ÀÖ´Â °ÍÀ¸·Î, »ç¿ë°¡´ÉÇÑ ¸Þ¸ð¸®ÀÇ °æ °èÀÌ´Ù. Àüü if ºí·ÏÀº malloc ¿µ¿ª ¾È¿¡ ÀÖ´Â ÀüÇüÀûÀÎ ¹öÆÛ¿À¹öÇ÷ο쿡 ´ëÇØ ¹« °üÇÏ´Ù. if (next == top(ar_ptr)) /* merge with top */ { sz += nextsz; if (!(hd & PREV_INUSE)) /* consolidate backward */ { prevsz = p->prev_size; p = chunk_at_offset(p, -(long)prevsz); sz += prevsz; unlink(p, bck, fwd); } set_head(p, sz | PREV_INUSE); top(ar_ptr) = p; if ((unsigned long)(sz) >= (unsigned long)trim_threshold) main_trim(top_pad); return; } ÀÌÁ¦ ÀÌÀü ûũ°¡ »ç¿ëÁßÀÎÁö ¾Æ´ÑÁö¸¦ °Ë»çÇϱâ À§ÇØ ÇöÀçûũÀÇ 'size'¸¦ °Ë»çÇÑ´Ù (PREV_INUSE Ç÷¡±×¸¦ °Ë»çÇÏ´Â ¹æ¹ýÀ¸·Î). ¸¸¾à ´ÙÀ½°ú °°Àº °æ¿ì¶ó¸é µÎ ûũ´Â ÇÕ ÃÄÁö°Ô µÈ´Ù. islr = 0; if (!(hd & PREV_INUSE)) /* consolidate backward */ { prevsz = p->prev_size; p = chunk_at_offset(p, -(long)prevsz); sz += prevsz; if (p->fd == last_remainder(ar_ptr)) /* keep as last_remainder */ islr = 1; else unlink(p, bck, fwd); } ÇöÀç ûũÀÇ ´ÙÀ½ ûũ°¡ freeµÇ¾ú´ÂÁö °Ë»çÇÏ´Â ¹æ¹ýµµ ÀÌ¿Í ºñ½ÁÇÏ´Ù.(µÎ ûũ ´Ù À½ ûũÀÇ PREV_INUSE Ç÷¡±×¸¦ °Ë»çÇÑ´Ù.) ´ÙÀ½°ú °°Àº °æ¿ì¿¡µµ µÎ ûũ´Â Çϳª·Î ÇÕÃÄÁö°Ô µÈ´Ù. if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */ { sz += nextsz; if (!islr && next->fd == last_remainder(ar_ptr)) /* re-insert last_remainder */ { islr = 1; link_last_remainder(ar_ptr, p); } else unlink(next, bck, fwd); next = chunk_at_offset(p, sz); } else set_head(next, nextsz); /* clear inuse bit */ set_head(p, sz | PREV_INUSE); next->prev_size = sz; if (!islr) frontlink(ar_ptr, p, sz, idx, bck, fwd); } ¼Ö¶óµðÀÚÀ̳ʰ¡ ¿ì¸®¿¡°Ô º¸¿©ÁØ °Í ó·³, unlink¸ÅÅ©·Î¸¦ ÀÌ¿ëÇؼ­ ¸Þ¸ð¸® ÀÓÀÇÀÇ ¿µ¿ªÀ» µ¤¾î ¾²´Â °ÍÀÌ °¡´ÉÇÏ¸ç ¿©±â¿¡ ±× ¹æ¹ýÀ» ¼³¸íÇÑ´Ù. ÀϹÝÀûÀÎ ¹öÆÛ¿À¹öÇ÷οì Çö»óÀÌ ¹ß»ýÇÏ´Â °æ¿ì´Â ´ÙÀ½°ú °°´Ù. mem = malloc (24); gets (mem); ... free (mem); ÀÌ ¹æ¹ýÀ¸·Î mallocµÈ ûũ´Â ´ÙÀ½°ú °°´Ù. [ prev_size ] [ size P] [ 24 bytes ... ] (next chunk from now) [ prev_size ] [ size P] [ fd ] [ bk ] or [ data ... ] ´ç½ÅÀÌ º¸´Â ¹Ù¿Í °°ÀÌ ´ÙÀ½ ûũ´Â ¿ì¸®°¡ ¿À¹öÇÃ·Î¿ì ½ÃÅ°´Â ûũÀÇ µÞ °æ°è¿¡ ÀÖ ´Ù. ¿ì¸®´Â µÚ¿¡ ÀÖ´Â ¶Ç´Ù¸¥ ûũÀÇ Çì´õ¸¦ µ¤¾î ¾µ¼ö ÀÖ´Ù. Áï, ÇöÀç ûũÀÇ µ¥ÀÌ Å¸ ¿µ¿ªµÚÀÇ ¾î¶² °Íµµ µ¤¾î ¾µ¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. chunk_free ÇÔ¼öÀÇ µÞºÎºÐ¿¡ °¡¸é ÀÌ·¯ÇÑ Äڵ带 º¼¼ö ÀÖ´Ù. if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */ { sz += nextsz; if (!islr && next->fd == last_remainder(ar_ptr)) /* re-insert last_remainder */ { islr = 1; link_last_remainder(ar_ptr, p); } else unlink(next, bck, fwd); next = chunk_at_offset(p, sz); } inuse_bit_at_offsetÀº malloc.cÀÇ ½ÃÀÛ ºÎºÐ¿¡ ¸ÅÅ©·Î·Î Á¤ÀÇ µÇ¾î ÀÖ´Ù. #define inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) ¿ì¸®°¡ 'next' chunkÀÇ Çì´õ¸¦ Á¦¾îÇÒ ¼ö ÀÖÀ¸¹Ç·Î if ºí·Ï Àüü¸¦ ¸¶À½´ë·Î ÇÒ ¼ö ÀÖ´Ù. ¿ì¸®ÀÇ Ã»Å©°¡ °¡Àå ÃÖ»óÀ§ chunkÀÇ °æ°è¿¡ ÀÖÀ» ¶§¸¦ Á¦¿ÜÇÏ°í´Â if¹® ¾ÈÀÇ ³»¿ëÀº Èï¹Ì·ÓÁö ¾Ê´Ù. ±×·¡¼­ if¹® ¹ÛÀÇ ¸í·ÉµéÀ» ½ÇÇàÇϱâ À§ÇØ Á¶°ÇÀ» Á¶ÀýÇÒ ¼ö ÀÖ´Ù¸é ¿ì¸®´Â unlink¸¦ ºÎ¸¦ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ÀÌ°Í ¶ÇÇÑ ¸ÅÅ©·Î·Î Á¤ÀǵǾî ÀÖ´Ù. #define unlink(P, BK, FD) \ { \ BK = P->bk; \ FD = P->fd; \ FD->bk = BK; \ BK->fd = FD; \ } unlink´Â bck¿Í fwdÀÇ µÎ°³ÀÇ ÀÓ½ÃÆ÷ÀÎÅÍ º¯¼ö¿Í free chunk¸¦ À§ÇÑ Æ÷ÀÎÅ͸¦ °¡Áö°í È£ÃâµÈ´Ù. unlink´Â next chunk Çì´õ¿¡ ¾Æ·¡¿Í °°ÀÌ ½ÇÇàÇÑ´Ù. *(next->fd + 12) = next->bk *(next->bk + 8) = next->fd ±×°ÍµéÀº ¼­·Î ±³È¯µÇÁö´Â ¾ÊÁö¸¸ fd¿Í bk Æ÷ÀÎÅÍ´Â ´Ù¸¥ chunk¸¦ °¡¸®Å²´Ù. ÀÌ µÎ chunkµéÀÌ ¿¬°áµÇ°í Å×À̺í·Î ºÎÅÍ ÇöÀç ûũ¸¦ ¾ø¾Ø´Ù. ±×·¯¹Ç·Î, mallocÀ» ±â¹ÝÀ¸·Î ÇÏ´Â ¹öÆÛ¿À¹öÇ÷ο츦 ÀͽºÇ÷ÎÀÕ ½ÃÅ°±â À§Çؼ­ ¿ì¸® ´Â ´ÙÀ½ ûũ¿¡ °¡Â¥ Çì´õ¸¦ ¸¸µé¾î¾ß ÇÏ°í, ¿ì¸®ÀÇ Ã»Å©°¡ free µÇ±â¸¦ ±â´Ù·Á¾ß ÇÑ ´Ù. [buffer .... ] | [ prev_size ] [ size ] [ fd ] [ bk ] '|'Àº ûũÀÇ °æ°èÀÌ´Ù. ¿ì¸®°¡ ÁöÁ¤ÇÑ prev_size¿Í size´Â Áß¿äÇÏÁö ¾ÊÀº °ªÀÌ´Ù. ±×·¯³ª À̰͵éÀÌ Àß ÀÛµ¿ ÇÏ·Á¸é ´ÙÀ½°ú °°Àº Á¶°ÇÀÌ ¸¸Á·µÇ¾î¾ß ÇÑ´Ù. a) 'size'ÀÇ ÃÖÇÏÀ§ ºñÆ®´Â 0 À̾î¾ß ÇÑ´Ù. b) 'prev_size' ¿Í 'size' ´Â ÀÐÇôÁú Æ÷ÀÎÅÍ·Î ¾ÈÀüÇÏ°Ô ´õÇØÁ®¾ß ÇÑ´Ù. ±×·¡¼­ ¸î õ ¹Û¿¡ ¾ÈµÇ´Â ¾ÆÁÖ ÀÛÀº °ªÀ» »ç¿ëÇϰųª Null byte¸¦ ÇÇÇϱâ À§ÇØ 0xfffffffc °°Àº Å« °ªÀ» »ç¿ëÇÑ´Ù. c) ´ç½ÅÀº (chunk_boundary + size + 4) ÀÇ ÃÖÇÏÀ§ ºñÆ®°¡ zero·Î ¸ÂÃß¾î Áö°Ô º¸ ÀåÇØ¾ß ÇÑ´Ù. (0xfffffffc´Â Àß ÀÛµ¿ÇÒ °ÍÀÌ´Ù.) 'fd' ¿Í 'bk' ÀÇ °ªÀº ¾Æ·¡ÀÇ ¹æ¹ýÀ¸·Î Á¤ÇØÁø´Ù.(¼Ö¶ó µðÀÚÀ̳ʰ¡ Netscape ÀͽºÇà ·ÎÀÕ¿¡¼­ »ç¿ëÇÑ °Íó·³) fd = retloc - 12 bk = retaddr ±×·¯³ª (retaddr + 8)¿¡ ¾î¶² °ªÀÌ ¾²¿©Áú ¼ö ÀÖ°í ±× ÁÖ¼Ò¿¡ ÀÖ´ø ³»¿ëÀÌ Æı«µÉ ¼ö ÀÖ´Ù. ´ç½ÅÀº retaddr¿¡ °£´ÜÈ÷ '\xeb\x0c'¸¦ ³ÖÀ½À¸·Î½á ÀÌ°ÍÀ» ȸÇÇÇÒ ¼ö ÀÖ´Ù. ÀÌ °ÍÀº ³»¿ëÀ» Æı«½ÃÅ°´Â °ÍÀ» ³Ñ¾î¼­ 12¹ÙÀÌÆ®¸¦ Á¡ÇÁÇÒ °ÍÀÌ´Ù. <6> <4 bogus> | \xff\xff\xff\xfc \xff\xff\xff\xfc ¿©±â¼­ '|'´Â ûũ °æ°èÀÌ´Ù.(¿ì¸®°¡ ¿À¹öÇ÷οìÇÏ´Â ±× ÁöÁ¡) µÎ À½¼ö´Â free()ÀÇ ¸î °¡Áö °Ë»ç¸¦ Åë°úÇÏ°í NUL ¹ÙÀÌÆ®¸¦ ÇÇÇÑ´Ù. ±×·± ´ÙÀ½ ¿ì¸®´Â (retloc - 12) Æ÷ ÀÎÅÍ¿¡ 'jmp-ahead' Äڵ尡 ÀúÀåµÇ¾î ÀÖ´Â return address¸¦ ÀúÀåÇÑ´Ù. '|' ¾ÕÂÊ ¹ö ÆÛ¿¡ µé¾î°¡´Â °ªµéÀº óÀ½ 12¹ÙÀÌÆ®¸¦ Á¦¿ÜÇÏ°í ´Ù¸¥ x86 ÀͽºÇ÷ÎÀÕ°ú °°´Ù. óÀ½ 12¹ÙÀÌÆ®¸¦ ÀÌ¿Í °°ÀÌ ÇÏ´Â ÀÌÀ¯´Â unlink ¸ÅÅ©·Î¿¡ ÀÇÇØ ¿ì¸®°¡ ¿øÇÏÁö ¾Ê´Â ´Ù¸¥ °ªÀÌ ¾²¿©Áö±â ¶§¹®¿¡ ±× ºÎºÐÀ» Á¡ÇÁÇÏ¿© Á¤»óÀûÀÎ ½©Äڵ带 ½ÇÇàÇϱâ À§Çؼ­ÀÌ´Ù. Off-by-one / Off-by-five ------------------------ ÀÓÀÇÀÇ Æ÷ÀÎÅ͸¦ ¿À¹ö¶óÀÌÆ® ÇÒ ¼ö Àִµ¥, ¾î¶² °æ¿ì 5¹ÙÀÌÆ®¸¸ ¿À¹ö¶óÀÌÆ®ÇÒ ¼ö ÀÖ À» ¼öµµ ÀÖ°í, Ưº°ÇÑ °æ¿ì ´ÜÁö 1¹ÙÀÌÆ®¸¸ °¡´ÉÇÒ ¼öµµ ÀÖ´Ù. 5¹ÙÀÌÆ®¸¦ ¿À¹ö¶óÀÌÆ® ÇÒ ¶§ ¸Þ¸ð¸® ·¹À̾ƿôÀº ¾Æ·¡¿Í °°´Ù. [chunk a] [chunk b] ¿©±â¼­ ûũ a´Â ¿ì¸®ÀÇ Á¦¾îÇÏ¿¡ ÀÖ°í ¿À¹öÇ÷ο찡 °¡´ÉÇÑ Ã»Å©ÀÌ´Ù. ûũ b´Â ¿À ¹öÇ÷ο찡 ÀϾ ¶§ ÀÌ¹Ì ÇÒ´çµÇ¾î ÀÖ¾ú´Ù°í °¡Á¤ÇÏÀÚ. ûũ bÀÇ Ã³À½ ´Ù¼¸ ¹ÙÀÌÆ® ¸¦ µ¤¾î ¾²¸é, ûũ Çì´õÀÇ 'prev_size' Ç׸ñÀÇ 4¹ÙÀÌÆ®¿Í 'size'Ç׸ñÀÇ ÃÖÇÏÀ§ 1 ¹Ù ÀÌÆ®¸¦ ¿ì¸®ÀÇ ¶æ´ë·Î ¹Ù²Ü ¼ö ÀÖ´Ù. ÀÌÁ¦ ûũ b°¡ free() µÉ ¶§, 'size'ÀÇ PREV_INUSE Ç÷¡±×°¡ Ŭ¸®¾îµÈ »óÅÂÀ̱⠶§¹®¿¡ ÀÌÀü ûũ¿Í ÇÕº´ÇÏ·Á ÇÒ °ÍÀÌ´Ù. ¸¸ÀÏ ¿ì¸®°¡ 'prev_size'¿¡ ÀÛÀº °ªÀ» Áشٸé, ûũ aÀÇ Å©±âº¸´Ù ´õ ÀÛÀº °¡Â¥ ûũ ±¸Á¶¸¦ »õ·Î ¸¸µé ¼ö ÀÖ´Ù. [chunk a ... fakechunk ...] [chunk b] | p ûũ bÀÇ 'prev_size'´Â °ÅÁþ ûũ¸¦ °¡¸®Å²´Ù. ÀÌ·¯ÇÑ ¼³Á¤À» ÀÌ¿ëÇÏ¿© ÀͽºÇ÷ÎÀÕ ÀÌ °¡´ÉÇÑ ÄÚµå´Â ÀÌ¹Ì Àü¿¡ ³íÇÏ¿´´Ù. if (!(hd & PREV_INUSE)) /* consolidate backward */ { prevsz = p->prev_size; p = chunk_at_offset(p, -(long)prevsz); sz += prevsz; if (p->fd == last_remainder(ar_ptr)) /* keep as last_remainder */ islr = 1; else unlink(p, bck, fwd); } 'hd'´Â ûũ bÀÇ size Ç׸ñÀÌ´Ù. ¿ì¸®°¡ ±×°Í(hd)À» ¿À¹ö¶óÀÌÆ® ÇÒ¶§, ÇÏÀ§ 2ºñÆ®¸¦ Ŭ¸®¾îÇÑ´Ù. ±×·¡¼­ PREV_INUSE°¡ Ŭ¸®¾î µÇ¾î if Á¶°ÇÀÌ ¸¸Á·ÇÏ°Ô µÈ´Ù.(NULÀÌ »ç½Ç »ó ÀÌ·¯ÇÑ ÀÏÀ» ÇÑ´Ù.) if¹® ¾ÈÀÇ ¸î¸î ¸í·ÉÀ¸·Î ¿ø·¡ ûũ b¸¦ °¡¸®Ä×´ø Æ÷ÀÎÅÍ 'p'´Â ¿ì¸®ÀÇ °¡Â¥ ûũ¿¡ Àç¹èÄ¡µÈ´Ù. ±×¸®°í ³ª¼­, unlink ¸ÅÅ©·Î°¡ È£ÃâµÇ°í, ¿ì¸®´Â ¿©´À ¶§Ã³·³ Æ÷ÀÎÅ͸¦ µ¤¾î ¾µ¼ö ÀÖ´Ù. ÀÌ ±â»çÀÇ ¾ÕºÎºÐ¿¡¼­´Â ±âÁØ Ã»Å©ÀÇ ´ÙÀ½ ûũ¿ÍÀÇ ÇÕº´À» ÀÌ¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¼³ ¸íÇÏ¿´°í, Áö±ÝÀº ÀÌÀü ûũ¿ÍÀÇ ÇÕº´À» ÀÌ¿ëÇÏ´Â ¹æ¹ýÀ» ¼³¸íÇÏ¿´´Ù. ÀÌ°ÍÀÌ È¥¶õ½º·¯¿î°¡? malloc ¿À¹öÇ÷ο츦 ÀͽºÇ÷ÎÀÕ ÇÒ¶§, ±× ¼¼ºÎÀûÀÎ °Í¿¡ ´ëÇØ °ÆÁ¤ÇÏÁö ¸»¾Æ¶ó. ±× °ÍÀº ´ç½ÅÀÌ ´õ ³ÐÀº ¹üÀ§ÀÇ malloc ±â´ÉÀ» ÀÌÇØÇÏ¸é ´õ ¸íÈ®ÇØ Áú °ÍÀÌ´Ù. malloc ±¸ÇöÀÇ °³¿ä¿Í ¼³¸íÀ» ´õ Àß ¾Ë°í ½Í´Ù¸é, GNU C Library Âü°í ¸Å´º¾óÀ» ÀÚ¼¼ È÷ º¸¾Æ¶ó. ÀÌ°ÍÀº ¶ÇÇÑ non-malloc°ú °ü·ÃµÈ °ÍÀ» ÀÌÇØÇϱâ À§Çؼ­µµ ÁÁÀº ¹®¼­ÀÌ´Ù =============================================================================== ÀÌÇÏ »ý·«... =============================================================================== Thanks ====== I would like to thank all proofreaders and correctors. For some really needed corrections I thank MaXX, who wrote the more detailed article about GNU C Library malloc in this issue of Phrack, kudos to him ! :) References ========== [1] Solar Designer, http://www.openwall.com/advisories/OW-002-netscape-jpeg.txt [2] DD Sleator, RE Tarjan, "Self-Adjusting Binary Trees", 1985, http://www.acm.org/pubs/citations/journals/jacm/1985-32-3/p652-sleator/ http://www.math.tau.ac.il/~haimk/adv-ds-2000/sleator-tarjan-splay.pdf [3] The GNU C Library http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_toc.html [4] Solaris 8 Foundation Source Program http://www.sun.com/software/solaris/source/ |=[ EOF ]=---------------------------------------------------------------=|