diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index a31b823b3c2d..1766d324d5e3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -413,7 +413,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
413 | tmp->vm_next = tmp->vm_prev = NULL; | 413 | tmp->vm_next = tmp->vm_prev = NULL; |
414 | file = tmp->vm_file; | 414 | file = tmp->vm_file; |
415 | if (file) { | 415 | if (file) { |
416 | struct inode *inode = file->f_path.dentry->d_inode; | 416 | struct inode *inode = file_inode(file); |
417 | struct address_space *mapping = file->f_mapping; | 417 | struct address_space *mapping = file->f_mapping; |
418 | 418 | ||
419 | get_file(file); | 419 | get_file(file); |
@@ -1141,6 +1141,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1141 | if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) | 1141 | if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) |
1142 | return ERR_PTR(-EINVAL); | 1142 | return ERR_PTR(-EINVAL); |
1143 | 1143 | ||
1144 | if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) | ||
1145 | return ERR_PTR(-EINVAL); | ||
1146 | |||
1144 | /* | 1147 | /* |
1145 | * Thread groups must share signals as well, and detached threads | 1148 | * Thread groups must share signals as well, and detached threads |
1146 | * can only be started up within the thread group. | 1149 | * can only be started up within the thread group. |
@@ -1166,6 +1169,14 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1166 | current->signal->flags & SIGNAL_UNKILLABLE) | 1169 | current->signal->flags & SIGNAL_UNKILLABLE) |
1167 | return ERR_PTR(-EINVAL); | 1170 | return ERR_PTR(-EINVAL); |
1168 | 1171 | ||
1172 | /* | ||
1173 | * If the new process will be in a different pid namespace | ||
1174 | * don't allow the creation of threads. | ||
1175 | */ | ||
1176 | if ((clone_flags & (CLONE_VM|CLONE_NEWPID)) && | ||
1177 | (task_active_pid_ns(current) != current->nsproxy->pid_ns)) | ||
1178 | return ERR_PTR(-EINVAL); | ||
1179 | |||
1169 | retval = security_task_create(clone_flags); | 1180 | retval = security_task_create(clone_flags); |
1170 | if (retval) | 1181 | if (retval) |
1171 | goto fork_out; | 1182 | goto fork_out; |
@@ -1225,6 +1236,12 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1225 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 1236 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
1226 | p->prev_cputime.utime = p->prev_cputime.stime = 0; | 1237 | p->prev_cputime.utime = p->prev_cputime.stime = 0; |
1227 | #endif | 1238 | #endif |
1239 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN | ||
1240 | seqlock_init(&p->vtime_seqlock); | ||
1241 | p->vtime_snap = 0; | ||
1242 | p->vtime_snap_whence = VTIME_SLEEPING; | ||
1243 | #endif | ||
1244 | |||
1228 | #if defined(SPLIT_RSS_COUNTING) | 1245 | #if defined(SPLIT_RSS_COUNTING) |
1229 | memset(&p->rss_stat, 0, sizeof(p->rss_stat)); | 1246 | memset(&p->rss_stat, 0, sizeof(p->rss_stat)); |
1230 | #endif | 1247 | #endif |
@@ -1660,8 +1677,10 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | |||
1660 | int, tls_val) | 1677 | int, tls_val) |
1661 | #endif | 1678 | #endif |
1662 | { | 1679 | { |
1663 | return do_fork(clone_flags, newsp, 0, | 1680 | long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr); |
1664 | parent_tidptr, child_tidptr); | 1681 | asmlinkage_protect(5, ret, clone_flags, newsp, |
1682 | parent_tidptr, child_tidptr, tls_val); | ||
1683 | return ret; | ||
1665 | } | 1684 | } |
1666 | #endif | 1685 | #endif |
1667 | 1686 | ||
@@ -1791,7 +1810,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1791 | * If unsharing a user namespace must also unshare the thread. | 1810 | * If unsharing a user namespace must also unshare the thread. |
1792 | */ | 1811 | */ |
1793 | if (unshare_flags & CLONE_NEWUSER) | 1812 | if (unshare_flags & CLONE_NEWUSER) |
1794 | unshare_flags |= CLONE_THREAD; | 1813 | unshare_flags |= CLONE_THREAD | CLONE_FS; |
1795 | /* | 1814 | /* |
1796 | * If unsharing a pid namespace must also unshare the thread. | 1815 | * If unsharing a pid namespace must also unshare the thread. |
1797 | */ | 1816 | */ |
@@ -1845,10 +1864,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1845 | exit_sem(current); | 1864 | exit_sem(current); |
1846 | } | 1865 | } |
1847 | 1866 | ||
1848 | if (new_nsproxy) { | 1867 | if (new_nsproxy) |
1849 | switch_task_namespaces(current, new_nsproxy); | 1868 | switch_task_namespaces(current, new_nsproxy); |
1850 | new_nsproxy = NULL; | ||
1851 | } | ||
1852 | 1869 | ||
1853 | task_lock(current); | 1870 | task_lock(current); |
1854 | 1871 | ||
@@ -1878,9 +1895,6 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) | |||
1878 | } | 1895 | } |
1879 | } | 1896 | } |
1880 | 1897 | ||
1881 | if (new_nsproxy) | ||
1882 | put_nsproxy(new_nsproxy); | ||
1883 | |||
1884 | bad_unshare_cleanup_cred: | 1898 | bad_unshare_cleanup_cred: |
1885 | if (new_cred) | 1899 | if (new_cred) |
1886 | put_cred(new_cred); | 1900 | put_cred(new_cred); |