|
@@ -1515,26 +1515,6 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Unshare the mnt_namespace structure if it is being shared
|
|
|
- */
|
|
|
-static int unshare_mnt_namespace(unsigned long unshare_flags,
|
|
|
- struct mnt_namespace **new_nsp, struct fs_struct *new_fs)
|
|
|
-{
|
|
|
- struct mnt_namespace *ns = current->nsproxy->mnt_ns;
|
|
|
-
|
|
|
- if ((unshare_flags & CLONE_NEWNS) && ns) {
|
|
|
- if (!capable(CAP_SYS_ADMIN))
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
- *new_nsp = dup_mnt_ns(current, new_fs ? new_fs : current->fs);
|
|
|
- if (!*new_nsp)
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Unsharing of sighand is not supported yet
|
|
|
*/
|
|
@@ -1593,16 +1573,6 @@ static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **n
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#ifndef CONFIG_IPC_NS
|
|
|
-static inline int unshare_ipcs(unsigned long flags, struct ipc_namespace **ns)
|
|
|
-{
|
|
|
- if (flags & CLONE_NEWIPC)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* unshare allows a process to 'unshare' part of the process
|
|
|
* context which was originally shared using clone. copy_*
|
|
@@ -1615,14 +1585,11 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
{
|
|
|
int err = 0;
|
|
|
struct fs_struct *fs, *new_fs = NULL;
|
|
|
- struct mnt_namespace *ns, *new_ns = NULL;
|
|
|
struct sighand_struct *new_sigh = NULL;
|
|
|
struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
|
|
|
struct files_struct *fd, *new_fd = NULL;
|
|
|
struct sem_undo_list *new_ulist = NULL;
|
|
|
struct nsproxy *new_nsproxy = NULL, *old_nsproxy = NULL;
|
|
|
- struct uts_namespace *uts, *new_uts = NULL;
|
|
|
- struct ipc_namespace *ipc, *new_ipc = NULL;
|
|
|
|
|
|
check_unshare_flags(&unshare_flags);
|
|
|
|
|
@@ -1637,36 +1604,24 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
goto bad_unshare_out;
|
|
|
if ((err = unshare_fs(unshare_flags, &new_fs)))
|
|
|
goto bad_unshare_cleanup_thread;
|
|
|
- if ((err = unshare_mnt_namespace(unshare_flags, &new_ns, new_fs)))
|
|
|
- goto bad_unshare_cleanup_fs;
|
|
|
if ((err = unshare_sighand(unshare_flags, &new_sigh)))
|
|
|
- goto bad_unshare_cleanup_ns;
|
|
|
+ goto bad_unshare_cleanup_fs;
|
|
|
if ((err = unshare_vm(unshare_flags, &new_mm)))
|
|
|
goto bad_unshare_cleanup_sigh;
|
|
|
if ((err = unshare_fd(unshare_flags, &new_fd)))
|
|
|
goto bad_unshare_cleanup_vm;
|
|
|
if ((err = unshare_semundo(unshare_flags, &new_ulist)))
|
|
|
goto bad_unshare_cleanup_fd;
|
|
|
- if ((err = unshare_utsname(unshare_flags, &new_uts)))
|
|
|
+ if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
|
|
|
+ new_fs)))
|
|
|
goto bad_unshare_cleanup_semundo;
|
|
|
- if ((err = unshare_ipcs(unshare_flags, &new_ipc)))
|
|
|
- goto bad_unshare_cleanup_uts;
|
|
|
-
|
|
|
- if (new_ns || new_uts || new_ipc) {
|
|
|
- old_nsproxy = current->nsproxy;
|
|
|
- new_nsproxy = dup_namespaces(old_nsproxy);
|
|
|
- if (!new_nsproxy) {
|
|
|
- err = -ENOMEM;
|
|
|
- goto bad_unshare_cleanup_ipc;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- if (new_fs || new_ns || new_mm || new_fd || new_ulist ||
|
|
|
- new_uts || new_ipc) {
|
|
|
+ if (new_fs || new_mm || new_fd || new_ulist || new_nsproxy) {
|
|
|
|
|
|
task_lock(current);
|
|
|
|
|
|
if (new_nsproxy) {
|
|
|
+ old_nsproxy = current->nsproxy;
|
|
|
current->nsproxy = new_nsproxy;
|
|
|
new_nsproxy = old_nsproxy;
|
|
|
}
|
|
@@ -1677,12 +1632,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
new_fs = fs;
|
|
|
}
|
|
|
|
|
|
- if (new_ns) {
|
|
|
- ns = current->nsproxy->mnt_ns;
|
|
|
- current->nsproxy->mnt_ns = new_ns;
|
|
|
- new_ns = ns;
|
|
|
- }
|
|
|
-
|
|
|
if (new_mm) {
|
|
|
mm = current->mm;
|
|
|
active_mm = current->active_mm;
|
|
@@ -1698,32 +1647,12 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
|
|
|
new_fd = fd;
|
|
|
}
|
|
|
|
|
|
- if (new_uts) {
|
|
|
- uts = current->nsproxy->uts_ns;
|
|
|
- current->nsproxy->uts_ns = new_uts;
|
|
|
- new_uts = uts;
|
|
|
- }
|
|
|
-
|
|
|
- if (new_ipc) {
|
|
|
- ipc = current->nsproxy->ipc_ns;
|
|
|
- current->nsproxy->ipc_ns = new_ipc;
|
|
|
- new_ipc = ipc;
|
|
|
- }
|
|
|
-
|
|
|
task_unlock(current);
|
|
|
}
|
|
|
|
|
|
if (new_nsproxy)
|
|
|
put_nsproxy(new_nsproxy);
|
|
|
|
|
|
-bad_unshare_cleanup_ipc:
|
|
|
- if (new_ipc)
|
|
|
- put_ipc_ns(new_ipc);
|
|
|
-
|
|
|
-bad_unshare_cleanup_uts:
|
|
|
- if (new_uts)
|
|
|
- put_uts_ns(new_uts);
|
|
|
-
|
|
|
bad_unshare_cleanup_semundo:
|
|
|
bad_unshare_cleanup_fd:
|
|
|
if (new_fd)
|
|
@@ -1738,10 +1667,6 @@ bad_unshare_cleanup_sigh:
|
|
|
if (atomic_dec_and_test(&new_sigh->count))
|
|
|
kmem_cache_free(sighand_cachep, new_sigh);
|
|
|
|
|
|
-bad_unshare_cleanup_ns:
|
|
|
- if (new_ns)
|
|
|
- put_mnt_ns(new_ns);
|
|
|
-
|
|
|
bad_unshare_cleanup_fs:
|
|
|
if (new_fs)
|
|
|
put_fs_struct(new_fs);
|