Data structure alignment by binary operation
2013-08-21 16:37
176 查看
在寫C的過程中,我們會很自然地以為,我連續宣告一堆大小不一的char array。
經過Complier之後這些char array未必是連續擺放。至於為什麼就要談到我們今天的主角了alignment
以x86-32bit為例,
他喜歡一次讀取 4 Bytes (i.e. 32 bits),記憶中可以想成一格一格為 4 Bytes.其indes從 0 ~ 2^32 - 1
我們可以用 printf(sizeof(void *)); 來得知。machine在讀取指令時以多少Bytes為單位。
printf(sizeof(unsigned long));也行。
好讓每次讀取的位置皆為4的倍數,e.g. 0, 4, 8, 12 ...etc.
為了電腦的執行速度,Complier 會幫我們增加一些padding(填充),好讓每次讀取的位置都能是4的倍數。
實例:
在exploit(http://www.exploit-db.com/exploits/15285/)中
假設 def_ops 指向struct security_operations開頭
先看一下 Kernel source code
經過Complier之後這些char array未必是連續擺放。至於為什麼就要談到我們今天的主角了alignment
以x86-32bit為例,
他喜歡一次讀取 4 Bytes (i.e. 32 bits),記憶中可以想成一格一格為 4 Bytes.其indes從 0 ~ 2^32 - 1
我們可以用 printf(sizeof(void *)); 來得知。machine在讀取指令時以多少Bytes為單位。
printf(sizeof(unsigned long));也行。
好讓每次讀取的位置皆為4的倍數,e.g. 0, 4, 8, 12 ...etc.
為了電腦的執行速度,Complier 會幫我們增加一些padding(填充),好讓每次讀取的位置都能是4的倍數。
實例:
在exploit(http://www.exploit-db.com/exploits/15285/)中
假設 def_ops 指向struct security_operations開頭
先看一下 Kernel source code
struct security_operations { char name[SECURITY_NAME_MAX + 1]; //SECURITY_NAME_MAX 預設10,所以我們知道為何target要+11 int (*ptrace_access_check) (struct task_struct *child, unsigned int mode); int (*ptrace_traceme) (struct task_struct *parent); .... http://lxr.linux.no/linux+v2.6.36/include/linux/security.h#L1363[/code]
解讀一下exploittarget = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1)); //target想跳至ptrace_traceme第一個 sizeof(void *) 因為要跳過 int (*ptrace_access_check) 這個pointer。然而 name 這個 string 因為大小為11,但是為了做alignment。所以寫成(11 + sizeof(void *)) & ~(sizeof(void *) - 1)
11 長度的char array 為了要入memory 又要 alignment 4 的倍數情況下,是要 給他三格(i.e. 12 Bytes)
多出的那 1 Bytes, 就是我們所謂的padding。 而"&"這邊的技巧在Linux Kernel也有用到[註1]。& ~(sizeof(void *) - 1) == & 1100 //sizeof(void *) = 4而(11 + sizeof(void *)) & 1100 在 Binary的角度來看就是做mask來遮蔽後面2-bits 前面兩個2-bits則保留。而最後(11 + sizeof(void *)) & ~(sizeof(void *) - 1) == 12 Bytes用我們人類常用的10進位來舉例更貼近,假設記憶體中以0, 10, 20, 30 ...來存取指令。 假設有一到指令從0放到15的位置。為了alignment 10 的倍數, 我們必須這指令從0~20。 實作上就是 15 + 10 = 25 個位數的地方mask掉變成20。 就像前面我們做& ~(sizeof(void *) - 1) 一樣。[註1] #define PAGE_MASK (~(PAGE_SIZE-1))
http://lxr.free-electrons.com/source/arch/arm/include/asm/page.h#L15
相关文章推荐
- Data Structure Array: Sort elements by frequency
- Data Structure Binary Tree: Inorder Tree Traversal without Recursion
- Data Structure Binary Tree: Inorder Tree Traversal without recursion and without stack!
- Data structure alignment
- Data Structure Binary Tree: Iterative Postorder Traversal
- 【DataStructure&AlgorithmInJava】Ch02-BinarySearchDemo
- Data Structure Binary Tree: Level order traversal in spiral form
- Data Structure Binary Search Tree: Find k-th smallest element in BST (Order Statistics in BST)
- Structure Member Alignment, Padding and Data Packing
- Data Structure Binary Tree: Construct Tree from given Inorder and Preorder traversals
- Data Structure Binary Tree: Check if a given Binary Tree is SumTree
- 【DataStructure&AlgorithmInJava】Ch02-OrderArray w binarySearch
- Data Structure Binary Tree: Check for Children Sum Property in a Binary Tree
- Data Structure Binary Tree: Connect nodes at same level using constant extra space
- dataStructure@ Binary Search Tree
- Data Structure Binary Tree: Populate Inorder Successor for all nodes
- Data Structure Binary Tree: Convert a given Binary Tree to Doubly Linked List
- Data Structure Binary Search Tree: Inorder Successor in Binary Search Tree
- Data Structure Binary Tree: Convert a given tree to its Sum Tree
- Data Structure Binary Tree: Print ancestors of a given binary tree node without recursion