diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-07-26 08:15:35 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-11-20 07:18:14 -0500 |
commit | b2e0d98705e60e45bbb3c0032c48824ad7ae0704 (patch) | |
tree | e187c82e1c3babd34095f2b946614131719bbb03 /kernel/fork.c | |
parent | cde1975bc242f3e1072bde623ef378e547b73f91 (diff) |
userns: Implement unshare of the user namespace
- Add CLONE_THREAD to the unshare flags if CLONE_NEWUSER is selected
As changing user namespaces is only valid if all there is only
a single thread.
- Restore the code to add CLONE_VM if CLONE_THREAD is selected and
the code to addCLONE_SIGHAND if CLONE_VM is selected.
Making the constraints in the code clear.
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 8c29abb19014..38e53b87402c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1687,7 +1687,7 @@ static int check_unshare_flags(unsigned long unshare_flags) | |||
1687 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| | 1687 | if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| |
1688 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| | 1688 | CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| |
1689 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| | 1689 | CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| |
1690 | CLONE_NEWPID)) | 1690 | CLONE_NEWUSER|CLONE_NEWPID)) |
1691 | return -EINVAL; | 1691 | return -EINVAL; |
1692 | /* | 1692 | /* |
1693 | * Not implemented, but pretend it works if there is nothing to | 1693 | * Not implemented, but pretend it works if there is nothing to |
@@ -1754,11 +1754,17 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1754 | { | 1754 | { |
1755 | struct fs_struct *fs, *new_fs = NULL; | 1755 | struct fs_struct *fs, *new_fs = NULL; |
1756 | struct files_struct *fd, *new_fd = NULL; | 1756 | struct files_struct *fd, *new_fd = NULL; |
1757 | struct cred *new_cred = NULL; | ||
1757 | struct nsproxy *new_nsproxy = NULL; | 1758 | struct nsproxy *new_nsproxy = NULL; |
1758 | int do_sysvsem = 0; | 1759 | int do_sysvsem = 0; |
1759 | int err; | 1760 | int err; |
1760 | 1761 | ||
1761 | /* | 1762 | /* |
1763 | * If unsharing a user namespace must also unshare the thread. | ||
1764 | */ | ||
1765 | if (unshare_flags & CLONE_NEWUSER) | ||
1766 | unshare_flags |= CLONE_THREAD; | ||
1767 | /* | ||
1762 | * If unsharing a pid namespace must also unshare the thread. | 1768 | * If unsharing a pid namespace must also unshare the thread. |
1763 | */ | 1769 | */ |
1764 | if (unshare_flags & CLONE_NEWPID) | 1770 | if (unshare_flags & CLONE_NEWPID) |
@@ -1795,11 +1801,15 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1795 | err = unshare_fd(unshare_flags, &new_fd); | 1801 | err = unshare_fd(unshare_flags, &new_fd); |
1796 | if (err) | 1802 | if (err) |
1797 | goto bad_unshare_cleanup_fs; | 1803 | goto bad_unshare_cleanup_fs; |
1798 | err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, new_fs); | 1804 | err = unshare_userns(unshare_flags, &new_cred); |
1799 | if (err) | 1805 | if (err) |
1800 | goto bad_unshare_cleanup_fd; | 1806 | goto bad_unshare_cleanup_fd; |
1807 | err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, | ||
1808 | new_cred, new_fs); | ||
1809 | if (err) | ||
1810 | goto bad_unshare_cleanup_cred; | ||
1801 | 1811 | ||
1802 | if (new_fs || new_fd || do_sysvsem || new_nsproxy) { | 1812 | if (new_fs || new_fd || do_sysvsem || new_cred || new_nsproxy) { |
1803 | if (do_sysvsem) { | 1813 | if (do_sysvsem) { |
1804 | /* | 1814 | /* |
1805 | * CLONE_SYSVSEM is equivalent to sys_exit(). | 1815 | * CLONE_SYSVSEM is equivalent to sys_exit(). |
@@ -1832,11 +1842,20 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1832 | } | 1842 | } |
1833 | 1843 | ||
1834 | task_unlock(current); | 1844 | task_unlock(current); |
1845 | |||
1846 | if (new_cred) { | ||
1847 | /* Install the new user namespace */ | ||
1848 | commit_creds(new_cred); | ||
1849 | new_cred = NULL; | ||
1850 | } | ||
1835 | } | 1851 | } |
1836 | 1852 | ||
1837 | if (new_nsproxy) | 1853 | if (new_nsproxy) |
1838 | put_nsproxy(new_nsproxy); | 1854 | put_nsproxy(new_nsproxy); |
1839 | 1855 | ||
1856 | bad_unshare_cleanup_cred: | ||
1857 | if (new_cred) | ||
1858 | put_cred(new_cred); | ||
1840 | bad_unshare_cleanup_fd: | 1859 | bad_unshare_cleanup_fd: |
1841 | if (new_fd) | 1860 | if (new_fd) |
1842 | put_files_struct(new_fd); | 1861 | put_files_struct(new_fd); |