[PATCH] sanitize unshare_files/reset_files_struct
* let unshare_files() give caller the displaced files_struct * don't bother with grabbing reference only to drop it in the caller if it hadn't been shared in the first place * in that form unshare_files() is trivially implemented via unshare_fd(), so we eliminate the duplicate logics in fork.c * reset_files_struct() is not just only called for current; it will break the system if somebody ever calls it for anything else (we can't modify ->files of somebody else). Lose the task_struct * argument. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -507,8 +507,9 @@ void put_files_struct(struct files_struct *files)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@@ -840,36 +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;
|
||||
struct files_struct *newf;
|
||||
int error = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
newf = dup_fd(files, &error);
|
||||
if (newf) {
|
||||
task_lock(current);
|
||||
current->files = newf;
|
||||
task_unlock(current);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
|
||||
{
|
||||
struct sighand_struct *sig;
|
||||
@@ -1807,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