diff options
| -rw-r--r-- | kernel/fork.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 1bfefc6f96a4..d544ae97f999 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1866,13 +1866,21 @@ static int check_unshare_flags(unsigned long unshare_flags) | |||
| 1866 | CLONE_NEWUSER|CLONE_NEWPID)) | 1866 | CLONE_NEWUSER|CLONE_NEWPID)) |
| 1867 | return -EINVAL; | 1867 | return -EINVAL; |
| 1868 | /* | 1868 | /* |
| 1869 | * Not implemented, but pretend it works if there is nothing to | 1869 | * Not implemented, but pretend it works if there is nothing |
| 1870 | * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND | 1870 | * to unshare. Note that unsharing the address space or the |
| 1871 | * needs to unshare vm. | 1871 | * signal handlers also need to unshare the signal queues (aka |
| 1872 | * CLONE_THREAD). | ||
| 1872 | */ | 1873 | */ |
| 1873 | if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) { | 1874 | if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) { |
| 1874 | /* FIXME: get_task_mm() increments ->mm_users */ | 1875 | if (!thread_group_empty(current)) |
| 1875 | if (atomic_read(¤t->mm->mm_users) > 1) | 1876 | return -EINVAL; |
| 1877 | } | ||
| 1878 | if (unshare_flags & (CLONE_SIGHAND | CLONE_VM)) { | ||
| 1879 | if (atomic_read(¤t->sighand->count) > 1) | ||
| 1880 | return -EINVAL; | ||
| 1881 | } | ||
| 1882 | if (unshare_flags & CLONE_VM) { | ||
| 1883 | if (!current_is_single_threaded()) | ||
| 1876 | return -EINVAL; | 1884 | return -EINVAL; |
| 1877 | } | 1885 | } |
| 1878 | 1886 | ||
| @@ -1941,16 +1949,16 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
| 1941 | if (unshare_flags & CLONE_NEWUSER) | 1949 | if (unshare_flags & CLONE_NEWUSER) |
| 1942 | unshare_flags |= CLONE_THREAD | CLONE_FS; | 1950 | unshare_flags |= CLONE_THREAD | CLONE_FS; |
| 1943 | /* | 1951 | /* |
| 1944 | * If unsharing a thread from a thread group, must also unshare vm. | ||
| 1945 | */ | ||
| 1946 | if (unshare_flags & CLONE_THREAD) | ||
| 1947 | unshare_flags |= CLONE_VM; | ||
| 1948 | /* | ||
| 1949 | * If unsharing vm, must also unshare signal handlers. | 1952 | * If unsharing vm, must also unshare signal handlers. |
| 1950 | */ | 1953 | */ |
| 1951 | if (unshare_flags & CLONE_VM) | 1954 | if (unshare_flags & CLONE_VM) |
| 1952 | unshare_flags |= CLONE_SIGHAND; | 1955 | unshare_flags |= CLONE_SIGHAND; |
| 1953 | /* | 1956 | /* |
| 1957 | * If unsharing a signal handlers, must also unshare the signal queues. | ||
| 1958 | */ | ||
| 1959 | if (unshare_flags & CLONE_SIGHAND) | ||
| 1960 | unshare_flags |= CLONE_THREAD; | ||
| 1961 | /* | ||
| 1954 | * If unsharing namespace, must also unshare filesystem information. | 1962 | * If unsharing namespace, must also unshare filesystem information. |
| 1955 | */ | 1963 | */ |
| 1956 | if (unshare_flags & CLONE_NEWNS) | 1964 | if (unshare_flags & CLONE_NEWNS) |
