aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c155
1 files changed, 43 insertions, 112 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 25e429152ddc..e7548dee636b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -40,6 +40,7 @@
40#include <linux/tracehook.h> 40#include <linux/tracehook.h>
41#include <linux/futex.h> 41#include <linux/futex.h>
42#include <linux/compat.h> 42#include <linux/compat.h>
43#include <linux/kthread.h>
43#include <linux/task_io_accounting_ops.h> 44#include <linux/task_io_accounting_ops.h>
44#include <linux/rcupdate.h> 45#include <linux/rcupdate.h>
45#include <linux/ptrace.h> 46#include <linux/ptrace.h>
@@ -109,20 +110,25 @@ int nr_processes(void)
109} 110}
110 111
111#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR 112#ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
112# define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) 113# define alloc_task_struct_node(node) \
113# define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk)) 114 kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node)
115# define free_task_struct(tsk) \
116 kmem_cache_free(task_struct_cachep, (tsk))
114static struct kmem_cache *task_struct_cachep; 117static struct kmem_cache *task_struct_cachep;
115#endif 118#endif
116 119
117#ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR 120#ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR
118static inline struct thread_info *alloc_thread_info(struct task_struct *tsk) 121static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
122 int node)
119{ 123{
120#ifdef CONFIG_DEBUG_STACK_USAGE 124#ifdef CONFIG_DEBUG_STACK_USAGE
121 gfp_t mask = GFP_KERNEL | __GFP_ZERO; 125 gfp_t mask = GFP_KERNEL | __GFP_ZERO;
122#else 126#else
123 gfp_t mask = GFP_KERNEL; 127 gfp_t mask = GFP_KERNEL;
124#endif 128#endif
125 return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER); 129 struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
130
131 return page ? page_address(page) : NULL;
126} 132}
127 133
128static inline void free_thread_info(struct thread_info *ti) 134static inline void free_thread_info(struct thread_info *ti)
@@ -193,6 +199,7 @@ void __put_task_struct(struct task_struct *tsk)
193 if (!profile_handoff_task(tsk)) 199 if (!profile_handoff_task(tsk))
194 free_task(tsk); 200 free_task(tsk);
195} 201}
202EXPORT_SYMBOL_GPL(__put_task_struct);
196 203
197/* 204/*
198 * macro override instead of weak attribute alias, to workaround 205 * macro override instead of weak attribute alias, to workaround
@@ -248,16 +255,16 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
248 struct task_struct *tsk; 255 struct task_struct *tsk;
249 struct thread_info *ti; 256 struct thread_info *ti;
250 unsigned long *stackend; 257 unsigned long *stackend;
251 258 int node = tsk_fork_get_node(orig);
252 int err; 259 int err;
253 260
254 prepare_to_copy(orig); 261 prepare_to_copy(orig);
255 262
256 tsk = alloc_task_struct(); 263 tsk = alloc_task_struct_node(node);
257 if (!tsk) 264 if (!tsk)
258 return NULL; 265 return NULL;
259 266
260 ti = alloc_thread_info(tsk); 267 ti = alloc_thread_info_node(tsk, node);
261 if (!ti) { 268 if (!ti) {
262 free_task_struct(tsk); 269 free_task_struct(tsk);
263 return NULL; 270 return NULL;
@@ -1180,12 +1187,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1180 pid = alloc_pid(p->nsproxy->pid_ns); 1187 pid = alloc_pid(p->nsproxy->pid_ns);
1181 if (!pid) 1188 if (!pid)
1182 goto bad_fork_cleanup_io; 1189 goto bad_fork_cleanup_io;
1183
1184 if (clone_flags & CLONE_NEWPID) {
1185 retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);
1186 if (retval < 0)
1187 goto bad_fork_free_pid;
1188 }
1189 } 1190 }
1190 1191
1191 p->pid = pid_nr(pid); 1192 p->pid = pid_nr(pid);
@@ -1204,6 +1205,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1204 * Clear TID on mm_release()? 1205 * Clear TID on mm_release()?
1205 */ 1206 */
1206 p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; 1207 p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
1208#ifdef CONFIG_BLOCK
1209 p->plug = NULL;
1210#endif
1207#ifdef CONFIG_FUTEX 1211#ifdef CONFIG_FUTEX
1208 p->robust_list = NULL; 1212 p->robust_list = NULL;
1209#ifdef CONFIG_COMPAT 1213#ifdef CONFIG_COMPAT
@@ -1289,7 +1293,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1289 tracehook_finish_clone(p, clone_flags, trace); 1293 tracehook_finish_clone(p, clone_flags, trace);
1290 1294
1291 if (thread_group_leader(p)) { 1295 if (thread_group_leader(p)) {
1292 if (clone_flags & CLONE_NEWPID) 1296 if (is_child_reaper(pid))
1293 p->nsproxy->pid_ns->child_reaper = p; 1297 p->nsproxy->pid_ns->child_reaper = p;
1294 1298
1295 p->signal->leader_pid = pid; 1299 p->signal->leader_pid = pid;
@@ -1512,38 +1516,24 @@ void __init proc_caches_init(void)
1512} 1516}
1513 1517
1514/* 1518/*
1515 * Check constraints on flags passed to the unshare system call and 1519 * Check constraints on flags passed to the unshare system call.
1516 * force unsharing of additional process context as appropriate.
1517 */ 1520 */
1518static void check_unshare_flags(unsigned long *flags_ptr) 1521static int check_unshare_flags(unsigned long unshare_flags)
1519{ 1522{
1523 if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
1524 CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
1525 CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
1526 return -EINVAL;
1520 /* 1527 /*
1521 * If unsharing a thread from a thread group, must also 1528 * Not implemented, but pretend it works if there is nothing to
1522 * unshare vm. 1529 * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
1523 */ 1530 * needs to unshare vm.
1524 if (*flags_ptr & CLONE_THREAD)
1525 *flags_ptr |= CLONE_VM;
1526
1527 /*
1528 * If unsharing vm, must also unshare signal handlers.
1529 */
1530 if (*flags_ptr & CLONE_VM)
1531 *flags_ptr |= CLONE_SIGHAND;
1532
1533 /*
1534 * If unsharing namespace, must also unshare filesystem information.
1535 */ 1531 */
1536 if (*flags_ptr & CLONE_NEWNS) 1532 if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
1537 *flags_ptr |= CLONE_FS; 1533 /* FIXME: get_task_mm() increments ->mm_users */
1538} 1534 if (atomic_read(&current->mm->mm_users) > 1)
1539 1535 return -EINVAL;
1540/* 1536 }
1541 * Unsharing of tasks created with CLONE_THREAD is not supported yet
1542 */
1543static int unshare_thread(unsigned long unshare_flags)
1544{
1545 if (unshare_flags & CLONE_THREAD)
1546 return -EINVAL;
1547 1537
1548 return 0; 1538 return 0;
1549} 1539}
@@ -1570,34 +1560,6 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
1570} 1560}
1571 1561
1572/* 1562/*
1573 * Unsharing of sighand is not supported yet
1574 */
1575static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
1576{
1577 struct sighand_struct *sigh = current->sighand;
1578
1579 if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1)
1580 return -EINVAL;
1581 else
1582 return 0;
1583}
1584
1585/*
1586 * Unshare vm if it is being shared
1587 */
1588static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
1589{
1590 struct mm_struct *mm = current->mm;
1591
1592 if ((unshare_flags & CLONE_VM) &&
1593 (mm && atomic_read(&mm->mm_users) > 1)) {
1594 return -EINVAL;
1595 }
1596
1597 return 0;
1598}
1599
1600/*
1601 * Unshare file descriptor table if it is being shared 1563 * Unshare file descriptor table if it is being shared
1602 */ 1564 */
1603static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp) 1565static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
@@ -1625,45 +1587,37 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
1625 */ 1587 */
1626SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags) 1588SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
1627{ 1589{
1628 int err = 0;
1629 struct fs_struct *fs, *new_fs = NULL; 1590 struct fs_struct *fs, *new_fs = NULL;
1630 struct sighand_struct *new_sigh = NULL;
1631 struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
1632 struct files_struct *fd, *new_fd = NULL; 1591 struct files_struct *fd, *new_fd = NULL;
1633 struct nsproxy *new_nsproxy = NULL; 1592 struct nsproxy *new_nsproxy = NULL;
1634 int do_sysvsem = 0; 1593 int do_sysvsem = 0;
1594 int err;
1635 1595
1636 check_unshare_flags(&unshare_flags); 1596 err = check_unshare_flags(unshare_flags);
1637 1597 if (err)
1638 /* Return -EINVAL for all unsupported flags */
1639 err = -EINVAL;
1640 if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
1641 CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
1642 CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
1643 goto bad_unshare_out; 1598 goto bad_unshare_out;
1644 1599
1645 /* 1600 /*
1601 * If unsharing namespace, must also unshare filesystem information.
1602 */
1603 if (unshare_flags & CLONE_NEWNS)
1604 unshare_flags |= CLONE_FS;
1605 /*
1646 * CLONE_NEWIPC must also detach from the undolist: after switching 1606 * CLONE_NEWIPC must also detach from the undolist: after switching
1647 * to a new ipc namespace, the semaphore arrays from the old 1607 * to a new ipc namespace, the semaphore arrays from the old
1648 * namespace are unreachable. 1608 * namespace are unreachable.
1649 */ 1609 */
1650 if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM)) 1610 if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
1651 do_sysvsem = 1; 1611 do_sysvsem = 1;
1652 if ((err = unshare_thread(unshare_flags)))
1653 goto bad_unshare_out;
1654 if ((err = unshare_fs(unshare_flags, &new_fs))) 1612 if ((err = unshare_fs(unshare_flags, &new_fs)))
1655 goto bad_unshare_cleanup_thread; 1613 goto bad_unshare_out;
1656 if ((err = unshare_sighand(unshare_flags, &new_sigh)))
1657 goto bad_unshare_cleanup_fs;
1658 if ((err = unshare_vm(unshare_flags, &new_mm)))
1659 goto bad_unshare_cleanup_sigh;
1660 if ((err = unshare_fd(unshare_flags, &new_fd))) 1614 if ((err = unshare_fd(unshare_flags, &new_fd)))
1661 goto bad_unshare_cleanup_vm; 1615 goto bad_unshare_cleanup_fs;
1662 if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy, 1616 if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
1663 new_fs))) 1617 new_fs)))
1664 goto bad_unshare_cleanup_fd; 1618 goto bad_unshare_cleanup_fd;
1665 1619
1666 if (new_fs || new_mm || new_fd || do_sysvsem || new_nsproxy) { 1620 if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
1667 if (do_sysvsem) { 1621 if (do_sysvsem) {
1668 /* 1622 /*
1669 * CLONE_SYSVSEM is equivalent to sys_exit(). 1623 * CLONE_SYSVSEM is equivalent to sys_exit().
@@ -1689,19 +1643,6 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
1689 spin_unlock(&fs->lock); 1643 spin_unlock(&fs->lock);
1690 } 1644 }
1691 1645
1692 if (new_mm) {
1693 mm = current->mm;
1694 active_mm = current->active_mm;
1695 current->mm = new_mm;
1696 current->active_mm = new_mm;
1697 if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
1698 atomic_dec(&mm->oom_disable_count);
1699 atomic_inc(&new_mm->oom_disable_count);
1700 }
1701 activate_mm(active_mm, new_mm);
1702 new_mm = mm;
1703 }
1704
1705 if (new_fd) { 1646 if (new_fd) {
1706 fd = current->files; 1647 fd = current->files;
1707 current->files = new_fd; 1648 current->files = new_fd;
@@ -1718,20 +1659,10 @@ bad_unshare_cleanup_fd:
1718 if (new_fd) 1659 if (new_fd)
1719 put_files_struct(new_fd); 1660 put_files_struct(new_fd);
1720 1661
1721bad_unshare_cleanup_vm:
1722 if (new_mm)
1723 mmput(new_mm);
1724
1725bad_unshare_cleanup_sigh:
1726 if (new_sigh)
1727 if (atomic_dec_and_test(&new_sigh->count))
1728 kmem_cache_free(sighand_cachep, new_sigh);
1729
1730bad_unshare_cleanup_fs: 1662bad_unshare_cleanup_fs:
1731 if (new_fs) 1663 if (new_fs)
1732 free_fs_struct(new_fs); 1664 free_fs_struct(new_fs);
1733 1665
1734bad_unshare_cleanup_thread:
1735bad_unshare_out: 1666bad_unshare_out:
1736 return err; 1667 return err;
1737} 1668}