Skip to content

Latest commit

 

History

History
1163 lines (960 loc) · 31.2 KB

a10c_157.md

File metadata and controls

1163 lines (960 loc) · 31.2 KB

1000### Neuromancer : 157 주차

일시 : 2016.09.03 (157 주차 스터디 진행)

모임명 : neuromancer.kr

장소 : 토즈 서현점

장소지원 : 공개 소프트웨어 개발자 커뮤니티 지원 프로그램

참여인원 : 2명

============

157주차 진도

  • ᇂ157차 시작 위치
    • start_kernel 1 ~/init/main.c
    • rest_init 968 ~/init/main.c
    • kernel_thread 453 ~/init/main.c
    • do_fork 1689 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
    • copy_process 1642 p = copy_process(clone_flags, stack_start, stack_size,

157 주차 함수 호출 구조

  • call: start_kernel()
  • lockdep_init()
  • smp_setup_processor_id()
  • debug_objects_early_init()
  • boot_init_stack_canary()
  • cgroup_init_early()
  • local_irq_disable()
  • boot_cpu_init()
  • page_address_init()
  • pr_notice()
  • setup_arch()
  • mm_init_owner()
  • mm_init_cpumask()
  • setup_command_line
  • build_all_zonelists()
  • page_alloc_init()
  • pr_notice()
  • parse_early_param()
  • parse_args()
  • jump_label_init()
  • setup_log_buf()
  • pidhash_init()
  • vfs_caches_init_early()
  • sort_main_extable()
  • trap_init()
  • mm_init()
  • sched_init()
  • preempt_disable()
  • irqs_disabled()
  • local_irq_disabled()
  • idr_init_cache()
  • rcu_init()
  • tick_nohz_init()
  • contect_tracking_init()
  • radix_tree_init()
  • early_irq_init()
  • init_IRQ()
  • tick_init()
  • init_timers()
  • hrtimers_init()
  • softirq_init()
  • timekeeping_init()
  • time_init()
  • sched_clock_postinit()
  • pref_event_init()
  • profile_init()
  • call_function_init()
  • irqs_disabled()
  • local_irq_enabled()
  • kmem_cache_init_late()
  • console_init()
  • lockdep_init()
  • lockdep_info()
  • locking_selftest()
  • virt_to_page()
  • page_to_pfn()
  • page_cgroup_init()
  • debug_objects_mem_init()
  • kmemleak_init()
  • setup_per_cpu_pageset()
  • numa_policy_init()
  • sched_clock_init()
  • calibrate_delay()
  • pidmap_init()
  • anon_vma_init()
  • thread_info_cache_init()
  • cred_init()
  • fork_init()
  • proc_caches_init()
  • buffer_init()
  • key_init()
  • security_init()
  • dbg_late_init()
  • vfs_caches_init()
  • signals_init()
  • page_writeback_init()
  • proc_root_init()
  • cgroup_init()
  • cpuset_init()
  • taskstats_init_early()
  • delayacct_init()
  • check_bugs()
  • acpi_early_init()
  • sfi_init_late()
  • efi_enabled(EFI_RUNTIME_SERVICES)
  • ftrace_init()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starting()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()

start_kernel()

  • call: start_kernel()
  • lockdep_init()
  • smp_setup_processor_id()
  • debug_objects_early_init()
  • boot_init_stack_canary()
  • cgroup_init_early()
  • local_irq_disable()
  • boot_cpu_init()
  • page_address_init()
  • pr_notice()
  • setup_arch()
  • mm_init_owner()
  • mm_init_cpumask()
  • setup_command_line
  • build_all_zonelists()
  • page_alloc_init()
  • pr_notice()
  • parse_early_param()
  • parse_args()
  • jump_label_init()
  • setup_log_buf()
  • pidhash_init()
  • vfs_caches_init_early()
  • sort_main_extable()
  • trap_init()
  • mm_init()
  • sched_init()
  • preempt_disable()
  • irqs_disabled()
  • local_irq_disabled()
  • idr_init_cache()
  • rcu_init()
  • tick_nohz_init()
  • contect_tracking_init()
  • radix_tree_init()
  • early_irq_init()
  • init_IRQ()
  • tick_init()
  • init_timers()
  • hrtimers_init()
  • softirq_init()
  • timekeeping_init()
  • time_init()
  • sched_clock_postinit()
  • pref_event_init()
  • profile_init()
  • call_function_init()
  • irqs_disabled()
  • local_irq_enabled()
  • kmem_cache_init_late()
  • console_init()
  • lockdep_init()
  • lockdep_info()
  • locking_selftest()
  • virt_to_page()
  • page_to_pfn()
  • page_cgroup_init()
  • debug_objects_mem_init()
  • kmemleak_init()
  • setup_per_cpu_pageset()
  • numa_policy_init()
  • sched_clock_init()
  • calibrate_delay()
  • pidmap_init()
  • anon_vma_init()
  • thread_info_cache_init()
  • cred_init()
  • fork_init()
  • proc_caches_init()
  • buffer_init()
  • key_init()
  • security_init()
  • dbg_late_init()
  • vfs_caches_init()
  • signals_init()
  • page_writeback_init()
  • proc_root_init()
  • cgroup_init()
  • cpuset_init()
  • taskstats_init_early()
  • delayacct_init()
  • check_bugs()
  • acpi_early_init()
  • sfi_init_late()
  • efi_enabled()
  • efi_late_init()
  • efi_free_boot_services()
  • ftrace_init()
  • rest_init()
// ARM10C 20130824
asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern const struct kernel_param __start___param[], __stop___param[];
	// ATAG,DTB 정보로 사용

	/*
	 * Need to run as early as possible, to initialize the
	 * lockdep hash:
	 */
	lockdep_init();
	smp_setup_processor_id();
	debug_objects_early_init();

	/*
	 * Set up the the initial canary ASAP:
	 */
	boot_init_stack_canary();

	cgroup_init_early();
	// cgroup 를 사용하기 위한 cgroup_dummy_root, cgroup_subsys 의 구조체 초기화 수행

	local_irq_disable();
	// IRQ를 disable 함

	early_boot_irqs_disabled = true;
	// early_boot_irqs_disabled: true

/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
	boot_cpu_init();
	// 현재 cpu(core id)를 얻어서 cpu_XXX_bits[] 의 cpu를 셋한다.
	
	page_address_init();
	// 128개의 page_address_htable 배열을 초기화

	pr_notice("%s", linux_banner);
	// 배너:
	//	Linux version 2.6.37_DM385_IPNC_3.50.00
	// 	(a0875405@bangvideoapps01) (gcc version 4.5.3 20110311
	// 	(prerelease) (GCC) ) #1 Fri Dec 21 17:27:08 IST 2012

	setup_arch(&command_line);

	mm_init_owner(&init_mm, &init_task); // null function
	mm_init_cpumask(&init_mm); // null function

	// command_line: exynos5420-smdk5420.dts 파일의 chosen node 의 bootarg 값
	// "console=ttySAC2,115200 init=/linuxrc"
	setup_command_line(command_line);
	// saved_command_line 및 static_command_line 할당

	setup_nr_cpu_ids();
	setup_per_cpu_areas();
	// pcpu 구조체를 만들어 줌 (mm/percpu.c)

	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
	// boot cpu 0의 pcpu 영역의 base주소를 core register에 설정해줌

	build_all_zonelists(NULL, NULL);

	page_alloc_init();
	// cpu_chain에 page_alloc_cpu_notify를 연결함 (mutex lock/unlock 사용)

	// boot_command_line: "console=ttySAC2,115200 init=/linuxrc"
	pr_notice("Kernel command line: %s\n", boot_command_line);
	// "Kernel command line: console=ttySAC2,115200 init=/linuxrc"

	parse_early_param();
	// setup_arch에서 수행했던 작업 다시 수행
	// command arg에서 각 요소들을 파싱하여 early init section으로 설정된 디바이스 초기화.
	// 우리는 serial device가 검색이 되지만 config설정은 없어서 아무것도 안함.

	// static_command_line: "console=ttySAC2,115200 init=/linuxrc"
	parse_args("Booting kernel", static_command_line, __start___param,
		   __stop___param - __start___param,
		   -1, -1, &unknown_bootoption);
	// DTB에서 넘어온 bootargs를 파싱하여 param, val을 뽑아내고 그에 대응되는
	// kernel_param 구조체에 값을 등록함.

	jump_label_init();
	// HAVE_JUMP_LABEL 이 undefined 이므로 NULL 함수

	/*
	 * These use large bootmem allocations and must precede
	 * kmem_cache_init()
	 */
	setup_log_buf(0);
	// defalut log_buf의 크기는 __LOG_BUF_LEN: 0x20000 (128KB) 임
	// early_param 에서 호출했던 log_buf_len 값이 있다면 log_buf의 크기를 넘어온 크기로 만듬

	pidhash_init();
	// pidhash의 크기를 16kB만큼 할당 받고 4096개의 hash list를 만듬

	vfs_caches_init_early();
	// Dentry cache, Inode-cache용 hash를 위한 메모리 공간을 각각 512kB, 256kB만큼 할당 받고,
	// 131072, 65536개 만큼 hash table을 각각 만듬

	sort_main_extable();
	// extable 을 cmp_ex를 이용하여 sort수행

	trap_init(); // null function

	mm_init();
	// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
	// pcpu 메모리, vmlist 는 slab으로 이관

	/*
	 * Set up the scheduler prior starting any interrupts (such as the
	 * timer interrupt). Full topology setup happens at smp_init()
	 * time - but meanwhile we still have a functioning scheduler.
	 */
	sched_init();
	// scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅

	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();
	// preempt count를 증가시켜 preemption 못하도록 막음

	// irqs_disabled(): 1
	if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n"))
		local_irq_disable();

	idr_init_cache();
	// integer ID management로 사용하는 idr_layer_cache에 kmem_cache#21 을 생성 및 초기화 후 할당

	rcu_init();
	// rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함

	tick_nohz_init(); // null function
	context_tracking_init(); // null function

	radix_tree_init();
	// radix tree로 사용하는 radix_tree_node_cachep에 kmem_cache#20을 생성 및 초기화 후 할당하고
	// height_to_maxindex을 초기화 수행

	/* init some links before init_ISA_irqs() */
	early_irq_init();
	// irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
	// allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

	init_IRQ();
	// gic, combiner이 사용할 메모리 할당과 자료 구조 설정,
	// gic irq (0~15), combiner irq (32~63) interrupt 를 enable 시킴

	tick_init();
	// tick 관련 mask 변수를 0으로 초기화 수행

	init_timers();
	// boot_tvec_bases의 맴버 값을 초기화하고 timers_nb를 cpu_notifier 에 등록,
	// softirq_vec[1] 에 run_timer_softirq 등록하여 초기화 수행

	hrtimers_init();
	// hrtimer_bases의 맴버 값을 초기화하고 hrtimers_nb를 cpu_notifier 에 등록,
	// softirq_vec[8] 에 run_hrtimer_softirq 등록하여 초기화 수행

	softirq_init();
	// tasklet_vec, tasklet_hi_vec 맴버 값을 초기화하고,
	// softirq_vec[6]에 tasklet_action, softirq_vec[0]에 tasklet_hi_action 등록하여 초기화 수행

	timekeeping_init();
	// ntp 관련 전역변수 초기화, timekeeper, shadow_timekeeper의 맴버값 초기화 수행

	time_init();
	// timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
	// timer event를 위한 timer irq (MCT) 초기화 수행

	sched_clock_postinit();
	// sched_clock_timer을 초기화 수행

	perf_event_init(); // null function
	profile_init(); // null function
	call_function_init();
	// 각 cpu core에서 사용할 call_single_queue를 맴버값 초기화
	// cfd_data 맴버값을 초기화하고 pcp에서 사용할 메모리 공간 할당
	// cpu_chain에 hotplug_cfd_notifier 를 등록함

	// irqs_disabled(): 1
	WARN(!irqs_disabled(), "Interrupts were enabled early\n");

	// early_boot_irqs_disabled: true
	early_boot_irqs_disabled = false;
	// early_boot_irqs_disabled: false

	local_irq_enable();
	// IRQ를 enable 함

	kmem_cache_init_late(); // null function

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init();

	// panic_later: NULL
	if (panic_later)
		panic(panic_later, panic_param);

	lockdep_info(); // null function

	/*
	 * Need to run this when irqs are enabled, because it wants
	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
	 * too:
	 */
	locking_selftest(); // null function

#ifdef CONFIG_BLK_DEV_INITRD // CONFIG_BLK_DEV_INITRD=y
	// initrd_start: NULL, initrd_below_start_ok: 0
	if (initrd_start && !initrd_below_start_ok &&
	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
		pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
		    page_to_pfn(virt_to_page((void *)initrd_start)),
		    min_low_pfn);
		initrd_start = 0;
	}
#endif

	page_cgroup_init(); // null function
	debug_objects_mem_init(); // null function
	kmemleak_init(); // null function

	setup_per_cpu_pageset();
	// per cpu가 사용하는 pageset의 각각의 zone 맴버값 초기화 수행

	numa_policy_init(); // null function

	// late_time_init: NULL
	if (late_time_init)
		late_time_init();

	sched_clock_init();
	// sched_clock_running 값을 1 로 초기화 수행

	calibrate_delay();
	// BogoMIPS값을 결정하기위한 계산을 수행하고 결과를 출력함

	pidmap_init();
	// pidmap 을 사용하기 위한 초기화 수행

	anon_vma_init();
	// anon vma 를 사용하기 위한 kmem_cache 할당자 초기화 수행

#ifdef CONFIG_X86 // CONFIG_X86=n
	if (efi_enabled(EFI_RUNTIME_SERVICES))
		efi_enter_virtual_mode();
#endif
	thread_info_cache_init(); // null function
	cred_init();
	// credentials 를 사용하기 위한 kmem_cache 할당자 초기화 수행

	// totalram_pages: 총 free된 page 수
	fork_init(totalram_pages);
	// task_struct 를 사용하기 위한 kmem_cache 할당자 초기화 수행
	// max_threads값을 계산하여 init_task에 threads값의 limit 값 설정함

	proc_caches_init();
	// sighand_struct, signal_struct, files_struct, fs_struct, mm_struct, vm_area_struct, nsproxy
	// 를 사용하기 위한 kmem_cache 할당자 및 percpu list 초기화 수행

	buffer_init();
	// buffer_head 를 사용하기 위한 kmem_cache 할당자 및 max_buffer_heads 값 초기화 수행

	key_init(); // null funtion
	security_init(); // null funtion
	dbg_late_init(); // null funtion

	// totalram_pages: 총 free된 page 수
	vfs_caches_init(totalram_pages);
	// virtual file system을 위한 names, dentry, inode, filp, mount cache 생성 후
	// file system 을 위한 초기화 수행 및 mount 수행, block, char dev 사용을 위한 초기화 수행

	signals_init();
	// signal을 사용하기 위한 kmem_cache 를 생성

	/* rootfs populating might need page-writeback */
	page_writeback_init();
	// page writeback을 위한 global_dirty_limit, ratelimit_pages 값을 초기화 수행

