aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@openvz.org>2012-06-07 17:21:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-07 17:43:55 -0400
commit300f786b2683f8bb1ec0afb6e1851183a479c86d (patch)
tree156c63abe6caaf885e439af30b7d883a33ba501d /kernel
parent1ad75b9e16280ca4e2501a629a225319cf2eef2e (diff)
c/r: prctl: add ability to get clear_tid_address
Zero is written at clear_tid_address when the process exits. This functionality is used by pthread_join(). We already have sys_set_tid_address() to change this address for the current task but there is no way to obtain it from user space. Without the ability to find this address and dump it we can't restore pthread'ed apps which call pthread_join() once they have been restored. This patch introduces the PR_GET_TID_ADDRESS prctl option which allows the current process to obtain own clear_tid_address. This feature is available iif CONFIG_CHECKPOINT_RESTORE is set. [akpm@linux-foundation.org: fix prctl numbering] Signed-off-by: Andrew Vagin <avagin@openvz.org> Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Pedro Alves <palves@redhat.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Tejun Heo <tj@kernel.org> Acked-by: Kees Cook <keescook@chromium.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sys.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index 19a2c7139960..0ec1942ba7ea 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1988,12 +1988,22 @@ out:
1988 up_read(&mm->mmap_sem); 1988 up_read(&mm->mmap_sem);
1989 return error; 1989 return error;
1990} 1990}
1991
1992static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
1993{
1994 return put_user(me->clear_child_tid, tid_addr);
1995}
1996
1991#else /* CONFIG_CHECKPOINT_RESTORE */ 1997#else /* CONFIG_CHECKPOINT_RESTORE */
1992static int prctl_set_mm(int opt, unsigned long addr, 1998static int prctl_set_mm(int opt, unsigned long addr,
1993 unsigned long arg4, unsigned long arg5) 1999 unsigned long arg4, unsigned long arg5)
1994{ 2000{
1995 return -EINVAL; 2001 return -EINVAL;
1996} 2002}
2003static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
2004{
2005 return -EINVAL;
2006}
1997#endif 2007#endif
1998 2008
1999SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, 2009SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
@@ -2131,6 +2141,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
2131 else 2141 else
2132 return -EINVAL; 2142 return -EINVAL;
2133 break; 2143 break;
2144 case PR_GET_TID_ADDRESS:
2145 error = prctl_get_tid_address(me, (int __user **)arg2);
2146 break;
2134 default: 2147 default:
2135 return -EINVAL; 2148 return -EINVAL;
2136 } 2149 }