⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exec.c

📁 unix/linux 编程实践一书的所有源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -