New locking/refcounting for fs_struct

* all changes of current->fs are done under task_lock and write_lock of
  old fs->lock
* refcount is not atomic anymore (same protection)
* its decrements are done when removing reference from current; at the
  same time we decide whether to free it.
* put_fs_struct() is gone
* new field - ->in_exec.  Set by check_unsafe_exec() if we are trying to do
  execve() and only subthreads share fs_struct.  Cleared when finishing exec
  (success and failure alike).  Makes CLONE_FS fail with -EAGAIN if set.
* check_unsafe_exec() may fail with -EAGAIN if another execve() from subthread
  is in progress.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro
2009-03-30 07:20:30 -04:00
parent 3e93cd6718
commit 498052bba5
7 changed files with 121 additions and 44 deletions

View File

@@ -51,6 +51,7 @@
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/eventpoll.h>
#include <linux/fs_struct.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -1441,12 +1442,15 @@ int compat_do_execve(char * filename,
bprm->cred = prepare_exec_creds();
if (!bprm->cred)
goto out_unlock;
check_unsafe_exec(bprm);
retval = check_unsafe_exec(bprm);
if (retval)
goto out_unlock;
file = open_exec(filename);
retval = PTR_ERR(file);
if (IS_ERR(file))
goto out_unlock;
goto out_unmark;
sched_exec();
@@ -1488,6 +1492,9 @@ int compat_do_execve(char * filename,
goto out;
/* execve succeeded */
write_lock(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);
acct_update_integrals(current);
@@ -1506,6 +1513,11 @@ out_file:
fput(bprm->file);
}
out_unmark:
write_lock(&current->fs->lock);
current->fs->in_exec = 0;
write_unlock(&current->fs->lock);
out_unlock:
current->in_execve = 0;
mutex_unlock(&current->cred_exec_mutex);