`

窥探 kernel,just for fun --- copy_process

阅读更多

本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7479714

邮箱:muge0913@sina.com


在do_fork中调用了copy_process,该函数及其重要。该函数创建进程描述符和子进程需要的其他数据结构。它定义在linux2.6.xxx/kernel/fork.c。

只对关键部分进行了注释如下:

 

  1. /* 
  2.  * This creates a new process as a copy of the old one, 
  3.  * but does not actually start it yet. 
  4.  * 
  5.  * It copies the registers, and all the appropriate 
  6.  * parts of the process environment (as per the clone 
  7.  * flags). The actual kick-off is left to the caller. 
  8.  */  
  9.    
  10.    
  11.  /*这部分代码是在2.6.38中实现的*/  
  12. static struct task_struct *copy_process(unsigned long clone_flags,  
  13.                     unsigned long stack_start,  
  14.                     struct pt_regs *regs,  
  15.                     unsigned long stack_size,  
  16.                     int __user *child_tidptr,  
  17.                     struct pid *pid,  
  18.                     int trace)  
  19. {  
  20.     int retval;  
  21.     struct task_struct *p;//保存新的进程描述符地址  
  22.     int cgroup_callbacks_done = 0;  
  23.     /*CLONE_NEWNS和CLONE_FS是冲突的不能同时设置,否则出错*/  
  24.     if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))  
  25.         return ERR_PTR(-EINVAL);  
  26.   
  27.     /* 
  28.      * Thread groups must share signals as well, and detached threads 
  29.      * can only be started up within the thread group. 
  30.      */  
  31.      /*CLONE_THREAD和CLONE_SIGHAND是冲突的不能同时设置,否则出错*/  
  32.     if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))  
  33.         return ERR_PTR(-EINVAL);  
  34.   
  35.     /* 
  36.      * Shared signal handlers imply shared VM. By way of the above, 
  37.      * thread groups also imply shared VM. Blocking this case allows 
  38.      * for various simplifications in other code. 
  39.      */  
  40.      /*CLONE_SIGHAND和CLONE_VM冲突不能同时设置。否则出错*/  
  41.     if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))  
  42.         return ERR_PTR(-EINVAL);  
  43.   
  44.     /* 
  45.      * Siblings of global init remain as zombies on exit since they are 
  46.      * not reaped by their parent (swapper). To solve this and to avoid 
  47.      * multi-rooted process trees, prevent global and container-inits 
  48.      * from creating siblings. 
  49.      */  
  50.     if ((clone_flags & CLONE_PARENT) &&  
  51.                 current->signal->flags & SIGNAL_UNKILLABLE)  
  52.         return ERR_PTR(-EINVAL);  
  53.     /*调用系统安全框架创建进程,在配置内核时没有选择CONFIG_SECURITY,则系统安全框架函数为空*/  
  54.     retval = security_task_create(clone_flags);  
  55.     if (retval)  
  56.         goto fork_out;  
  57.   
  58.     retval = -ENOMEM;  
  59.     /*来复制一份当前进程的进程描述符,为子进程描述符做准备 
  60.     *该函数为子进程创建一个新的内核栈,并分配一个新的进程描述符和thread_info结构,然后 
  61.     *把父进程的进程描述符和thread_info拷贝进去。这里是完全拷贝,子进程和父进程的描述符完全 
  62.     *相同。 
  63.     */  
  64.     p = dup_task_struct(current);  
  65.     if (!p)  
  66.         goto fork_out;  
  67.   
  68.     ftrace_graph_init_task(p);  
  69.   
  70.     rt_mutex_init_task(p);  
  71.   
  72. #ifdef CONFIG_PROVE_LOCKING  
  73.     DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);  
  74.     DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);  
  75. #endif  
  76.   
  77.     /*判断是否超出了设置权限*/  
  78.     retval = -EAGAIN;  
  79.     if (atomic_read(&p->real_cred->user->processes) >=  
  80.             task_rlimit(p, RLIMIT_NPROC)) {  
  81.         if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&  
  82.             p->real_cred->user != INIT_USER)  
  83.             goto bad_fork_free;  
  84.     }  
  85.   
  86.     retval = copy_creds(p, clone_flags);  
  87.     if (retval < 0)  
  88.         goto bad_fork_free;  
  89.   
  90.     /* 
  91.      * If multiple threads are within copy_process(), then this check 
  92.      * triggers too late. This doesn't hurt, the check is only there 
  93.      * to stop root fork bombs. 
  94.      */  
  95.      /*判断线程数量是否超出系统允许范围,否则释放已经申请到的资源*/  
  96.     retval = -EAGAIN;  
  97.     if (nr_threads >= max_threads)//max_threads在kernel_fork中的fork_init中有定义。  
  98.                     //系统最大进程数和系统的内存有关  
  99.         goto bad_fork_cleanup_count;  
  100.   
  101.   
  102.     /*下面的代码主要是对子进程的描述符初始化和复制父进程的资源给子进程*/  
  103.       
  104.       
  105.     /*模块引用计数操作*/  
  106.     if (!try_module_get(task_thread_info(p)->exec_domain->module))  
  107.         goto bad_fork_cleanup_count;  
  108.     /*execve系统调用数初始化为0*/  
  109.     p->did_exec = 0;  
  110.     delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */  
  111.     /*设置状态标记,因为目前状态表示是从父进程拷贝过来的*/  
  112.     copy_flags(clone_flags, p);  
  113.     INIT_LIST_HEAD(&p->children);  
  114.     INIT_LIST_HEAD(&p->sibling);  
  115.     rcu_copy_process(p);  
  116.     p->vfork_done = NULL;  
  117.     spin_lock_init(&p->alloc_lock);  
  118.   
  119.     init_sigpending(&p->pending);  
  120.   
  121.     p->utime = cputime_zero;  
  122.     p->stime = cputime_zero;  
  123.     p->gtime = cputime_zero;  
  124.     p->utimescaled = cputime_zero;  
  125.     p->stimescaled = cputime_zero;  
  126. #ifndef CONFIG_VIRT_CPU_ACCOUNTING  
  127.     p->prev_utime = cputime_zero;  
  128.     p->prev_stime = cputime_zero;  
  129. #endif  
  130. #if defined(SPLIT_RSS_COUNTING)  
  131.     memset(&p->rss_stat, 0, sizeof(p->rss_stat));  
  132. #endif  
  133.   
  134.     p->default_timer_slack_ns = current->timer_slack_ns;  
  135.   
  136.     task_io_accounting_init(&p->ioac);  
  137.     acct_clear_integrals(p);  
  138.   
  139.     posix_cpu_timers_init(p);  
  140.   
  141.     p->lock_depth = -1;      /* -1 = no lock */  
  142.     do_posix_clock_monotonic_gettime(&p->start_time);  
  143.     p->real_start_time = p->start_time;  
  144.     monotonic_to_bootbased(&p->real_start_time);  
  145.     p->io_context = NULL;  
  146.     p->audit_context = NULL;  
  147.     cgroup_fork(p);  
  148. #ifdef CONFIG_NUMA  
  149.     p->mempolicy = mpol_dup(p->mempolicy);  
  150.     if (IS_ERR(p->mempolicy)) {  
  151.         retval = PTR_ERR(p->mempolicy);  
  152.         p->mempolicy = NULL;  
  153.         goto bad_fork_cleanup_cgroup;  
  154.     }  
  155.     mpol_fix_fork_child_flag(p);  
  156. #endif  
  157. #ifdef CONFIG_TRACE_IRQFLAGS  
  158.     p->irq_events = 0;  
  159. #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW  
  160.     p->hardirqs_enabled = 1;  
  161. #else  
  162.     p->hardirqs_enabled = 0;  
  163. #endif  
  164.     p->hardirq_enable_ip = 0;  
  165.     p->hardirq_enable_event = 0;  
  166.     p->hardirq_disable_ip = _THIS_IP_;  
  167.     p->hardirq_disable_event = 0;  
  168.     p->softirqs_enabled = 1;  
  169.     p->softirq_enable_ip = _THIS_IP_;  
  170.     p->softirq_enable_event = 0;  
  171.     p->softirq_disable_ip = 0;  
  172.     p->softirq_disable_event = 0;  
  173.     p->hardirq_context = 0;  
  174.     p->softirq_context = 0;  
  175. #endif  
  176. #ifdef CONFIG_LOCKDEP  
  177.     p->lockdep_depth = 0; /* no locks held yet */  
  178.     p->curr_chain_key = 0;  
  179.     p->lockdep_recursion = 0;  
  180. #endif  
  181.   
  182. #ifdef CONFIG_DEBUG_MUTEXES  
  183.     p->blocked_on = NULL; /* not blocked yet */  
  184. #endif  
  185. #ifdef CONFIG_CGROUP_MEM_RES_CTLR  
  186.     p->memcg_batch.do_batch = 0;  
  187.     p->memcg_batch.memcg = NULL;  
  188. #endif  
  189.   
  190.     /* Perform scheduler related setup. Assign this task to a CPU. */  
  191.     sched_fork(p, clone_flags);  
  192.   
  193.     retval = perf_event_init_task(p);  
  194.     if (retval)  
  195.         goto bad_fork_cleanup_policy;  
  196.   
  197.     if ((retval = audit_alloc(p)))  
  198.         goto bad_fork_cleanup_policy;  
  199.     /* copy all the process information */  
  200.     if ((retval = copy_semundo(clone_flags, p)))  
  201.         goto bad_fork_cleanup_audit;  
  202.     if ((retval = copy_files(clone_flags, p)))  
  203.         goto bad_fork_cleanup_semundo;  
  204.     if ((retval = copy_fs(clone_flags, p)))  
  205.         goto bad_fork_cleanup_files;  
  206.     if ((retval = copy_sighand(clone_flags, p)))  
  207.         goto bad_fork_cleanup_fs;  
  208.     if ((retval = copy_signal(clone_flags, p)))  
  209.         goto bad_fork_cleanup_sighand;  
  210.     if ((retval = copy_mm(clone_flags, p)))  
  211.         goto bad_fork_cleanup_signal;  
  212.     if ((retval = copy_namespaces(clone_flags, p)))  
  213.         goto bad_fork_cleanup_mm;  
  214.     if ((retval = copy_io(clone_flags, p)))  
  215.         goto bad_fork_cleanup_namespaces;  
  216.     retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);  
  217.     if (retval)  
  218.         goto bad_fork_cleanup_io;  
  219.   
  220.     if (pid != &init_struct_pid) {  
  221.         retval = -ENOMEM;  
  222.         pid = alloc_pid(p->nsproxy->pid_ns);  
  223.         if (!pid)  
  224.             goto bad_fork_cleanup_io;  
  225.   
  226.         if (clone_flags & CLONE_NEWPID) {  
  227.             retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);  
  228.             if (retval < 0)  
  229.                 goto bad_fork_free_pid;  
  230.         }  
  231.     }  
  232.   
  233.     p->pid = pid_nr(pid);  
  234.     p->tgid = p->pid;  
  235.     if (clone_flags & CLONE_THREAD)  
  236.         p->tgid = current->tgid;  
  237.   
  238.     if (current->nsproxy != p->nsproxy) {  
  239.         retval = ns_cgroup_clone(p, pid);  
  240.         if (retval)  
  241.             goto bad_fork_free_pid;  
  242.     }  
  243.   
  244.     p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;  
  245.     /* 
  246.      * Clear TID on mm_release()? 
  247.      */  
  248.     p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr:   
  249. NULL;  
  250. #ifdef CONFIG_FUTEX  
  251.     p->robust_list = NULL;  
  252. #ifdef CONFIG_COMPAT  
  253.     p->compat_robust_list = NULL;  
  254. #endif  
  255.     INIT_LIST_HEAD(&p->pi_state_list);  
  256.     p->pi_state_cache = NULL;  
  257. #endif  
  258.     /* 
  259.      * sigaltstack should be cleared when sharing the same VM 
  260.      */  
  261.     if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)  
  262.         p->sas_ss_sp = p->sas_ss_size = 0;  
  263.   
  264.     /* 
  265.      * Syscall tracing and stepping should be turned off in the 
  266.      * child regardless of CLONE_PTRACE. 
  267.      */  
  268.     user_disable_single_step(p);  
  269.     clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);  
  270. #ifdef TIF_SYSCALL_EMU  
  271.     clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);  
  272. #endif  
  273.     clear_all_latency_tracing(p);  
  274.   
  275.     /* ok, now we should be set up.. */  
  276.     p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);  
  277.     p->pdeath_signal = 0;  
  278.     p->exit_state = 0;  
  279.   
  280.     /* 
  281.      * Ok, make it visible to the rest of the system. 
  282.      * We dont wake it up yet. 
  283.      */  
  284.     p->group_leader = p;  
  285.     INIT_LIST_HEAD(&p->thread_group);  
  286.   
  287.     /* Now that the task is set up, run cgroup callbacks if 
  288.      * necessary. We need to run them before the task is visible 
  289.      * on the tasklist. */  
  290.     cgroup_fork_callbacks(p);  
  291.     cgroup_callbacks_done = 1;  
  292.   
  293.     /* Need tasklist lock for parent etc handling! */  
  294.     write_lock_irq(&tasklist_lock);  
  295.   
  296.     /* CLONE_PARENT re-uses the old parent */  
  297.     if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {  
  298.         p->real_parent = current->real_parent;  
  299.         p->parent_exec_id = current->parent_exec_id;  
  300.     } else {  
  301.         p->real_parent = current;  
  302.         p->parent_exec_id = current->self_exec_id;  
  303.     }  
  304.   
  305.     spin_lock(¤t->sighand->siglock);  
  306.   
  307.     /* 
  308.      * Process group and session signals need to be delivered to just the 
  309.      * parent before the fork or both the parent and the child after the 
  310.      * fork. Restart if a signal comes in before we add the new process to 
  311.      * it's process group. 
  312.      * A fatal signal pending means that current will exit, so the new 
  313.      * thread can't slip out of an OOM kill (or normal SIGKILL). 
  314.      */  
  315.     recalc_sigpending();  
  316.     if (signal_pending(current)) {  
  317.         spin_unlock(¤t->sighand->siglock);  
  318.         write_unlock_irq(&tasklist_lock);  
  319.         retval = -ERESTARTNOINTR;  
  320.         goto bad_fork_free_pid;  
  321.     }  
  322.   
  323.     if (clone_flags & CLONE_THREAD) {  
  324.         current->signal->nr_threads++;  
  325.         atomic_inc(¤t->signal->live);  
  326.         atomic_inc(¤t->signal->sigcnt);  
  327.         p->group_leader = current->group_leader;  
  328.         list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);  
  329.     }  
  330.   
  331.     if (likely(p->pid)) {  
  332.         tracehook_finish_clone(p, clone_flags, trace);  
  333.   
  334.         if (thread_group_leader(p)) {  
  335.             if (clone_flags & CLONE_NEWPID)  
  336.                 p->nsproxy->pid_ns->child_reaper = p;  
  337.   
  338.             p->signal->leader_pid = pid;  
  339.             p->signal->tty = tty_kref_get(current->signal->tty);  
  340.             attach_pid(p, PIDTYPE_PGID, task_pgrp(current));  
  341.             attach_pid(p, PIDTYPE_SID, task_session(current));  
  342.             list_add_tail(&p->sibling, &p->real_parent->children);  
  343.             list_add_tail_rcu(&p->tasks, &init_task.tasks);  
  344.             __get_cpu_var(process_counts)++;  
  345.         }  
  346.         attach_pid(p, PIDTYPE_PID, pid);  
  347.         nr_threads++;  
  348.     }  
  349.   
  350.     total_forks++;  
  351.     spin_unlock(¤t->sighand->siglock);  
  352.     write_unlock_irq(&tasklist_lock);  
  353.     proc_fork_connector(p);  
  354.     cgroup_post_fork(p);  
  355.     perf_event_fork(p);  
  356.     /*返回子进程描述符的指针*/  
  357.     return p;  
  358.   
  359. bad_fork_free_pid:  
  360.     if (pid != &init_struct_pid)  
  361.         free_pid(pid);  
  362. bad_fork_cleanup_io:  
  363.     if (p->io_context)  
  364.         exit_io_context(p);  
  365. bad_fork_cleanup_namespaces:  
  366.     exit_task_namespaces(p);  
  367. bad_fork_cleanup_mm:  
  368.     if (p->mm) {  
  369.         task_lock(p);  
  370.         if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)  
  371.             atomic_dec(&p->mm->oom_disable_count);  
  372.         task_unlock(p);  
  373.         mmput(p->mm);  
  374.     }  
  375. bad_fork_cleanup_signal:  
  376.     if (!(clone_flags & CLONE_THREAD))  
  377.         free_signal_struct(p->signal);  
  378. bad_fork_cleanup_sighand:  
  379.     __cleanup_sighand(p->sighand);  
  380. bad_fork_cleanup_fs:  
  381.     exit_fs(p); /* blocking */  
  382. bad_fork_cleanup_files:  
  383.     exit_files(p); /* blocking */  
  384. bad_fork_cleanup_semundo:  
  385.     exit_sem(p);  
  386. bad_fork_cleanup_audit:  
  387.     audit_free(p);  
  388. bad_fork_cleanup_policy:  
  389.     perf_event_free_task(p);  
  390. #ifdef CONFIG_NUMA  
  391.     mpol_put(p->mempolicy);  
  392. bad_fork_cleanup_cgroup:  
  393. #endif  
  394.     cgroup_exit(p, cgroup_callbacks_done);  
  395.     delayacct_tsk_free(p);  
  396.     module_put(task_thread_info(p)->exec_domain->module);  
  397. bad_fork_cleanup_count:  
  398.     atomic_dec(&p->cred->user->processes);  
  399.     exit_creds(p);  
  400. bad_fork_free:  
  401.     free_task(p);  
  402. fork_out:  
  403.     return ERR_PTR(retval);  
  404. }  

 

分享到:
评论

相关推荐

    Qt源码窥探(1)---创建窗口过程图解

    Qt源码窥探(1)---创建窗口过程图解。。

    从问界窥探华为智能汽车布局-2022-10-新势力

    【华为智能汽车布局】 华为作为全球知名的科技巨头,在近年来逐渐涉足智能汽车领域,尤其是在新能源汽车市场,华为通过三种合作模式——零部件模式、HI模式(Huawei Inside模式)、智选车模式,展现了其在汽车行业...

    e-Border-driver-win_3_5_1

    标题中的“e-Border-driver-win_3_5_1”显然指的是一个特定版本的软件,即e-Border驱动程序的Windows版本,版本号为3.5.1。...通过这个软件,用户可以有效地绕过某些网络限制,同时保护他们的网络活动免受窥探。

    ttx.rar_SANSUI-A-A7CD_teletext_teletext解析

    总结,SANSUI-A-A7CD Teletext解析源代码为我们提供了一个难得的机会,去窥探过去的技术如何在现代设备中实现,同时也揭示了早期交互式信息系统的原理。通过深入学习和分析,我们可以从中获得宝贵的知识和经验,这...

    Python库 | pspy-1.4.7-cp37-cp37m-macosx_10_9_x86_64.whl

    `pspy`的名字来源于“process spy”,即进程间窥探,它为开发人员提供了一个方便的接口来获取和分析运行中的进程信息。 `pspy-1.4.7-cp37-cp37m-macosx_10_9_x86_64.whl`这个文件是一个预编译的Python轮子包(wheel...

    jdk-9-ea-bin-b53-linux-x64-04_mar_2015.tar

    这个压缩包文件,标志着JDK 9开发过程中的一个重要里程碑,为我们提供了窥探新特性、改进和优化的窗口。 首先,"ea"(Early Access)表明这是JDK 9的一个早期预览版本,用于开发者测试和反馈,帮助Oracle公司在正式...

    µTorrent_3.31_Build_30017-BYRBT

    8. **安全性**: μTorrent支持加密连接,保护用户的下载活动免受窥探,同时还有防止病毒和恶意软件的内置保护。 9. **BYRBT**: BYRBT可能是指某个社区或种子库的标识,表明这个μTorrent版本可能是从这个特定的社区...

    信息安全_数据安全_窥探安卓内核.pdf

    窥探安卓内核 企业安全 物联网安全云安全 安全意识教育 安全管理

    大数据初次窥探---第一节.docx

    大数据是21世纪信息技术发展的重要领域,它标志着我们正从传统的IT时代迈向DT时代。DT时代强调以数据为中心,利用先进的数据处理技术提升服务质量、驱动生产力。马云曾指出,DT时代将取代IT时代,成为未来的主要发展...

    FileZilla_3.63.2.1_macosx-x86.zip

    SSL/TLS加密支持:确保数据传输的安全性,无论是使用FTPS还是SFTP协议,都能保护数据免遭窥探。 防火墙支持:兼容大多数代理和防火墙设置,适合在各种网络环境下使用。 队列管理:用户可以安排文件传输的顺序,...

    ediary-3.3.1-copy.zip

    软件提供了强大的密码保护机制,确保用户的私密日记不被他人窥探。同时,数据加密技术的应用,保证了即使日记文件被盗,内容也无法被轻易解密,为用户的隐私安全筑起了一道坚实的防线。 在eDiary-3.3.1这个版本中,...

    沟通能力人才测评试题-智尊测评_嵌入式-常用知识&面试题库_大厂面试真题.pdf

    例如,当发现有同事希望担任你的职位时,可以选择主动接触,而不是无视或暗中窥探。 在与同事的日常互动中,诚实和公平的沟通原则很重要。如果竞争对手向你借书,大方地借出是一种展示胸怀的方式,而不是试图贬低...

    PyPI 官网下载 | pwclip-1.1.3.linux-x86_64.tar.gz

    它可能使用操作系统级别的安全特性来保护密码不被窥探。 2. **剪贴板交互**:库可能提供了与系统剪贴板交互的API,允许程序读取、写入或清除剪贴板内容,特别适用于需要处理敏感信息的场景。 3. **加密/解密**:...

    VB源代码-文本防窥探工具.doc

    ### VB源代码-文本防窥探工具知识点解析 #### 一、概述 本文将深入解析一个基于Visual Basic(简称VB)编写的文本防窥探工具的源代码。该工具主要功能在于实现文本文件的安全加密与解密操作,通过简单的用户界面...

    窥探Docker中的Volume Plugin内幕-有容云

    Volume与CoW(Copy-on-Write)的分层文件系统是完全独立的,且可以通过Volume Plugin机制轻松地整合外部存储。 Docker Volume Plugin机制允许Docker方便地整合第三方存储系统,为容器提供存储卷。Volume Plugin的...

    FileZilla_3.63.2.1_win64_sponsored2-setup.zip

    SSL/TLS加密支持:确保数据传输的安全性,无论是使用FTPS还是SFTP协议,都能保护数据免遭窥探。 防火墙支持:兼容大多数代理和防火墙设置,适合在各种网络环境下使用。 队列管理:用户可以安排文件传输的顺序,...

    「风险评估」窥探安卓内核 - 应急响应.zip

    在本压缩包中所包含的《窥探安卓内核.pdf》文件,很可能是对上述概念和技术进行详细介绍的教程或研究报告。这份资料可能详细讲解了内核漏洞的发现方法、安全更新的重要性,以及如何在应急情况下快速定位并修复问题。...

Global site tag (gtag.js) - Google Analytics