📄 exec.c
字号:
file.f_op = inode->i_op->default_file_ops; if (file.f_op->open) if (file.f_op->open(inode,&file)) goto end_readexec; if (!file.f_op || !file.f_op->read) goto close_readexec; if (file.f_op->lseek) { if (file.f_op->lseek(inode,&file,offset,0) != offset) goto close_readexec; } else file.f_pos = offset; if (to_kmem) { unsigned long old_fs = get_fs(); set_fs(get_ds()); result = file.f_op->read(inode, &file, addr, count); set_fs(old_fs); } else { result = verify_area(VERIFY_WRITE, addr, count); if (result) goto close_readexec; result = file.f_op->read(inode, &file, addr, count); }close_readexec: if (file.f_op->release) file.f_op->release(inode,&file);end_readexec: return result;}static void exec_mmap(void){ /* * The clear_page_tables done later on exec does the right thing * to the page directory when shared, except for graceful abort * (the oom is wrong there, too, IMHO) */ if (current->mm->count > 1) { struct mm_struct *mm = kmalloc(sizeof(*mm), GFP_KERNEL); if (!mm) { /* this is wrong, I think. */ oom(current); return; } *mm = *current->mm; mm->def_flags = 0; /* should future lockings be kept? */ mm->count = 1; mm->mmap = NULL; mm->mmap_avl = NULL; mm->total_vm = 0; mm->rss = 0; current->mm->count--; current->mm = mm; new_page_tables(current); return; } exit_mmap(current->mm); clear_page_tables(current);}/* * These functions flushes out all traces of the currently running executable * so that a new one can be started */static inline void flush_old_signals(struct signal_struct *sig){ int i; struct sigaction * sa = sig->action; for (i=32 ; i != 0 ; i--) { sa->sa_mask = 0; sa->sa_flags = 0; if (sa->sa_handler != SIG_IGN) sa->sa_handler = NULL; sa++; }}static inline void flush_old_files(struct files_struct * files){ unsigned long j; j = 0; for (;;) { unsigned long set, i; i = j * __NFDBITS; if (i >= NR_OPEN) break; set = files->close_on_exec.fds_bits[j]; files->close_on_exec.fds_bits[j] = 0; j++; for ( ; set ; i++,set >>= 1) { if (set & 1) sys_close(i); } }}void flush_old_exec(struct linux_binprm * bprm){ int i; int ch; char * name; if (current->euid == current->uid && current->egid == current->gid) current->dumpable = 1; name = bprm->filename; for (i=0; (ch = *(name++)) != '\0';) { if (ch == '/') i = 0; else if (i < 15) current->comm[i++] = ch; } current->comm[i] = '\0'; /* Release all of the old mmap stuff. */ exec_mmap(); flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || permission(bprm->inode,MAY_READ)) current->dumpable = 0; flush_old_signals(current->sig); flush_old_files(current->files);}/* * Fill the binprm structure from the inode. * Check permissions, then read the first 512 bytes */int prepare_binprm(struct linux_binprm *bprm){ int mode; int retval,id_change; mode = bprm->inode->i_mode; if (!S_ISREG(mode)) /* must be regular file */ return -EACCES; if (!(mode & 0111)) /* with at least _one_ execute bit set */ return -EACCES; if (IS_NOEXEC(bprm->inode)) /* FS mustn't be mounted noexec */ return -EACCES; if (!bprm->inode->i_sb) return -EACCES; if ((retval = permission(bprm->inode, MAY_EXEC)) != 0) return retval; /* better not execute files which are being written to */ if (bprm->inode->i_writecount > 0) return -ETXTBSY; bprm->e_uid = current->euid; bprm->e_gid = current->egid; id_change = 0; /* Set-uid? */ if (mode & S_ISUID) { bprm->e_uid = bprm->inode->i_uid; if (bprm->e_uid != current->euid) id_change = 1; } /* Set-gid? */ /* * If setgid is set but no group execute bit then this * is a candidate for mandatory locking, not a setgid * executable. */ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { bprm->e_gid = bprm->inode->i_gid; if (!in_group_p(bprm->e_gid)) id_change = 1; } if (id_change) { /* We can't suid-execute if we're sharing parts of the executable */ /* or if we're being traced (or if suid execs are not allowed) */ /* (current->mm->count > 1 is ok, as we'll get a new mm anyway) */ if (IS_NOSUID(bprm->inode) || (current->flags & PF_PTRACED) || (current->fs->count > 1) || (current->sig->count > 1) || (current->files->count > 1)) { if (!suser()) return -EPERM; } } memset(bprm->buf,0,sizeof(bprm->buf)); return read_exec(bprm->inode,0,bprm->buf,128,1);}void remove_arg_zero(struct linux_binprm *bprm){ if (bprm->argc) { unsigned long offset; char * page; offset = bprm->p % PAGE_SIZE; page = (char*)bprm->page[bprm->p/PAGE_SIZE]; while(bprm->p++,*(page+offset++)) if(offset==PAGE_SIZE){ offset=0; page = (char*)bprm->page[bprm->p/PAGE_SIZE]; } bprm->argc--; }}/* * cycle the list of binary formats handler, until one recognizes the image */int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs){ int try,retval=0; struct linux_binfmt *fmt;#ifdef __alpha__ /* handle /sbin/loader.. */ { struct exec * eh = (struct exec *) bprm->buf; if (!bprm->loader && eh->fh.f_magic == 0x183 && (eh->fh.f_flags & 0x3000) == 0x3000) { char * dynloader[] = { "/sbin/loader" }; iput(bprm->inode); bprm->dont_iput = 1; remove_arg_zero(bprm); bprm->p = copy_strings(1, dynloader, bprm->page, bprm->p, 2); bprm->argc++; bprm->loader = bprm->p; retval = open_namei(dynloader[0], 0, 0, &bprm->inode, NULL); if (retval) return retval; bprm->dont_iput = 0; retval = prepare_binprm(bprm); if (retval<0) return retval; /* should call search_binary_handler recursively here, but it does not matter */ } }#endif for (try=0; try<2; try++) { for (fmt = formats ; fmt ; fmt = fmt->next) { int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; if (!fn) continue; retval = fn(bprm, regs); if (retval >= 0) { if(!bprm->dont_iput) iput(bprm->inode); bprm->dont_iput=1; current->did_exec = 1; return retval; } if (retval != -ENOEXEC) break; if (bprm->dont_iput) /* We don't have the inode anymore*/ return retval; } if (retval != -ENOEXEC) { break;#ifdef CONFIG_KERNELD }else{#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e)) char modname[20]; if (printable(bprm->buf[0]) && printable(bprm->buf[1]) && printable(bprm->buf[2]) && printable(bprm->buf[3])) break; /* -ENOEXEC */ sprintf(modname, "binfmt-%hd", *(short*)(&bprm->buf)); request_module(modname);#endif } } return retval;}/* * sys_execve() executes a new program. */int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs){ struct linux_binprm bprm; int retval; int i; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; retval = open_namei(filename, 0, 0, &bprm.inode, NULL); if (retval) return retval; bprm.filename = filename; bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; bprm.dont_iput = 0; if ((bprm.argc = count(argv)) < 0) return bprm.argc; if ((bprm.envc = count(envp)) < 0) return bprm.envc; retval = prepare_binprm(&bprm); if(retval>=0) { bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2); bprm.exec = bprm.p; bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p,0); bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p,0); if (!bprm.p) retval = -E2BIG; } if(retval>=0) retval = search_binary_handler(&bprm,regs); if(retval>=0) /* execve success */ return retval; /* Something went wrong, return the inode and free the argument pages*/ if(!bprm.dont_iput) iput(bprm.inode); for (i=0 ; i<MAX_ARG_PAGES ; i++) free_page(bprm.page[i]); return(retval);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -