1 /*
2 * Check decoding of prctl PR_SET_VMA operation.
3 *
4 * Copyright (c) 2019-2022 Dmitry V. Levin <ldv@strace.io>
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11 #include "scno.h"
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <linux/prctl.h>
15
16 static const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
17 static const char *errstr;
18
19 static long
20 pr_set_vma(const kernel_ulong_t op, const void *const addr,
21 const kernel_ulong_t size, const void *const arg)
22 {
23 const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
24 const kernel_ulong_t arg1 = fill | PR_SET_VMA;
25 const kernel_ulong_t arg2 = op;
26 const kernel_ulong_t arg3 = (uintptr_t) addr;
27 const kernel_ulong_t arg4 = size;
28 const kernel_ulong_t arg5 = (uintptr_t) arg;
29 const long rc = syscall(__NR_prctl, arg1, arg2, arg3, arg4, arg5, bad);
30 errstr = sprintrc(rc);
31 return rc;
32 }
33
34 int
35 main(void)
36 {
37 prctl_marker();
38
39 char *const name1 = tail_alloc(DEFAULT_STRLEN + 2);
40 char *const name = name1 + 1;
41 const void *const efault = name + DEFAULT_STRLEN + 1;
42 const char *const empty = efault - 1;
43 fill_memory_ex(name1, DEFAULT_STRLEN + 1, '0', 10);
44 name1[DEFAULT_STRLEN + 1] = '\0';
45
46 pr_set_vma(0, 0, 1, name);
47 printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, NULL, 1, \"%s\")"
48 " = %s\n",
49 name, errstr);
50
51 pr_set_vma(0, empty, 2, name1);
52 printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 2, \"%.*s\"...)"
53 " = %s\n",
54 empty, DEFAULT_STRLEN, name1, errstr);
55
56 pr_set_vma(0, empty, 3, efault);
57 printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 3, %p)"
58 " = %s\n",
59 empty, efault, errstr);
60
61 pr_set_vma(0, empty, 4, 0);
62 printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 4, NULL)"
63 " = %s\n",
64 empty, errstr);
65
66 pr_set_vma(0, efault, 5, empty);
67 printf("prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, %p, 5, \"\")"
68 " = %s\n",
69 efault, errstr);
70
71 const kernel_ulong_t bad_op = fill | 0xface1fed;
72 const kernel_ulong_t bad_size = fill | 0xface2fed;
73
74 pr_set_vma(bad_op, efault, bad_size, empty);
75 printf("prctl(PR_SET_VMA, %#llx /* PR_SET_VMA_??? */, %p, %#llx, %p)"
76 " = %s\n",
77 (unsigned long long) bad_op, efault,
78 (unsigned long long) bad_size, empty, errstr);
79
80 puts("+++ exited with 0 +++");
81 return 0;
82 }