#ifdef CONFIG_PROC_FS // CONFIG_PROC_FS=y
	proc_root_init();
	// proc filesystem을 등록 하고 proc을 사용하기 위한 dentry, inode 생성 후
	// sysctl_base_table 에 등록된 kernel, vm, fs, debug, dev의 dir, files 를 recursive 하게 RB Tree 를 구성함
#endif
	cgroup_init();
	// cgroup에서 사용하는 sub system 인 debug_subsys, cpu_cgroup_subsys, cpuacct_subsys, freezer_subsys 를 등록 하고
	// init_css_set.subsys 를 이용하여 hash key 값 생성, cgroup 을 위한 kobject 를 생성, cgroup용 fils system type을 추가 하여
	// filesystem 에 등록함, cgroup 을 위한 proc 생성.

	cpuset_init(); // null function
	taskstats_init_early(); // null function
	delayacct_init(); // null function

	check_bugs();
	// page 2개를 할당 받고 할당 받은 메모리에값을 쓰고 비교하여
	// 메모리 동작을 테스트 수행한 이후 다시 메모리를 반환함

	acpi_early_init(); /* before LAPIC and SMP init */  // null function
	sfi_init_late(); // null function

	// efi_enabled(EFI_RUNTIME_SERVICES): 1
	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
		efi_late_init(); // null function
		efi_free_boot_services(); // null function
	}

	ftrace_init(); // null function

	/* Do the rest non-__init'ed, we're now alive */
	rest_init();
}	

