diff options
author | Cyrill Gorcunov <gorcunov@openvz.org> | 2012-06-07 17:21:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-07 17:43:55 -0400 |
commit | 300f786b2683f8bb1ec0afb6e1851183a479c86d (patch) | |
tree | 156c63abe6caaf885e439af30b7d883a33ba501d | |
parent | 1ad75b9e16280ca4e2501a629a225319cf2eef2e (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.h | 10 | ||||
-rw-r--r-- | kernel/sys.c | 13 |
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 | |||
1992 | static 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 */ |
1992 | static int prctl_set_mm(int opt, unsigned long addr, | 1998 | static 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 | } |
2003 | static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) | ||
2004 | { | ||
2005 | return -EINVAL; | ||
2006 | } | ||
1997 | #endif | 2007 | #endif |
1998 | 2008 | ||
1999 | SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | 2009 | SYSCALL_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 | } |