Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 300f786b authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Linus Torvalds
Browse files

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: default avatarAndrew Vagin <avagin@openvz.org>
Signed-off-by: default avatarCyrill 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: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1ad75b9e
Loading
Loading
Loading
Loading
+6 −4
Original line number Original line Diff line number Diff line
@@ -145,4 +145,6 @@
#define PR_SET_NO_NEW_PRIVS	38
#define PR_SET_NO_NEW_PRIVS	38
#define PR_GET_NO_NEW_PRIVS	39
#define PR_GET_NO_NEW_PRIVS	39


#define PR_GET_TID_ADDRESS	40

#endif /* _LINUX_PRCTL_H */
#endif /* _LINUX_PRCTL_H */
+13 −0
Original line number Original line Diff line number Diff line
@@ -1988,12 +1988,22 @@ static int prctl_set_mm(int opt, unsigned long addr,
	up_read(&mm->mmap_sem);
	up_read(&mm->mmap_sem);
	return error;
	return error;
}
}

static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
{
	return put_user(me->clear_child_tid, tid_addr);
}

#else /* CONFIG_CHECKPOINT_RESTORE */
#else /* CONFIG_CHECKPOINT_RESTORE */
static int prctl_set_mm(int opt, unsigned long addr,
static int prctl_set_mm(int opt, unsigned long addr,
			unsigned long arg4, unsigned long arg5)
			unsigned long arg4, unsigned long arg5)
{
{
	return -EINVAL;
	return -EINVAL;
}
}
static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
{
	return -EINVAL;
}
#endif
#endif


SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
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,
				else
				else
					return -EINVAL;
					return -EINVAL;
				break;
				break;
		case PR_GET_TID_ADDRESS:
			error = prctl_get_tid_address(me, (int __user **)arg2);
			break;
			default:
			default:
				return -EINVAL;
				return -EINVAL;
			}
			}