rest_init()

  • start_kernel()
  • rest_init()
  • call: rest_init()
// ARM10C 20160827
static noinline void __init_refok rest_init(void)
{
	int pid;

	rcu_scheduler_starting(); // null function
	/*
	 * We need to spawn init first so that it obtains pid 1, however
	 * the init task will end up wanting to create kthreads, which, if
	 * we schedule it before we create kthreadd, will OOPS.
	 */
	// CLONE_FS: 0x00000200, CLONE_SIGHAND: 0x00000800
	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

kernel_thread()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
// ARM10C 20160827
// kernel_init, NULL, 0x00000A00
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
	// flags: 0x00000A00, CLONE_VM: 0x00000100, CLONE_UNTRACED: 0x00800000,
	// fn: kernel_init, arg: NULL
	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
		(unsigned long)arg, NULL, NULL);
}

do_fork()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
// ARM10C 20160827
// flags: 0x00800B00, fn: kernel_init, arg: NULL, NULL, NULL
long do_fork(unsigned long clone_flags,
	      unsigned long stack_start,
	      unsigned long stack_size,
	      int __user *parent_tidptr,
	      int __user *child_tidptr)
{
	struct task_struct *p;
	int trace = 0;
	// trace: 0

	long nr;

	/*
	 * Determine whether and which event to report to ptracer.  When
	 * called from kernel_thread or CLONE_UNTRACED is explicitly
	 * requested, no event is reported; otherwise, report if the event
	 * for the type of forking is enabled.
	 */
	// clone_flags: 0x00800B00, CLONE_UNTRACED: 0x00800000
	if (!(clone_flags & CLONE_UNTRACED)) {
		if (clone_flags & CLONE_VFORK)
			trace = PTRACE_EVENT_VFORK;
		else if ((clone_flags & CSIGNAL) != SIGCHLD)
			trace = PTRACE_EVENT_CLONE;
		else
			trace = PTRACE_EVENT_FORK;

		if (likely(!ptrace_event_enabled(current, trace)))
			trace = 0;
	}

	// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, trace: 0
	p = copy_process(clone_flags, stack_start, stack_size,
			 child_tidptr, NULL, trace);

do_fork()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
// ARM10C 20160827
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, NULL, trace: 0
static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
	int retval;
	struct task_struct *p;

	// clone_flags: 0x00800B00, CLONE_NEWNS: 0x00020000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
		return ERR_PTR(-EINVAL);

	// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
		return ERR_PTR(-EINVAL);

	/*
	 * Thread groups must share signals as well, and detached threads
	 * can only be started up within the thread group.
	 */
	// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000, CLONE_SIGHAND: 0x00000800
	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
		return ERR_PTR(-EINVAL);

	/*
	 * Shared signal handlers imply shared VM. By way of the above,
	 * thread groups also imply shared VM. Blocking this case allows
	 * for various simplifications in other code.
	 */
	// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800, CLONE_VM: 0x00000100
	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
		return ERR_PTR(-EINVAL);

	/*
	 * Siblings of global init remain as zombies on exit since they are
	 * not reaped by their parent (swapper). To solve this and to avoid
	 * multi-rooted process trees, prevent global and container-inits
	 * from creating siblings.
	 */
	// clone_flags: 0x00800B00, CLONE_PARENT: 0x00008000, SIGNAL_UNKILLABLE: 0x00000040
	// current->signal->flags
	// current: &init_task
	if ((clone_flags & CLONE_PARENT) &&
				current->signal->flags & SIGNAL_UNKILLABLE)
		return ERR_PTR(-EINVAL);

	if (clone_flags & CLONE_SIGHAND) {
		if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
		    (task_active_pid_ns(current) !=
				current->nsproxy->pid_ns_for_children))

task_active_pid_ns()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • call: task_active_pid_ns()
struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
{
	return ns_of_pid(task_pid(tsk));
}
EXPORT_SYMBOL_GPL(task_active_pid_ns);

ns_of_pid()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • call: task_active_pid_ns()
  • task_pid()
  • call: task_pid()
static inline struct pid *task_pid(struct task_struct *task)
{
	return task->pids[PIDTYPE_PID].pid;
}
  • call: ns_of_pid(task_pid(tsk))
static inline struct pid_namespace *ns_of_pid(struct pid *pid)
{
	struct pid_namespace *ns = NULL;
	if (pid)
		ns = pid->numbers[pid->level].ns;
	return ns;
}
  • return copy_process()

copy_process()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • security_task_create(clone_flags);
// ARM10C 20160827
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, NULL, trace: 0
static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
	int retval;
	struct task_struct *p;

	// clone_flags: 0x00800B00, CLONE_NEWNS: 0x00020000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
		return ERR_PTR(-EINVAL);

	// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
		return ERR_PTR(-EINVAL);

	/*
	 * Thread groups must share signals as well, and detached threads
	 * can only be started up within the thread group.
	 */
	// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000, CLONE_SIGHAND: 0x00000800
	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
		return ERR_PTR(-EINVAL);

	/*
	 * Shared signal handlers imply shared VM. By way of the above,
	 * thread groups also imply shared VM. Blocking this case allows
	 * for various simplifications in other code.
	 */
	// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800, CLONE_VM: 0x00000100
	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
		return ERR_PTR(-EINVAL);

	/*
	 * Siblings of global init remain as zombies on exit since they are
	 * not reaped by their parent (swapper). To solve this and to avoid
	 * multi-rooted process trees, prevent global and container-inits
	 * from creating siblings.
	 */
	// clone_flags: 0x00800B00, CLONE_PARENT: 0x00008000, SIGNAL_UNKILLABLE: 0x00000040
	// current->signal->flags
	// current: &init_task
	if ((clone_flags & CLONE_PARENT) &&
				current->signal->flags & SIGNAL_UNKILLABLE)
		return ERR_PTR(-EINVAL);

	/*
	 * If the new process will be in a different pid or user namespace
	 * do not allow it to share a thread group or signal handlers or
	 * parent with the forking task.
	 */
	if (clone_flags & CLONE_SIGHAND) {
		if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
		    (task_active_pid_ns(current) !=
				current->nsproxy->pid_ns_for_children))
			return ERR_PTR(-EINVAL);
	}

	retval = security_task_create(clone_flags);

security_task_create()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • security_task_create(clone_flags);
  • call: security_task_create()
static inline int security_task_create(unsigned long clone_flags)
{
	return 0;
}

copy_process()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • security_task_create(clone_flags);
// ARM10C 20160827
// clone_flags: 0x00800B00, stack_start: kernel_init, stack_size: 0, child_tidptr: 0, NULL, trace: 0
static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
	int retval;
	struct task_struct *p;

	// clone_flags: 0x00800B00, CLONE_NEWNS: 0x00020000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
		return ERR_PTR(-EINVAL);

	// clone_flags: 0x00800B00, CLONE_NEWUSER: 0x10000000, CLONE_FS: 0x00000200
	if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
		return ERR_PTR(-EINVAL);

	/*
	 * Thread groups must share signals as well, and detached threads
	 * can only be started up within the thread group.
	 */
	// clone_flags: 0x00800B00, CLONE_THREAD: 0x00010000, CLONE_SIGHAND: 0x00000800
	if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
		return ERR_PTR(-EINVAL);

	/*
	 * Shared signal handlers imply shared VM. By way of the above,
	 * thread groups also imply shared VM. Blocking this case allows
	 * for various simplifications in other code.
	 */
	// clone_flags: 0x00800B00, CLONE_SIGHAND: 0x00000800, CLONE_VM: 0x00000100
	if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
		return ERR_PTR(-EINVAL);

	/*
	 * Siblings of global init remain as zombies on exit since they are
	 * not reaped by their parent (swapper). To solve this and to avoid
	 * multi-rooted process trees, prevent global and container-inits
	 * from creating siblings.
	 */
	// clone_flags: 0x00800B00, CLONE_PARENT: 0x00008000, SIGNAL_UNKILLABLE: 0x00000040
	// current->signal->flags
	// current: &init_task
	if ((clone_flags & CLONE_PARENT) &&
				current->signal->flags & SIGNAL_UNKILLABLE)
		return ERR_PTR(-EINVAL);

	/*
	 * If the new process will be in a different pid or user namespace
	 * do not allow it to share a thread group or signal handlers or
	 * parent with the forking task.
	 */
	if (clone_flags & CLONE_SIGHAND) {
		if ((clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) ||
		    (task_active_pid_ns(current) !=
				current->nsproxy->pid_ns_for_children))
			return ERR_PTR(-EINVAL);
	}

	retval = security_task_create(clone_flags);
	if (retval)
		goto fork_out;

	retval = -ENOMEM;
	p = dup_task_struct(current);

dup_task_struct()

  • start_kernel()
  • rest_init()
  • call: rest_init()
  • rcu_scheduler_starring()
  • kernel_thread()
  • call: kernel_thread()
  • do_fork()
  • call: do_fork()
  • copy_process()
  • call: copy_process()
  • task_active_pid_ns()
  • security_task_create(clone_flags);
  • dup_task_struct()
  • call: dup_task_struct()
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
	struct task_struct *tsk;
	struct thread_info *ti;
	unsigned long *stackend;
	int node = tsk_fork_get_node(orig);
  • call: tak_for_get_node()
int tsk_fork_get_node(struct task_struct *tsk)
{
#ifdef CONFIG_NUMA
	if (tsk == kthreadd_task)
		return tsk->pref_node_fork;
#endif
	return numa_node_id();
}
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
	struct task_struct *tsk;
	struct thread_info *ti;
	unsigned long *stackend;
	int node = tsk_fork_get_node(orig);
	int err;

	tsk = alloc_task_struct_node(node);
  • call: alloc_task_struct_node()
static inline struct task_struct *alloc_task_struct_node(int node)
{
	return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node);
}
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
	struct task_struct *tsk;
	struct thread_info *ti;
	unsigned long *stackend;
	int node = tsk_fork_get_node(orig);
	int err;

	tsk = alloc_task_struct_node(node);
	if (!tsk)
		return NULL;

	ti = alloc_thread_info_node(tsk, node);
  • call: alloc_thread_info_node()
