Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: [PATCH] sanitize locate_fd() [PATCH] sanitize unshare_files/reset_files_struct [PATCH] sanitize handling of shared descriptor tables in failing execve() [PATCH] close race in unshare_files() [PATCH] restore sane ->umount_begin() API cifs: timeout dfs automounts +little fix.
This commit is contained in:
@@ -507,10 +507,9 @@ void put_files_struct(struct files_struct *files)
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(put_files_struct);
|
||||
|
||||
void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
|
||||
void reset_files_struct(struct files_struct *files)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct files_struct *old;
|
||||
|
||||
old = tsk->files;
|
||||
@@ -519,7 +518,6 @@ void reset_files_struct(struct task_struct *tsk, struct files_struct *files)
|
||||
task_unlock(tsk);
|
||||
put_files_struct(old);
|
||||
}
|
||||
EXPORT_SYMBOL(reset_files_struct);
|
||||
|
||||
void exit_files(struct task_struct *tsk)
|
||||
{
|
||||
|
@@ -805,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we may be using current for both targets (See exec.c)
|
||||
* This works because we cache current->files (old) as oldf. Don't
|
||||
* break this.
|
||||
*/
|
||||
tsk->files = NULL;
|
||||
newf = dup_fd(oldf, &error);
|
||||
if (!newf)
|
||||
goto out;
|
||||
@@ -846,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper to unshare the files of the current task.
|
||||
* We don't want to expose copy_files internals to
|
||||
* the exec layer of the kernel.
|
||||
*/
|
||||
|
||||
int unshare_files(void)
|
||||
{
|
||||
struct files_struct *files = current->files;
|
||||
int rc;
|
||||
|
||||
BUG_ON(!files);
|
||||
|
||||
/* This can race but the race causes us to copy when we don't
|
||||
need to and drop the copy */
|
||||
if(atomic_read(&files->count) == 1)
|
||||
{
|
||||
atomic_inc(&files->count);
|
||||
return 0;
|
||||
}
|
||||
rc = copy_files(0, current);
|
||||
if(rc)
|
||||
current->files = files;
|
||||
return rc;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(unshare_files);
|
||||
|
||||
static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
|
||||
{
|
||||
struct sighand_struct *sig;
|
||||
@@ -1811,3 +1777,27 @@ bad_unshare_cleanup_thread:
|
||||
bad_unshare_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper to unshare the files of the current task.
|
||||
* We don't want to expose copy_files internals to
|
||||
* the exec layer of the kernel.
|
||||
*/
|
||||
|
||||
int unshare_files(struct files_struct **displaced)
|
||||
{
|
||||
struct task_struct *task = current;
|
||||
struct files_struct *copy;
|
||||
int error;
|
||||
|
||||
error = unshare_fd(CLONE_FILES, ©);
|
||||
if (error || !copy) {
|
||||
*displaced = NULL;
|
||||
return error;
|
||||
}
|
||||
*displaced = task->files;
|
||||
task_lock(task);
|
||||
task->files = copy;
|
||||
task_unlock(task);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user