/*����ֻ������������do_execve2,exec.c�������ط���û�иĶ� * do_execve2��Ҫʵ�����������ط�ʽִ�п�ִ���ļ���ֻ��Ҫ���պ���do_no_page���������ȶ�����ҳ����ҳ���ϴ������� * ��������my_do_no_page���������ܺ�do_no_page��ȫһ�� * ����дһ����ԭ���ǣ���������ԭ�ȵ�do_no_page�����������Ӵ�ӡ��Ϣ * �������ʹ��ԭ�ȵ�do_no_page������ÿ��һ�ζ����ӡ��Ϣ * �������޷��б�do_execve2������û��ʵ���������صĹ��� */ int do_execve2(unsigned long* eip, long tmp, char* filename, char** argv, char** envp) { struct m_inode* inode; struct buffer_head* bh; struct exec ex; unsigned long page[MAX_ARG_PAGES]; int i, argc, envc; int e_uid, e_gid; int retval; int sh_bang = 0; unsigned long p = PAGE_SIZE * MAX_ARG_PAGES - 4; if ((0xffff & eip[1]) != 0x000f) panic("execve2 called from supervisor mode"); for (i = 0; i < MAX_ARG_PAGES; i++) /* clear page-table */ page[i] = 0; if (!(inode = namei(filename))) /* get executables inode */ return -ENOENT; argc = count(argv); envc = count(envp); restart_interp: if (!S_ISREG(inode->i_mode)) { /* must be regular file */ retval = -EACCES; goto exec_error2; } i = inode->i_mode; e_uid = (i & S_ISUID) ? inode->i_uid : current->euid; e_gid = (i & S_ISGID) ? inode->i_gid : current->egid; if (current->euid == inode->i_uid) i >>= 6; else if (current->egid == inode->i_gid) i >>= 3; if (!(i & 1) && !((inode->i_mode & 0111) && suser())) { retval = -ENOEXEC; goto exec_error2; } if (!(bh = bread(inode->i_dev, inode->i_zone[0]))) { retval = -EACCES; goto exec_error2; } ex = *((struct exec*)bh->b_data); /* read exec-header */ if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) { /* * This section does the #! interpretation. * Sorta complicated, but hopefully it will work. -TYT */ char buf[1023], * cp, * interp, * i_name, * i_arg; unsigned long old_fs; strncpy(buf, bh->b_data + 2, 1022); brelse(bh); iput(inode); buf[1022] = '\0'; if (cp = strchr(buf, '\n')) { *cp = '\0'; for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++); } if (!cp || *cp == '\0') { retval = -ENOEXEC; /* No interpreter name found */ goto exec_error1; } interp = i_name = cp; i_arg = 0; for (; *cp && (*cp != ' ') && (*cp != '\t'); cp++) { if (*cp == '/') i_name = cp + 1; } if (*cp) { *cp++ = '\0'; i_arg = cp; } /* * OK, we've parsed out the interpreter name and * (optional) argument. */ if (sh_bang++ == 0) { p = copy_strings(envc, envp, page, p, 0); p = copy_strings(--argc, argv + 1, page, p, 0); } /* * Splice in (1) the interpreter's name for argv[0] * (2) (optional) argument to interpreter * (3) filename of shell script * * This is done in reverse order, because of how the * user environment and arguments are stored. */ p = copy_strings(1, &filename, page, p, 1); argc++; if (i_arg) { p = copy_strings(1, &i_arg, page, p, 2); argc++; } p = copy_strings(1, &i_name, page, p, 2); argc++; if (!p) { retval = -ENOMEM; goto exec_error1; } /* * OK, now restart the process with the interpreter's inode. */ old_fs = get_fs(); set_fs(get_ds()); if (!(inode = namei(interp))) { /* get executables inode */ set_fs(old_fs); retval = -ENOENT; goto exec_error1; } set_fs(old_fs); goto restart_interp; } brelse(bh); if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize || ex.a_text + ex.a_data + ex.a_bss > 0x3000000 || inode->i_size < ex.a_text + ex.a_data + ex.a_syms + N_TXTOFF(ex)) { retval = -ENOEXEC; goto exec_error2; } if (N_TXTOFF(ex) != BLOCK_SIZE) { printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename); retval = -ENOEXEC; goto exec_error2; } if (!sh_bang) { p = copy_strings(envc, envp, page, p, 0); p = copy_strings(argc, argv, page, p, 0); if (!p) { retval = -ENOMEM; goto exec_error2; } } /* OK, This is the point of no return */ if (current->executable) iput(current->executable); current->executable = inode; for (i = 0; i < 32; i++) current->sigaction[i].sa_handler = NULL; for (i = 0; i < NR_OPEN; i++) if ((current->close_on_exec >> i) & 1) sys_close(i); current->close_on_exec = 0; free_page_tables(get_base(current->ldt[1]), get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]), get_limit(0x17)); if (last_task_used_math == current) last_task_used_math = NULL; current->used_math = 0; p += change_ldt(ex.a_text, page) - MAX_ARG_PAGES * PAGE_SIZE; p = (unsigned long)create_tables((char*)p, argc, envc); current->brk = ex.a_bss + (current->end_data = ex.a_data + (current->end_code = ex.a_text)); current->start_stack = p & 0xfffff000; current->euid = e_uid; current->egid = e_gid; /* �޸IJ��� */ unsigned long No_Page_Addr; unsigned long Addr_End = (current->brk - 1) & 0xfffff000; for (No_Page_Addr = 0; No_Page_Addr <= Addr_End; No_Page_Addr += 0x1000) my_do_no_page(4, No_Page_Addr + current->start_code); /* �����ԣ�����������Ϊ4��6�����ԣ�4��ʾ�ɶ���������6��ʾ��д�������� */ /* �޸IJ��� */ i = ex.a_text + ex.a_data; while (i & 0xfff) put_fs_byte(0, (char*)(i++)); eip[0] = ex.a_entry; /* eip, magic happens :-) */ eip[3] = p; /* stack pointer */ return 0; exec_error2: iput(inode); exec_error1: for (i = 0; i < MAX_ARG_PAGES; i++) free_page(page[i]); return(retval); }