aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/prctl.h10
-rw-r--r--kernel/sys.c13
2 files changed, 19 insertions, 4 deletions
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 711e0a30aacc..3988012255dc 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -127,8 +127,8 @@
127#define PR_SET_PTRACER 0x59616d61 127#define PR_SET_PTRACER 0x59616d61
128# define PR_SET_PTRACER_ANY ((unsigned long)-1) 128# define PR_SET_PTRACER_ANY ((unsigned long)-1)
129 129
130#define PR_SET_CHILD_SUBREAPER 36 130#define PR_SET_CHILD_SUBREAPER 36
131#define PR_GET_CHILD_SUBREAPER 37 131#define PR_GET_CHILD_SUBREAPER 37
132 132
133/* 133/*
134 * If no_new_privs is set, then operations that grant new privileges (i.e. 134 * If no_new_privs is set, then operations that grant new privileges (i.e.
@@ -142,7 +142,9 @@
142 * asking selinux for a specific new context (e.g. with runcon) will result 142 * asking selinux for a specific new context (e.g. with runcon) will result
143 * in execve returning -EPERM. 143 * in execve returning -EPERM.
144 */ 144 */
145#define PR_SET_NO_NEW_PRIVS 38 145#define PR_SET_NO_NEW_PRIVS 38
146#define PR_GET_NO_NEW_PRIVS 39 146#define PR_GET_NO_NEW_PRIVS 39
147
148#define PR_GET_TID_ADDRESS 40
147 149
148#endif /* _LINUX_PRCTL_H */ 150#endif /* _LINUX_PRCTL_H */
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 }