diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 32 | 
1 files changed, 16 insertions, 16 deletions
diff --git a/fs/exec.c b/fs/exec.c index 052a961e41a..639177b0eea 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -69,17 +69,18 @@ int suid_dumpable = 0;  static LIST_HEAD(formats);  static DEFINE_RWLOCK(binfmt_lock); -int register_binfmt(struct linux_binfmt * fmt) +int __register_binfmt(struct linux_binfmt * fmt, int insert)  {  	if (!fmt)  		return -EINVAL;  	write_lock(&binfmt_lock); -	list_add(&fmt->lh, &formats); +	insert ? list_add(&fmt->lh, &formats) : +		 list_add_tail(&fmt->lh, &formats);  	write_unlock(&binfmt_lock);  	return 0;	  } -EXPORT_SYMBOL(register_binfmt); +EXPORT_SYMBOL(__register_binfmt);  void unregister_binfmt(struct linux_binfmt * fmt)  { @@ -1060,7 +1061,6 @@ EXPORT_SYMBOL(install_exec_creds);  int check_unsafe_exec(struct linux_binprm *bprm)  {  	struct task_struct *p = current, *t; -	unsigned long flags;  	unsigned n_fs;  	int res = 0; @@ -1068,21 +1068,22 @@ int check_unsafe_exec(struct linux_binprm *bprm)  	n_fs = 1;  	write_lock(&p->fs->lock); -	lock_task_sighand(p, &flags); +	rcu_read_lock();  	for (t = next_thread(p); t != p; t = next_thread(t)) {  		if (t->fs == p->fs)  			n_fs++;  	} +	rcu_read_unlock();  	if (p->fs->users > n_fs) {  		bprm->unsafe |= LSM_UNSAFE_SHARE;  	} else { -		if (p->fs->in_exec) -			res = -EAGAIN; -		p->fs->in_exec = 1; +		res = -EAGAIN; +		if (!p->fs->in_exec) { +			p->fs->in_exec = 1; +			res = 1; +		}  	} - -	unlock_task_sighand(p, &flags);  	write_unlock(&p->fs->lock);  	return res; @@ -1284,6 +1285,7 @@ int do_execve(char * filename,  	struct linux_binprm *bprm;  	struct file *file;  	struct files_struct *displaced; +	bool clear_in_exec;  	int retval;  	retval = unshare_files(&displaced); @@ -1306,8 +1308,9 @@ int do_execve(char * filename,  		goto out_unlock;  	retval = check_unsafe_exec(bprm); -	if (retval) +	if (retval < 0)  		goto out_unlock; +	clear_in_exec = retval;  	file = open_exec(filename);  	retval = PTR_ERR(file); @@ -1355,9 +1358,7 @@ int do_execve(char * filename,  		goto out;  	/* execve succeeded */ -	write_lock(¤t->fs->lock);  	current->fs->in_exec = 0; -	write_unlock(¤t->fs->lock);  	current->in_execve = 0;  	mutex_unlock(¤t->cred_exec_mutex);  	acct_update_integrals(current); @@ -1377,9 +1378,8 @@ out_file:  	}  out_unmark: -	write_lock(¤t->fs->lock); -	current->fs->in_exec = 0; -	write_unlock(¤t->fs->lock); +	if (clear_in_exec) +		current->fs->in_exec = 0;  out_unlock:  	current->in_execve = 0;  |