前置:這里使用的linux版本是4.8,x86體系。
start_kernel是過了引導階段,進入到了內核啟動階段的入口。函數在init/main.c中。
set_task_stack_end_magic(&init_task);
這個函數是設置操作系統的第一個進程init。
這個init_task變量是怎么來的呢?從init/init_task.c中初始化的。
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
而這個INIT_TASK的初始化在init/init_task.h:
#define INIT_TASK(tsk) \
{ \
.state = 0, \
.stack = init_stack, \
.usage = ATOMIC_INIT(2), \
.flags = PF_KTHREAD, \
.prio = MAX_PRIO-20, \
.static_prio = MAX_PRIO-20, \
.normal_prio = MAX_PRIO-20, \
...
這里使用的是gcc的結構體初始化方式。http://blog.csdn.net/justlinux2010/article/details/7494754 。這個結構體是根據task_struct結構進行初始化的。
再回到set_task_stack_end_magic
void set_task_stack_end_magic(struct task_struct *tsk)
{
unsigned long *stackend;
stackend = end_of_stack(tsk);
*stackend = STACK_END_MAGIC; /* for overflow detection */
}
這個end_of_stack 在include/linux/sched.h中。它的意思是獲取棧邊界地址。然后把棧底地址設置為STACK_END_MAGIC。這個作為棧溢出的標記。
每個進程創建的時候,系統會為這個進程創建2個頁大小的內核棧。這個內核棧底下是thread_info結構。高位是棧。

http://blog.chinaunix.net/uid-20543672-id-2996319.html
這里的STACK_END_MAGIC就是設置在thread_info結構的上面。比如如果你寫了一個無限循環,導致棧使用不斷增長了,那么,一旦把這個標記未修改了,就導致了棧溢出的錯誤。
smp_setup_processor_id();
下面是這個
smp_setup_processor_id(); // 設置smp模型的處理器id
smp模型指的是對稱多處理模型(Symmetric Multi-Processor),與它對應的是NUMA非一致存儲訪問結構(Non-Uniform Memory Access)和MPP 海量並行處理結構(Massive Parallel Processing)。它們的區別分別在於,SMP指的是多個CPU之間是平等關系,共享全部總線,內存和I/O等。但是這個結構擴展性不好,往往CPU數量多了之后,很容易遇到搶占資源的問題。NUMA結構則是把CPU分模塊,每個模塊具有獨立的內存,I/O插槽等。各個模塊之間通過互聯模塊進行數據交互。但是這樣,就表示了有的內存數據在這個CPU模塊中,那么處理這個數據當然最好是選擇當前的CPU模塊,這樣每個CPU實際上地位就不一致了。所以叫做非一致的存儲訪問結構。而MPP呢,則是由多個SMP服務器通過互聯網方式連接起來。
支持SMP模型的CPU有AMD/AMD64。而支持NUMA的有X86等。而這里的代碼,smp_setup_process_id在普通情況下是空實現,在不同的體系,比如arch/arm/kernel/setup.c, line 586
就有對應的邏輯了。
debug_objects_early_init();
這個函數的實際代碼在lib/debugobject.c
void __init debug_objects_early_init(void)
{
int i;
for (i = 0; i < ODEBUG_HASH_SIZE; i++)
raw_spin_lock_init(&obj_hash[i].lock);
for (i = 0; i < ODEBUG_POOL_SIZE; i++)
hlist_add_head(&obj_static_pool[i].node, &obj_pool);
}
可以看到,它主要是用來對obj_hash,obj_static_pool這兩個全局變量進行初始化設置。這兩個全局變量在進行調試的時候會使用到。
http://m.blog.chinaunix.net/uid-27717694-id-4425488.html
boot_init_stack_canary();
這個函數是做什么的呢?我們要說堆棧溢出漏洞,它的意思就是動態分配的堆中,不按照本來分配的大小進行設置,而是使用某種方法,設置變量分配大小之外的數據。甚至設置到了函數棧的數據了,那么,這個時候就可能會被調用到注入的某個函數中了。具體攻擊示例看:http://www.ibm.com/developerworks/cn/linux/l-overflow/
那么,和前面的end_magic邏輯一樣,我們在堆和棧的中介處設置一個標記位(叫做canary word)。當這個位被修改的時候,我們就知道了,這個時候存在堆棧溢出,就進行錯誤處理。
那么這個標記位的值是怎么樣子的,就是使用這個函數。這個也和CPU架構有關系了,比如在x86的系統中,是隨機產生的。https://www.ibm.com/developerworks/cn/linux/l-cn-gccstack/
