[PATCH] unshare system call -v5: unshare files
If the file descriptor structure is being shared, allocate a new one and copy information from the current, shared, structure. Signed-off-by: Janak Desai <janak@us.ibm.com> Cc: Al Viro <viro@ftp.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Cc: Michael Kerrisk <mtk-manpages@gmx.net> Cc: Andi Kleen <ak@muc.de> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
a0a7ec308f
commit
a016f3389c
|
@ -620,32 +620,17 @@ out:
|
|||
return newf;
|
||||
}
|
||||
|
||||
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
||||
/*
|
||||
* Allocate a new files structure and copy contents from the
|
||||
* passed in files structure.
|
||||
*/
|
||||
static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
|
||||
{
|
||||
struct files_struct *oldf, *newf;
|
||||
struct files_struct *newf;
|
||||
struct file **old_fds, **new_fds;
|
||||
int open_files, size, i, error = 0, expand;
|
||||
int open_files, size, i, expand;
|
||||
struct fdtable *old_fdt, *new_fdt;
|
||||
|
||||
/*
|
||||
* A background process may not have any files ...
|
||||
*/
|
||||
oldf = current->files;
|
||||
if (!oldf)
|
||||
goto out;
|
||||
|
||||
if (clone_flags & CLONE_FILES) {
|
||||
atomic_inc(&oldf->count);
|
||||
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;
|
||||
error = -ENOMEM;
|
||||
newf = alloc_files();
|
||||
if (!newf)
|
||||
goto out;
|
||||
|
@ -674,9 +659,9 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
|||
if (expand) {
|
||||
spin_unlock(&oldf->file_lock);
|
||||
spin_lock(&newf->file_lock);
|
||||
error = expand_files(newf, open_files-1);
|
||||
*errorp = expand_files(newf, open_files-1);
|
||||
spin_unlock(&newf->file_lock);
|
||||
if (error < 0)
|
||||
if (*errorp < 0)
|
||||
goto out_release;
|
||||
new_fdt = files_fdtable(newf);
|
||||
/*
|
||||
|
@ -725,10 +710,8 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
|||
memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
|
||||
}
|
||||
|
||||
tsk->files = newf;
|
||||
error = 0;
|
||||
out:
|
||||
return error;
|
||||
return newf;
|
||||
|
||||
out_release:
|
||||
free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
|
||||
|
@ -738,6 +721,40 @@ out_release:
|
|||
goto out;
|
||||
}
|
||||
|
||||
static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
||||
{
|
||||
struct files_struct *oldf, *newf;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
* A background process may not have any files ...
|
||||
*/
|
||||
oldf = current->files;
|
||||
if (!oldf)
|
||||
goto out;
|
||||
|
||||
if (clone_flags & CLONE_FILES) {
|
||||
atomic_inc(&oldf->count);
|
||||
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;
|
||||
error = -ENOMEM;
|
||||
newf = dup_fd(oldf, &error);
|
||||
if (!newf)
|
||||
goto out;
|
||||
|
||||
tsk->files = newf;
|
||||
error = 0;
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper to unshare the files of the current task.
|
||||
* We don't want to expose copy_files internals to
|
||||
|
@ -1463,15 +1480,19 @@ static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
|
|||
}
|
||||
|
||||
/*
|
||||
* Unsharing of files for tasks created with CLONE_FILES is not supported yet
|
||||
* Unshare file descriptor table if it is being shared
|
||||
*/
|
||||
static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
|
||||
{
|
||||
struct files_struct *fd = current->files;
|
||||
int error = 0;
|
||||
|
||||
if ((unshare_flags & CLONE_FILES) &&
|
||||
(fd && atomic_read(&fd->count) > 1))
|
||||
return -EINVAL;
|
||||
(fd && atomic_read(&fd->count) > 1)) {
|
||||
*new_fdp = dup_fd(fd, &error);
|
||||
if (!*new_fdp)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue