From ad4b18f25b117b7dba529aca939bc77e9d338289 Mon Sep 17 00:00:00 2001 From: mp6sgfx3h <1610531619@qq.com> Date: Sat, 2 Jul 2022 00:19:52 +0800 Subject: [PATCH 1/4] ADD file via upload --- fork.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 fork.c diff --git a/fork.c b/fork.c new file mode 100644 index 0000000..effc165 --- /dev/null +++ b/fork.c @@ -0,0 +1,241 @@ +/* + * linux/kernel/fork.c + * + * (C) 1991 Linus Torvalds + */ + +/* + * 'fork.c' contains the help-routines for the 'fork' system call + * (see also system_call.s), and some misc functions ('verify_area'). + * Fork is rather simple, once you get the hang of it, but the memory + * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()' + */ +#include + +#include +#include +#include +#include + +extern void write_verify(unsigned long address); + +long last_pid=0; + +void verify_area(void * addr,int size) +{ + unsigned long start; + + start = (unsigned long) addr; + size += start & 0xfff; + start &= 0xfffff000; + start += get_base(current->ldt[2]); + while (size>0) { + size -= 4096; + write_verify(start); + start += 4096; + } +} + +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; + + code_limit=get_limit(0x0f); + data_limit=get_limit(0x17); + old_code_base = get_base(current->ldt[1]); + old_data_base = get_base(current->ldt[2]); + if (old_data_base != old_code_base) + panic("We don't support separate I&D"); + if (data_limit < code_limit) + panic("Bad data_limit"); + new_data_base = new_code_base = nr * 0x4000000; + 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,flag)) { + free_page_tables(new_data_base,data_limit); + return -ENOMEM; + } + return 0; +} + +/* + * Ok, this is the main fork-routine. It copies the system process + * information (task[nr]) and sets up the necessary registers. It + * also copies the data segment in it's entirety. + */ +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) +{ + struct task_struct *p; + int i; + struct file *f; + + p = (struct task_struct *) get_free_page(); + if (!p) + return -EAGAIN; + task[nr] = p; + __asm__ volatile ("cld"); /* by wyj */ + *p = *current; /* NOTE! this doesn't copy the supervisor stack */ + p->state = TASK_UNINTERRUPTIBLE; + p->pid = last_pid; + p->father = current->pid; + p->counter = p->priority; + p->signal = 0; + p->alarm = 0; + p->leader = 0; /* process leadership doesn't inherit */ + p->utime = p->stime = 0; + p->cutime = p->cstime = 0; + p->start_time = jiffies; + p->tss.back_link = 0; + p->tss.esp0 = PAGE_SIZE + (long) p; + p->tss.ss0 = 0x10; + p->tss.eip = eip; + p->tss.eflags = eflags; + p->tss.eax = 0; + p->tss.ecx = ecx; + p->tss.edx = edx; + p->tss.ebx = ebx; + p->tss.esp = esp; + p->tss.ebp = ebp; + p->tss.esi = esi; + p->tss.edi = edi; + p->tss.es = es & 0xffff; + p->tss.cs = cs & 0xffff; + p->tss.ss = ss & 0xffff; + p->tss.ds = ds & 0xffff; + p->tss.fs = fs & 0xffff; + p->tss.gs = gs & 0xffff; + p->tss.ldt = _LDT(nr); + p->tss.trace_bitmap = 0x80000000; + if (last_task_used_math == current) + __asm__("clts ; fnsave %0"::"m" (p->tss.i387)); + if (copy_mem(nr,p,flag)) { + task[nr] = NULL; + free_page((long) p); + return -EAGAIN; + } + for (i=0; ifilp[i]) + f->f_count++; + if (current->pwd) + current->pwd->i_count++; + if (current->root) + current->root->i_count++; + if (current->executable) + current->executable->i_count++; + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + p->state = TASK_RUNNING; /* do this last, just in case */ + return last_pid; +} + +int find_empty_process(void) +{ + int i; + + repeat: + if ((++last_pid)<0) last_pid=1; + for(i=0 ; ipid == last_pid) goto repeat; + for(i=1 ; itss.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; +} +*/ \ No newline at end of file From 620d522d76d26b6c1c3423a1b7143e9870c5e1c1 Mon Sep 17 00:00:00 2001 From: mp6sgfx3h <1610531619@qq.com> Date: Sat, 2 Jul 2022 00:20:16 +0800 Subject: [PATCH 2/4] ADD file via upload --- system_call.s | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 system_call.s diff --git a/system_call.s b/system_call.s new file mode 100644 index 0000000..d26f913 --- /dev/null +++ b/system_call.s @@ -0,0 +1,317 @@ +/* + * linux/kernel/system_call.s + * + * (C) 1991 Linus Torvalds + */ + +/* + * system_call.s contains the system-call low-level handling routines. + * This also contains the timer-interrupt handler, as some of the code is + * the same. The hd- and flopppy-interrupts are also here. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. Ordinary interrupts + * don't handle signal-recognition, as that would clutter them up totally + * unnecessarily. + * + * Stack layout in 'ret_from_system_call': + * + * 0(%esp) - %eax + * 4(%esp) - %ebx + * 8(%esp) - %ecx + * C(%esp) - %edx + * 10(%esp) - %fs + * 14(%esp) - %es + * 18(%esp) - %ds + * 1C(%esp) - %eip + * 20(%esp) - %cs + * 24(%esp) - %eflags + * 28(%esp) - %oldesp + * 2C(%esp) - %oldss + */ + +SIG_CHLD = 17 + +EAX = 0x00 +EBX = 0x04 +ECX = 0x08 +EDX = 0x0C +FS = 0x10 +ES = 0x14 +DS = 0x18 +EIP = 0x1C +CS = 0x20 +EFLAGS = 0x24 +OLDESP = 0x28 +OLDSS = 0x2C + +state = 0 # these are offsets into the task-struct. +counter = 4 +priority = 8 +signal = 12 +sigaction = 16 # MUST be 16 (=len of sigaction) +blocked = (33*16) + +# offsets within sigaction +sa_handler = 0 +sa_mask = 4 +sa_flags = 8 +sa_restorer = 12 + +nr_system_calls = 95 /* 72 */ + +/* + * Ok, I get parallel printer interrupts while using the floppy for some + * strange reason. Urgel. Now I just ignore them. + */ +.globl system_call,sys_fork,timer_interrupt,sys_execve,sys_execve2,sys_clone +.globl hd_interrupt,floppy_interrupt,parallel_interrupt +.globl device_not_available, coprocessor_error + +.align 4 +bad_sys_call: + movl $-1,%eax + iret +.align 4 +reschedule: + pushl $ret_from_sys_call + jmp schedule +.align 4 +system_call: + cmpl $nr_system_calls-1,%eax + ja bad_sys_call + push %ds + push %es + push %fs + pushl %edx + pushl %ecx # push %ebx,%ecx,%edx as parameters + pushl %ebx # to the system call + movl $0x10,%edx # set up ds,es to kernel space + mov %dx,%ds + mov %dx,%es + movl $0x17,%edx # fs points to local data space + mov %dx,%fs + + pushl %eax #by wyj + call print_nr + popl %eax + + call sys_call_table(,%eax,4) + pushl %eax + movl current,%eax + cmpl $0,state(%eax) # state + jne reschedule + cmpl $0,counter(%eax) # counter + je reschedule +ret_from_sys_call: + movl current,%eax # task[0] cannot have signals + cmpl task,%eax + je 3f + cmpw $0x0f,CS(%esp) # was old code segment supervisor ? + jne 3f + cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ? + jne 3f + movl signal(%eax),%ebx + movl blocked(%eax),%ecx + notl %ecx + andl %ebx,%ecx + bsfl %ecx,%ecx + je 3f + btrl %ecx,%ebx + movl %ebx,signal(%eax) + incl %ecx + pushl %ecx + call do_signal + popl %eax +3: popl %eax + popl %ebx + popl %ecx + popl %edx + pop %fs + pop %es + pop %ds + iret + +.align 4 +coprocessor_error: + push %ds + push %es + push %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + pushl $ret_from_sys_call + jmp math_error + +.align 2 +device_not_available: + push %ds + push %es + push %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + pushl $ret_from_sys_call + clts # clear TS so that we can use math + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je math_state_restore + pushl %ebp + pushl %esi + pushl %edi + call math_emulate + popl %edi + popl %esi + popl %ebp + ret + +.align 4 +timer_interrupt: + push %ds # save ds,es and put kernel data space + push %es # into them. %fs is used by _system_call + push %fs + pushl %edx # we save %eax,%ecx,%edx as gcc doesn't + pushl %ecx # save those across function calls. %ebx + pushl %ebx # is saved as we use that in ret_sys_call + pushl %eax + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + incl jiffies + movb $0x20,%al # EOI to interrupt controller #1 + outb %al,$0x20 + movl CS(%esp),%eax + andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor) + pushl %eax + call do_timer # 'do_timer(long CPL)' does everything from + addl $4,%esp # task switching to accounting ... + jmp ret_from_sys_call + +.align 4 +sys_execve: + lea EIP(%esp),%eax + pushl %eax + call do_execve + addl $4,%esp + ret + +.align 4 +sys_execve2: + lea EIP(%esp),%eax + pushl %eax + call do_execve2 + addl $4,%esp + ret + +.align 4 +sys_fork: + call find_empty_process + testl %eax,%eax + js 1f + push %gs + pushl %esi + pushl %edi + pushl %ebp + pushl %eax + pushl $0x0 #for flag + call copy_process + addl $24,%esp #for flag +1: ret + +.align 4 +sys_clone: + call find_empty_process + testl %eax,%eax + js 1f + pushl %eax + push %gs + pushl %esi + pushl %edi + pushl %ebp + pushl %eax + pushl $0x1 #for flag + call copy_process + addl $24,%esp #for flag + call do_clone + addl $4,%esp +1: ret + +hd_interrupt: + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + movb $0x20,%al + outb %al,$0xA0 # EOI to interrupt controller #1 + jmp 1f # give port chance to breathe +1: jmp 1f +1: xorl %edx,%edx + xchgl do_hd,%edx + testl %edx,%edx + jne 1f + movl $unexpected_hd_interrupt,%edx +1: outb %al,$0x20 + call *%edx # "interesting" way of handling intr. + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +floppy_interrupt: + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $0x10,%eax + mov %ax,%ds + mov %ax,%es + movl $0x17,%eax + mov %ax,%fs + movb $0x20,%al + outb %al,$0x20 # EOI to interrupt controller #1 + xorl %eax,%eax + xchgl do_floppy,%eax + testl %eax,%eax + jne 1f + movl $unexpected_floppy_interrupt,%eax +1: call *%eax # "interesting" way of handling intr. + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +parallel_interrupt: + pushl %eax + movb $0x20,%al + outb %al,$0x20 + popl %eax + iret From 00ecae07ec0a939d326f6323252fd76873dc8bf9 Mon Sep 17 00:00:00 2001 From: mp6sgfx3h <1610531619@qq.com> Date: Sat, 2 Jul 2022 00:39:54 +0800 Subject: [PATCH 3/4] Update fork.c --- linux/kernel/fork.c | 101 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/linux/kernel/fork.c b/linux/kernel/fork.c index 816fdba..effc165 100644 --- a/linux/kernel/fork.c +++ b/linux/kernel/fork.c @@ -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; +} +*/ \ No newline at end of file From 083778d87cad0e18db15154a3cc7a8c5336725a5 Mon Sep 17 00:00:00 2001 From: mp6sgfx3h <1610531619@qq.com> Date: Sat, 2 Jul 2022 00:40:49 +0800 Subject: [PATCH 4/4] Update system_call.s --- linux/kernel/system_call.s | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/linux/kernel/system_call.s b/linux/kernel/system_call.s index fe13e1d..d26f913 100644 --- a/linux/kernel/system_call.s +++ b/linux/kernel/system_call.s @@ -64,7 +64,7 @@ nr_system_calls = 95 /* 72 */ * Ok, I get parallel printer interrupts while using the floppy for some * strange reason. Urgel. Now I just ignore them. */ -.globl system_call,sys_fork,timer_interrupt,sys_execve,sys_execve2 +.globl system_call,sys_fork,timer_interrupt,sys_execve,sys_execve2,sys_clone .globl hd_interrupt,floppy_interrupt,parallel_interrupt .globl device_not_available, coprocessor_error @@ -227,8 +227,27 @@ sys_fork: pushl %edi pushl %ebp pushl %eax + pushl $0x0 #for flag call copy_process - addl $20,%esp + addl $24,%esp #for flag +1: ret + +.align 4 +sys_clone: + call find_empty_process + testl %eax,%eax + js 1f + pushl %eax + push %gs + pushl %esi + pushl %edi + pushl %ebp + pushl %eax + pushl $0x1 #for flag + call copy_process + addl $24,%esp #for flag + call do_clone + addl $4,%esp 1: ret hd_interrupt: