execve 启动新程序
- execve 实现
系统相关 系统无关
sys_execve - > do_execve
do_execve 定义
1 *
2 * sys_execve() executes a new program.
3 */
4int do_execve(char * filename,
5char __user *__user *argv,
6char __user *__user *envp,
7struct pt_regs * regs)
do_execve 执行流程图
首先打开内核文件,具体可见第八章
bprm_init
mm_alloc 生成新的mm_struct 实例管理进程地址空间
init_new_context 特定于体系,用于初始化该实例
__bprm_mm_init 建立初始的栈
新进程的各个参数会合并到一个struct linux_binprm *bprm;的机构。 prepare_binprm用于提供一些父进程相关的值
prepare_binprm也维护了SUID SGID位的处理
1
/*
2
* Fill the binprm structure from the inode.
3
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
4
*/
5
int prepare_binprm(struct linux_binprm *bprm)
6{
7int mode;
8struct inode * inode = bprm->file->f_path.dentry->d_inode;
9int retval;
1011 mode = inode->i_mode;
12if (bprm->file->f_op == NULL)
13return -EACCES;
1415 bprm->e_uid = current->euid;
16 bprm->e_gid = current->egid;
1718if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
19/* Set-uid? */20if (mode & S_ISUID) {
21 current->personality &= ~PER_CLEAR_ON_SETID;
22 bprm->e_uid = inode->i_uid;
23 }
2425/* Set-gid? */26/*27 * If setgid is set but no group execute bit then this
28 * is a candidate for mandatory locking, not a setgid
29 * executable.
30*/31if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
32 current->personality &= ~PER_CLEAR_ON_SETID;
33 bprm->e_gid = inode->i_gid;
34 }
35 }
3637/* fill in binprm security blob */38 retval = security_bprm_set(bprm);
39if (retval)
40return retval;
4142 memset(bprm->buf,0,BINPRM_BUF_SIZE);
43return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
44 }
search_binary_handler用于在do_execve 结束是查找一种适当的二进制格式,具体细节(待补充。。。)
二进制格式处理程序负责将新的程序数据加载到旧的地址空间中,
二进制格式处理程序执行步骤如下:
- 释放原进程资源
- 将应用进程映射到虚拟地址空间
- text 段,start_code 和 end_code 指定该段在地址空间驻留区域
- 预先初始化的数据位于start_data和end_data之间
- heap 用于动态内存分配,亦置于虚拟地址空间中,start_brk和brk 指定其边界
- stack 由start_stack 定义,几乎所有体系自动向下增长,PA-Risc是例外,对于栈的反向增长,体系结构的相关部分必须告诉内核,可以通过设置符号STACK_DROWSUP
- 程序的参数与环境也映射到虚拟地址空间中,分别位于arg_start 和arg_end 之间
- 设置进程的相关指令和其他特定于体系结构的寄存器,以便调度器选择该进程时候开始执行程序的main函数
2 解释二进制格式
1
/*
2
* This structure defines the functions that are used to load the binary formats that
3
* linux accepts.
4
*/
5
struct
linux_binfmt {
6
struct
list_head lh;
7
struct module *module;
8int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
9int (*load_shlib)(struct file *);
10int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
11 unsigned long min_coredump; /* minimal dump size */12int hasvdso;
13 };
每种二进制格式提供下面三个函数
load_binary加载普通程序
load_shlib用于加载共享库。
coredump error 下输出内存转储
每种二进制格式需要使用register_binfmt向内核注册。该函数的目的是向一个链表增加一个新的二进制格式
该链表表头是fs/exec.c的全局变量formats, linux_binfmt 实例通过其next成员彼此联系起来
原文:http://www.cnblogs.com/songbingyu/p/3683038.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!