# if THREAD_SIZE >= PAGE_SIZE // THREAD_SIZE: 8192, PAGE_SIZE: 0x1000
static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
						  int node)
{
	struct page *page = alloc_pages_node(node, THREADINFO_GFP_ACCOUNTED,
					     THREAD_SIZE_ORDER);

	return page ? page_address(page) : NULL;
}
  • return: dup_task_struct()
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
	struct task_struct *tsk;
	struct thread_info *ti;
	unsigned long *stackend;
	int node = tsk_fork_get_node(orig);
	int err;

	tsk = alloc_task_struct_node(node);
	if (!tsk)
		return NULL;

	ti = alloc_thread_info_node(tsk, node);
    if (!ti)
		goto free_tsk;

	err = arch_dup_task_struct(tsk, orig);
	if (err)
		goto free_ti;

	tsk->stack = ti;

	setup_thread_stack(tsk, orig);

log

da7339e..6f02498  master     -> origin/master
Updating da7339e..6f02498
Fast-forward
arch/arm/include/asm/atomic.h         |   5 +++
arch/arm/include/asm/bitops.h         |   5 ++-
arch/arm/include/asm/memory.h         |   2 +
arch/arm/include/asm/page.h           |   1 +
arch/arm/include/asm/thread_info.h    |   7 ++++
include/asm-generic/resource.h        |  44 ++++++++++++++++++++
include/linux/capability.h            |   3 ++
include/linux/compiler.h              |   2 +
include/linux/cred.h                  |   3 ++
include/linux/ftrace.h                |   2 +
include/linux/gfp.h                   |   9 +++++
include/linux/init_task.h             | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/list.h                  |   6 +++
include/linux/mm.h                    |   6 +++
include/linux/mm_types.h              |   2 +
include/linux/mmzone.h                |   5 +++
include/linux/mutex.h                 |  17 ++++++++
include/linux/pid.h                   |  13 ++++++
include/linux/pid_namespace.h         |   1 +
include/linux/pipe_fs_i.h             |   1 +
include/linux/plist.h                 |   2 +
include/linux/rcupdate.h              |   4 ++
include/linux/rwsem.h                 |  13 ++++++
include/linux/sched.h                 |  79 +++++++++++++++++++++++++++++++++---
include/linux/seccomp.h               |   4 +-
include/linux/security.h              |   8 ++++
include/linux/slab.h                  |   2 +
include/linux/spinlock.h              |   2 +
include/linux/spinlock_types.h        |  20 ++++++++++
include/linux/thread_info.h           |  16 +++++++-
include/linux/topology.h              |   1 +
include/linux/user-return-notifier.h  |   3 +-
include/linux/wait.h                  |  28 +++++++++++++
include/uapi/asm-generic/errno-base.h |   2 +
include/uapi/asm-generic/resource.h   |  35 ++++++++++++++++
include/uapi/linux/capability.h       |  11 +++++
include/uapi/linux/fs.h               |   4 ++
include/uapi/linux/magic.h            |   2 +
include/uapi/linux/mqueue.h           |   2 +
include/uapi/linux/resource.h         |   6 +++
include/uapi/linux/sched.h            |   4 ++
init/init_task.c                      | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
kernel/capability.c                   |   7 ++++
kernel/cred.c                         |   3 ++
kernel/fork.c                         | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
kernel/kthread.c                      |   6 ++-
kernel/nsproxy.c                      |   1 +
kernel/pid.c                          |  22 ++++++++++
kernel/user.c                         |   3 ++
mm/highmem.c                          |   2 +
mm/vmstat.c                           |   3 ++
security/commoncap.c                  |   8 ++++
52 files changed, 1041 insertions(+), 42 deletions(-)