|
|
@ -147,7 +147,7 @@ int free_page_tables(unsigned long from,unsigned long size)
|
|
|
|
* 1 Mb-range, so the pages can be shared with the kernel. Thus the
|
|
|
|
* 1 Mb-range, so the pages can be shared with the kernel. Thus the
|
|
|
|
* special case for nr=xxxx.
|
|
|
|
* special case for nr=xxxx.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
int copy_page_tables(unsigned long from,unsigned long to,long size)
|
|
|
|
int copy_page_tables(unsigned long from,unsigned long to,long size )
|
|
|
|
{
|
|
|
|
{
|
|
|
|
unsigned long * from_page_table;
|
|
|
|
unsigned long * from_page_table;
|
|
|
|
unsigned long * to_page_table;
|
|
|
|
unsigned long * to_page_table;
|
|
|
@ -809,3 +809,160 @@ mytag:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
直接让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-4 00 00 00 00 */
|
|
|
|
|
|
|
|
/* child_stack-8 00 00 00 00 */
|
|
|
|
|
|
|
|
/* child_stack-12 arg */
|
|
|
|
|
|
|
|
/* child_stack-16 fn */ //esp
|
|
|
|
|
|
|
|
/* child_stack-20 00 00 00 00 */
|
|
|
|
|
|
|
|
/* child_stack-24 00 00 00 00 */
|
|
|
|
|
|
|
|
/* child_stack-28 00 00 00 00 */
|
|
|
|
|
|
|
|
/* child_stack-32 0x000000c3 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
int do_clone(int nr,long tmp,int (*fn)(void *), void *child_stack, int flag)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
void * argv =NULL;
|
|
|
|
|
|
|
|
//共享物理页:写法有缺陷,可能child——stack跨页
|
|
|
|
|
|
|
|
//子进程task[nr]的页表项获取,目的是更新成child——stacK的物理页
|
|
|
|
|
|
|
|
unsigned long nrfrom_page,nrfrom,from_page,from,tpage,address;
|
|
|
|
|
|
|
|
address = task[nr]->tss.esp;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
unsigned long stack[128];
|
|
|
|
|
|
|
|
unsigned long off=(unsigned long)child_stack & 0xfff;
|
|
|
|
|
|
|
|
if(off < 32)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
printk("地址跨页,我也没办法.\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//更新esp,让其指向child_stack同样偏移的地点;
|
|
|
|
|
|
|
|
//注意:这里child_stack 指向的是高地址,要向下面push.
|
|
|
|
|
|
|
|
task[nr]->tss.esp &=0xfffff000;
|
|
|
|
|
|
|
|
task[nr]->tss.esp |=off - 16;
|
|
|
|
|
|
|
|
//eip 只有一条ret //所以传进来的fn必须以exit结尾,不能return ,
|
|
|
|
|
|
|
|
//因为我不会return这个玩意push ebp 又pop 啥的
|
|
|
|
|
|
|
|
task[nr]->tss.eip &=0xfffff000;
|
|
|
|
|
|
|
|
task[nr]->tss.eip |=off - 32;
|
|
|
|
|
|
|
|
//ret eip
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stack[0]=0x000000c3;
|
|
|
|
|
|
|
|
stack[4]=(unsigned long)fn;
|
|
|
|
|
|
|
|
stack[5]=(unsigned long)argv;
|
|
|
|
|
|
|
|
char * p1=stack, *p2=(unsigned long) child_stack - 32,len=32;
|
|
|
|
|
|
|
|
while(len--)
|
|
|
|
|
|
|
|
put_fs_byte(*(p1++),p2++);
|
|
|
|
|
|
|
|
printk("nr:%d::fn:%x\n",nr,(unsigned long )fn);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
int copy_page_tables_clone(unsigned long from,unsigned long to,long size )
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
unsigned long * from_page_table;
|
|
|
|
|
|
|
|
unsigned long * to_page_table;
|
|
|
|
|
|
|
|
unsigned long this_page;
|
|
|
|
|
|
|
|
unsigned long * from_dir, * to_dir;
|
|
|
|
|
|
|
|
unsigned long nr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((from&0x3fffff) || (to&0x3fffff))
|
|
|
|
|
|
|
|
panic("copy_page_tables called with wrong alignment");
|
|
|
|
|
|
|
|
from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
|
|
|
|
|
|
|
|
to_dir = (unsigned long *) ((to>>20) & 0xffc);
|
|
|
|
|
|
|
|
size = ((unsigned) (size+0x3fffff)) >> 22;
|
|
|
|
|
|
|
|
for( ; size-->0 ; from_dir++,to_dir++) {
|
|
|
|
|
|
|
|
if (1 & *to_dir)
|
|
|
|
|
|
|
|
panic("copy_page_tables: already exist");
|
|
|
|
|
|
|
|
if (!(1 & *from_dir))
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
|
|
|
|
|
|
|
|
if (!(to_page_table = (unsigned long *) get_free_page()))
|
|
|
|
|
|
|
|
return -1; /* Out of memory, see freeing */
|
|
|
|
|
|
|
|
*to_dir = ((unsigned long) to_page_table) | 7;
|
|
|
|
|
|
|
|
nr = (from==0)?0xA0:1024;
|
|
|
|
|
|
|
|
for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
|
|
|
|
|
|
|
|
this_page = *from_page_table;
|
|
|
|
|
|
|
|
if (!(1 & this_page))
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*to_page_table = this_page;
|
|
|
|
|
|
|
|
if (this_page > LOW_MEM) {
|
|
|
|
|
|
|
|
*from_page_table = this_page;
|
|
|
|
|
|
|
|
this_page -= LOW_MEM;
|
|
|
|
|
|
|
|
this_page >>= 12;
|
|
|
|
|
|
|
|
mem_map[this_page]++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
invalidate();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|