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

📄 exec.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		set = files->close_on_exec->fds_bits[j];		if (!set)			continue;		files->close_on_exec->fds_bits[j] = 0;		write_unlock(&files->file_lock);		for ( ; set ; i++,set >>= 1) {			if (set & 1) {				sys_close(i);			}		}		write_lock(&files->file_lock);	}	write_unlock(&files->file_lock);}/* * An execve() will automatically "de-thread" the process. * Note: we don't have to hold the tasklist_lock to test * whether we migth need to do this. If we're not part of * a thread group, there is no way we can become one * dynamically. And if we are, we only need to protect the * unlink - even if we race with the last other thread exit, * at worst the list_del_init() might end up being a no-op. */static inline void de_thread(struct task_struct *tsk){	if (!list_empty(&tsk->thread_group)) {		write_lock_irq(&tasklist_lock);		list_del_init(&tsk->thread_group);		write_unlock_irq(&tasklist_lock);	}	/* Minor oddity: this might stay the same. */	tsk->tgid = tsk->pid;}int flush_old_exec(struct linux_binprm * bprm){	char * name;	int i, ch, retval;	struct signal_struct * oldsig;	/*	 * Make sure we have a private signal table	 */	oldsig = current->sig;	retval = make_private_signals();	if (retval) goto flush_failed;	/* 	 * Release all of the old mmap stuff	 */	retval = exec_mmap();	if (retval) goto mmap_failed;	/* This is the point of no return */	release_old_signals(oldsig);	current->sas_ss_sp = current->sas_ss_size = 0;	if (current->euid == current->uid && current->egid == current->gid)		current->mm->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';	flush_thread();	de_thread(current);	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 	    permission(bprm->file->f_dentry->d_inode,MAY_READ))		current->mm->dumpable = 0;	/* An exec changes our domain. We are no longer part of the thread	   group */	   	current->self_exec_id++;				flush_signal_handlers(current);	flush_old_files(current->files);	return 0;mmap_failed:flush_failed:	spin_lock_irq(&current->sigmask_lock);	if (current->sig != oldsig) {		kmem_cache_free(sigact_cachep, current->sig);		current->sig = oldsig;	}	spin_unlock_irq(&current->sigmask_lock);	return retval;}/* * We mustn't allow tracing of suid binaries, unless * the tracer has the capability to trace anything.. */static inline int must_not_trace_exec(struct task_struct * p){	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);}/*  * Fill the binprm structure from the inode.  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes */int prepare_binprm(struct linux_binprm *bprm){	int mode;	struct inode * inode = bprm->file->f_dentry->d_inode;	mode = inode->i_mode;	/*	 * Check execute perms again - if the caller has CAP_DAC_OVERRIDE,	 * vfs_permission lets a non-executable through	 */	if (!(mode & 0111))	/* with at least _one_ execute bit set */		return -EACCES;	if (bprm->file->f_op == NULL)		return -EACCES;	bprm->e_uid = current->euid;	bprm->e_gid = current->egid;	if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {		/* Set-uid? */		if (mode & S_ISUID)			bprm->e_uid = inode->i_uid;		/* 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 = inode->i_gid;	}	/* We don't have VFS support for capabilities yet */	cap_clear(bprm->cap_inheritable);	cap_clear(bprm->cap_permitted);	cap_clear(bprm->cap_effective);	/*  To support inheritance of root-permissions and suid-root         *  executables under compatibility mode, we raise all three         *  capability sets for the file.         *         *  If only the real uid is 0, we only raise the inheritable         *  and permitted sets of the executable file.         */	if (!issecure(SECURE_NOROOT)) {		if (bprm->e_uid == 0 || current->uid == 0) {			cap_set_full(bprm->cap_inheritable);			cap_set_full(bprm->cap_permitted);		}		if (bprm->e_uid == 0) 			cap_set_full(bprm->cap_effective);	}	memset(bprm->buf,0,BINPRM_BUF_SIZE);	return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);}/* * This function is used to produce the new IDs and capabilities * from the old ones and the file's capabilities. * * The formula used for evolving capabilities is: * *       pI' = pI * (***) pP' = (fP & X) | (fI & pI) *       pE' = pP' & fE          [NB. fE is 0 or ~0] * * I=Inheritable, P=Permitted, E=Effective // p=process, f=file * ' indicates post-exec(), and X is the global 'cap_bset'. * */void compute_creds(struct linux_binprm *bprm) {	kernel_cap_t new_permitted, working;	int do_unlock = 0;	new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);	working = cap_intersect(bprm->cap_inheritable,				current->cap_inheritable);	new_permitted = cap_combine(new_permitted, working);	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||	    !cap_issubset(new_permitted, current->cap_permitted)) {                current->mm->dumpable = 0;				lock_kernel();		if (must_not_trace_exec(current)		    || atomic_read(&current->fs->count) > 1		    || atomic_read(&current->files->count) > 1		    || atomic_read(&current->sig->count) > 1) {			if(!capable(CAP_SETUID)) {				bprm->e_uid = current->uid;				bprm->e_gid = current->gid;			}			if(!capable(CAP_SETPCAP)) {				new_permitted = cap_intersect(new_permitted,							current->cap_permitted);			}		}		do_unlock = 1;	}	/* For init, we want to retain the capabilities set         * in the init_task struct. Thus we skip the usual         * capability rules */	if (current->pid != 1) {		current->cap_permitted = new_permitted;		current->cap_effective =			cap_intersect(new_permitted, bprm->cap_effective);	}	        /* AUD: Audit candidate if current->cap_effective is set */        current->suid = current->euid = current->fsuid = bprm->e_uid;        current->sgid = current->egid = current->fsgid = bprm->e_gid;	if(do_unlock)		unlock_kernel();	current->keep_capabilities = 0;}void remove_arg_zero(struct linux_binprm *bprm){	if (bprm->argc) {		unsigned long offset;		char * kaddr;		struct page *page;		offset = bprm->p % PAGE_SIZE;		goto inside;		while (bprm->p++, *(kaddr+offset++)) {			if (offset != PAGE_SIZE)				continue;			offset = 0;			kunmap(page);inside:			page = bprm->page[bprm->p/PAGE_SIZE];			kaddr = kmap(page);		}		kunmap(page);		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)	    {		struct file * file;		unsigned long loader;		allow_write_access(bprm->file);		fput(bprm->file);		bprm->file = NULL;	        loader = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);		file = open_exec("/sbin/loader");		retval = PTR_ERR(file);		if (IS_ERR(file))			return retval;		/* Remember if the application is TASO.  */		bprm->sh_bang = eh->ah.entry < 0x100000000;		bprm->file = file;		bprm->loader = loader;		retval = prepare_binprm(bprm);		if (retval<0)			return retval;		/* should call search_binary_handler recursively here,		   but it does not matter */	    }	}#endif	/* kernel module loader fixup */	/* so we don't try to load run modprobe in kernel space. */	set_fs(USER_DS);	for (try=0; try<2; try++) {		read_lock(&binfmt_lock);		for (fmt = formats ; fmt ; fmt = fmt->next) {			int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;			if (!fn)				continue;			if (!try_inc_mod_count(fmt->module))				continue;			read_unlock(&binfmt_lock);			retval = fn(bprm, regs);			if (retval >= 0) {				put_binfmt(fmt);				allow_write_access(bprm->file);				if (bprm->file)					fput(bprm->file);				bprm->file = NULL;				current->did_exec = 1;				return retval;			}			read_lock(&binfmt_lock);			put_binfmt(fmt);			if (retval != -ENOEXEC)				break;			if (!bprm->file) {				read_unlock(&binfmt_lock);				return retval;			}		}		read_unlock(&binfmt_lock);		if (retval != -ENOEXEC) {			break;#ifdef CONFIG_KMOD		}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-%04x", *(unsigned short *)(&bprm->buf[2]));			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;	struct file *file;	int retval;	int i;	file = open_exec(filename);	retval = PTR_ERR(file);	if (IS_ERR(file))		return retval;	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); 	bprm.file = file;	bprm.filename = filename;	bprm.sh_bang = 0;	bprm.loader = 0;	bprm.exec = 0;	if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {		allow_write_access(file);		fput(file);		return bprm.argc;	}	if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {		allow_write_access(file);		fput(file);		return bprm.envc;	}	retval = prepare_binprm(&bprm);	if (retval < 0) 		goto out; 	retval = copy_strings_kernel(1, &bprm.filename, &bprm);	if (retval < 0) 		goto out; 	bprm.exec = bprm.p;	retval = copy_strings(bprm.envc, envp, &bprm);	if (retval < 0) 		goto out; 	retval = copy_strings(bprm.argc, argv, &bprm);	if (retval < 0) 		goto out; 	retval = search_binary_handler(&bprm,regs);	if (retval >= 0)		/* execve success */		return retval;out:	/* Something went wrong, return the inode and free the argument pages*/	allow_write_access(bprm.file);	if (bprm.file)		fput(bprm.file);	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {		struct page * page = bprm.page[i];		if (page)			__free_page(page);	}	return retval;}void set_binfmt(struct linux_binfmt *new){	struct linux_binfmt *old = current->binfmt;	if (new && new->module)		__MOD_INC_USE_COUNT(new->module);	current->binfmt = new;	if (old && old->module)		__MOD_DEC_USE_COUNT(old->module);}int do_coredump(long signr, struct pt_regs * regs){	struct linux_binfmt * binfmt;	char corename[6+sizeof(current->comm)+10];	struct file * file;	struct inode * inode;	int retval = 0;	lock_kernel();	binfmt = current->binfmt;	if (!binfmt || !binfmt->core_dump)		goto fail;	if (!current->mm->dumpable)		goto fail;	current->mm->dumpable = 0;	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)		goto fail;	memcpy(corename,"core.", 5);	corename[4] = '\0'; 	if (core_uses_pid || atomic_read(&current->mm->mm_users) != 1) 		sprintf(&corename[4], ".%d", current->pid);	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW, 0600);	if (IS_ERR(file))		goto fail;	inode = file->f_dentry->d_inode;	if (inode->i_nlink > 1)		goto close_fail;	/* multiple links - don't dump */	if (d_unhashed(file->f_dentry))		goto close_fail;	if (!S_ISREG(inode->i_mode))		goto close_fail;	if (!file->f_op)		goto close_fail;	if (!file->f_op->write)		goto close_fail;	if (do_truncate(file->f_dentry, 0) != 0)		goto close_fail;	retval = binfmt->core_dump(signr, regs, file);close_fail:	filp_close(file, NULL);fail:	unlock_kernel();	return retval;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -