1 /*
2 * Check decoding of prctl PR_GET_TID_ADDRESS operation.
3 *
4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2016-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <unistd.h>
17 #include <linux/prctl.h>
18
19 static const char *
20 sprintaddr(kernel_ulong_t addr)
21 {
22 static char buf[sizeof("0x") + sizeof(addr) * 2];
23
24 if (addr) {
25 snprintf(buf, sizeof(buf), "%#llx", (unsigned long long) addr);
26
27 return buf;
28 }
29
30 return "NULL";
31 }
32
33 int
34 main(void)
35 {
36 static const kernel_ulong_t bogus_addr =
37 (kernel_ulong_t) 0xfffffffffffffffdULL;
38
39 /* Note that kernel puts kernel-sized pointer even on x32 */
40 TAIL_ALLOC_OBJECT_CONST_PTR(kernel_ulong_t, ptr);
41 long rc;
42 long set_ok;
43
44 prctl_marker();
45
46 *ptr = (kernel_ulong_t) 0xbadc0dedda7a1057ULL;
47
48 rc = syscall(__NR_prctl, PR_GET_TID_ADDRESS, NULL);
49 printf("prctl(PR_GET_TID_ADDRESS, NULL) = %s\n", sprintrc(rc));
50
51 rc = syscall(__NR_prctl, PR_GET_TID_ADDRESS, bogus_addr);
52 printf("prctl(PR_GET_TID_ADDRESS, %#llx) = %s\n",
53 (unsigned long long) bogus_addr, sprintrc(rc));
54
55 rc = syscall(__NR_prctl, PR_GET_TID_ADDRESS, ptr);
56 if (rc) {
57 printf("prctl(PR_GET_TID_ADDRESS, %p) = %s\n",
58 ptr, sprintrc(rc));
59 } else {
60 printf("prctl(PR_GET_TID_ADDRESS, [%s]) = %s\n",
61 sprintaddr(*ptr), sprintrc(rc));
62 }
63
64 set_ok = syscall(__NR_set_tid_address, bogus_addr);
65
66 rc = syscall(__NR_prctl, PR_GET_TID_ADDRESS, ptr);
67 if (rc) {
68 printf("prctl(PR_GET_TID_ADDRESS, %p) = %s\n",
69 ptr, sprintrc(rc));
70 } else {
71 printf("prctl(PR_GET_TID_ADDRESS, [%s]) = %s\n",
72 sprintaddr(set_ok ? bogus_addr : *ptr), sprintrc(rc));
73 }
74
75 puts("+++ exited with 0 +++");
76 return 0;
77 }