mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
[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
1 changed files with 51 additions and 30 deletions
|
@ -620,32 +620,17 @@ out:
|
||||||
return newf;
|
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;
|
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;
|
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();
|
newf = alloc_files();
|
||||||
if (!newf)
|
if (!newf)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -674,9 +659,9 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
|
||||||
if (expand) {
|
if (expand) {
|
||||||
spin_unlock(&oldf->file_lock);
|
spin_unlock(&oldf->file_lock);
|
||||||
spin_lock(&newf->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);
|
spin_unlock(&newf->file_lock);
|
||||||
if (error < 0)
|
if (*errorp < 0)
|
||||||
goto out_release;
|
goto out_release;
|
||||||
new_fdt = files_fdtable(newf);
|
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);
|
memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
tsk->files = newf;
|
|
||||||
error = 0;
|
|
||||||
out:
|
out:
|
||||||
return error;
|
return newf;
|
||||||
|
|
||||||
out_release:
|
out_release:
|
||||||
free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
|
free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
|
||||||
|
@ -738,6 +721,40 @@ out_release:
|
||||||
goto out;
|
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.
|
* Helper to unshare the files of the current task.
|
||||||
* We don't want to expose copy_files internals to
|
* 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)
|
static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
|
||||||
{
|
{
|
||||||
struct files_struct *fd = current->files;
|
struct files_struct *fd = current->files;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if ((unshare_flags & CLONE_FILES) &&
|
if ((unshare_flags & CLONE_FILES) &&
|
||||||
(fd && atomic_read(&fd->count) > 1))
|
(fd && atomic_read(&fd->count) > 1)) {
|
||||||
return -EINVAL;
|
*new_fdp = dup_fd(fd, &error);
|
||||||
|
if (!*new_fdp)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue