|
|
|
@ -36,7 +36,7 @@ void verify_area(void * addr,int size)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int copy_mem(int nr,struct task_struct * p)
|
|
|
|
|
int copy_mem(int nr,struct task_struct * p,int flag)
|
|
|
|
|
{
|
|
|
|
|
unsigned long old_data_base,new_data_base,data_limit;
|
|
|
|
|
unsigned long old_code_base,new_code_base,code_limit;
|
|
|
|
@ -53,7 +53,7 @@ int copy_mem(int nr,struct task_struct * p)
|
|
|
|
|
p->start_code = new_code_base;
|
|
|
|
|
set_base(p->ldt[1],new_code_base);
|
|
|
|
|
set_base(p->ldt[2],new_data_base);
|
|
|
|
|
if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
|
|
|
|
|
if (copy_page_tables(old_data_base,new_data_base,data_limit,flag)) {
|
|
|
|
|
free_page_tables(new_data_base,data_limit);
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
}
|
|
|
|
@ -65,7 +65,7 @@ int copy_mem(int nr,struct task_struct * p)
|
|
|
|
|
* information (task[nr]) and sets up the necessary registers. It
|
|
|
|
|
* also copies the data segment in it's entirety.
|
|
|
|
|
*/
|
|
|
|
|
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
|
|
|
|
|
int copy_process(int flag,int nr,long ebp,long edi,long esi,long gs,long none,
|
|
|
|
|
long ebx,long ecx,long edx,
|
|
|
|
|
long fs,long es,long ds,
|
|
|
|
|
long eip,long cs,long eflags,long esp,long ss)
|
|
|
|
@ -113,7 +113,7 @@ int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
|
|
|
|
|
p->tss.trace_bitmap = 0x80000000;
|
|
|
|
|
if (last_task_used_math == current)
|
|
|
|
|
__asm__("clts ; fnsave %0"::"m" (p->tss.i387));
|
|
|
|
|
if (copy_mem(nr,p)) {
|
|
|
|
|
if (copy_mem(nr,p,flag)) {
|
|
|
|
|
task[nr] = NULL;
|
|
|
|
|
free_page((long) p);
|
|
|
|
|
return -EAGAIN;
|
|
|
|
@ -146,3 +146,96 @@ int find_empty_process(void)
|
|
|
|
|
return i;
|
|
|
|
|
return -EAGAIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
直接让esp(子进程)指向另一个进程(当前进程)的地址;
|
|
|
|
|
修改eip对应的指令,改为ret 0xec8353c3 ps:应该只有0xc3有用
|
|
|
|
|
由于eip只执行一条指令,我们将eip指向栈,将ret压入栈即可;
|
|
|
|
|
在这里我们只实现了int (*fn)(void *) 一种函数类型,并且要求fn内以exit结尾
|
|
|
|
|
于是我们只需修改八字节即可;
|
|
|
|
|
下面写的不对,不能指向另一个进程的地址,只能修改物理页了。
|
|
|
|
|
*/
|
|
|
|
|
int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag)
|
|
|
|
|
{
|
|
|
|
|
//设置压栈表,方便操作;
|
|
|
|
|
long stack[1024];
|
|
|
|
|
unsigned long len=0;
|
|
|
|
|
task[nr]->tss.esp=(unsigned long) child_stack - 8;
|
|
|
|
|
stack[0] = (unsigned long) fn;
|
|
|
|
|
task[nr]->tss.eip = (unsigned long) child_stack - 4;
|
|
|
|
|
stack[1]= 0xec8353c3;
|
|
|
|
|
//栈区赋值;
|
|
|
|
|
len = 8;
|
|
|
|
|
char *p1=stack ,*p2=(char *)((unsigned long)child_stack-len);
|
|
|
|
|
while(len--)
|
|
|
|
|
put_fs_byte(*(p1++),p2++);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
共享物理页:写法有缺陷,可能child——stack跨页
|
|
|
|
|
//子进程task[nr]的页表项获取,目的是更新成child——stacK的物理页
|
|
|
|
|
nrfrom_page = ((address>>20) & 0xffc);
|
|
|
|
|
nrfrom_page += ((task[nr]->start_code>>20) & 0xffc);//页目录
|
|
|
|
|
nrfrom=*(unsigned long *)nrfrom_page; //页表项
|
|
|
|
|
if(!(nrfrom&1)) //无页表项分配一个
|
|
|
|
|
{
|
|
|
|
|
if(!(tpage=get_free_page()))
|
|
|
|
|
{
|
|
|
|
|
printk("out of memory.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*(unsigned long *)nrfrom_page= tpage | 7;
|
|
|
|
|
mem_map[(tpage-LOW_MEM)>>12]++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nrfrom &= 0xfffff000;
|
|
|
|
|
nrfrom_page = nrfrom + ((address>>10) & 0xffc);
|
|
|
|
|
|
|
|
|
|
//获取child_stack的物理页,并将其复制给task[nr];
|
|
|
|
|
address=(unsigned long) child_stack;
|
|
|
|
|
from_page = ((address>>20) & 0xffc);
|
|
|
|
|
from_page += ((current->start_code>>20) & 0xffc);//页目录
|
|
|
|
|
if(!(*(unsigned long *)from_page&1)) //页表项不存在,申请页面
|
|
|
|
|
if(!(tpage=get_free_page()))
|
|
|
|
|
{
|
|
|
|
|
printk("out of memory.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*(unsigned long *)from_page= tpage | 7;
|
|
|
|
|
mem_map[(tpage-LOW_MEM)>>12]++;
|
|
|
|
|
}
|
|
|
|
|
from=*(unsigned long *)from_page; //页表项
|
|
|
|
|
from &= 0xfffff000;
|
|
|
|
|
from_page = from + ((address>>10) & 0xffc);
|
|
|
|
|
if(!(*(unsigned long *)from_page & 1)) //物理页不存在
|
|
|
|
|
if(!(tpage=get_free_page()))
|
|
|
|
|
{
|
|
|
|
|
printk("out of memory.\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*(unsigned long *)from_page= tpage | 7;
|
|
|
|
|
mem_map[(tpage-LOW_MEM)>>12]++;
|
|
|
|
|
}
|
|
|
|
|
//复制给nr
|
|
|
|
|
*(unsigned long *)nrfrom_page = *(unsigned long *)from_page;
|
|
|
|
|
|
|
|
|
|
//更新esp,让其指向child_stack同样偏移的地点;
|
|
|
|
|
task[nr]->tss.esp=(unsigned long) child_stack;
|
|
|
|
|
|
|
|
|
|
//注意:这里child_stack 指向的是高地址,要向下面push.
|
|
|
|
|
unsigned long phy_addr = (*(unsigned long *)nrfrom_page & 0xfffff000) | ((unsigned long) child_stack & 0xfff);
|
|
|
|
|
if(argv)//参数列表不为空,将参数压入栈中,这里直接修改物理页
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//char * tmp1=nrfrom, *tmp2=child_stack-1024,len=;
|
|
|
|
|
//while()
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
*/
|