0001
0002 #include <linux/compiler.h>
0003 #include <sys/types.h>
0004 #include <sys/wait.h>
0005 #include <sys/user.h>
0006 #include <syscall.h>
0007 #include <unistd.h>
0008 #include <stdio.h>
0009 #include <stdlib.h>
0010 #include <string.h>
0011 #include <sys/ptrace.h>
0012 #include <asm/ptrace.h>
0013 #include <errno.h>
0014 #include "debug.h"
0015 #include "tests/tests.h"
0016 #include "arch-tests.h"
0017
0018 static noinline int bp_1(void)
0019 {
0020 pr_debug("in %s\n", __func__);
0021 return 0;
0022 }
0023
0024 static noinline int bp_2(void)
0025 {
0026 pr_debug("in %s\n", __func__);
0027 return 0;
0028 }
0029
0030 static int spawn_child(void)
0031 {
0032 int child = fork();
0033
0034 if (child == 0) {
0035
0036
0037
0038
0039
0040 int err = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
0041
0042 if (err) {
0043 pr_debug("failed to PTRACE_TRACEME\n");
0044 exit(1);
0045 }
0046
0047 raise(SIGCONT);
0048 bp_1();
0049 exit(0);
0050 }
0051
0052 return child;
0053 }
0054
0055
0056
0057
0058
0059 static int bp_modify1(void)
0060 {
0061 pid_t child;
0062 int status;
0063 unsigned long rip = 0, dr7 = 1;
0064
0065 child = spawn_child();
0066
0067 waitpid(child, &status, 0);
0068 if (WIFEXITED(status)) {
0069 pr_debug("tracee exited prematurely 1\n");
0070 return TEST_FAIL;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 if (ptrace(PTRACE_POKEUSER, child,
0082 offsetof(struct user, u_debugreg[0]), bp_2)) {
0083 pr_debug("failed to set breakpoint, 1st time: %s\n",
0084 strerror(errno));
0085 goto out;
0086 }
0087
0088 if (ptrace(PTRACE_POKEUSER, child,
0089 offsetof(struct user, u_debugreg[0]), bp_1)) {
0090 pr_debug("failed to set breakpoint, 2nd time: %s\n",
0091 strerror(errno));
0092 goto out;
0093 }
0094
0095 if (ptrace(PTRACE_POKEUSER, child,
0096 offsetof(struct user, u_debugreg[7]), dr7)) {
0097 pr_debug("failed to set dr7: %s\n", strerror(errno));
0098 goto out;
0099 }
0100
0101 if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
0102 pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
0103 goto out;
0104 }
0105
0106 waitpid(child, &status, 0);
0107 if (WIFEXITED(status)) {
0108 pr_debug("tracee exited prematurely 2\n");
0109 return TEST_FAIL;
0110 }
0111
0112 rip = ptrace(PTRACE_PEEKUSER, child,
0113 offsetof(struct user_regs_struct, rip), NULL);
0114 if (rip == (unsigned long) -1) {
0115 pr_debug("failed to PTRACE_PEEKUSER: %s\n",
0116 strerror(errno));
0117 goto out;
0118 }
0119
0120 pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
0121
0122 out:
0123 if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
0124 pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
0125 return TEST_FAIL;
0126 }
0127
0128 return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
0129 }
0130
0131
0132
0133
0134
0135
0136 static int bp_modify2(void)
0137 {
0138 pid_t child;
0139 int status;
0140 unsigned long rip = 0, dr7 = 1;
0141
0142 child = spawn_child();
0143
0144 waitpid(child, &status, 0);
0145 if (WIFEXITED(status)) {
0146 pr_debug("tracee exited prematurely 1\n");
0147 return TEST_FAIL;
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 if (ptrace(PTRACE_POKEUSER, child,
0159 offsetof(struct user, u_debugreg[0]), bp_1)) {
0160 pr_debug("failed to set breakpoint: %s\n",
0161 strerror(errno));
0162 goto out;
0163 }
0164
0165 if (ptrace(PTRACE_POKEUSER, child,
0166 offsetof(struct user, u_debugreg[7]), dr7)) {
0167 pr_debug("failed to set dr7: %s\n", strerror(errno));
0168 goto out;
0169 }
0170
0171 if (!ptrace(PTRACE_POKEUSER, child,
0172 offsetof(struct user, u_debugreg[0]), (unsigned long) (-1))) {
0173 pr_debug("failed, breakpoint set to bogus address\n");
0174 goto out;
0175 }
0176
0177 if (ptrace(PTRACE_CONT, child, NULL, NULL)) {
0178 pr_debug("failed to PTRACE_CONT: %s\n", strerror(errno));
0179 goto out;
0180 }
0181
0182 waitpid(child, &status, 0);
0183 if (WIFEXITED(status)) {
0184 pr_debug("tracee exited prematurely 2\n");
0185 return TEST_FAIL;
0186 }
0187
0188 rip = ptrace(PTRACE_PEEKUSER, child,
0189 offsetof(struct user_regs_struct, rip), NULL);
0190 if (rip == (unsigned long) -1) {
0191 pr_debug("failed to PTRACE_PEEKUSER: %s\n",
0192 strerror(errno));
0193 goto out;
0194 }
0195
0196 pr_debug("rip %lx, bp_1 %p\n", rip, bp_1);
0197
0198 out:
0199 if (ptrace(PTRACE_DETACH, child, NULL, NULL)) {
0200 pr_debug("failed to PTRACE_DETACH: %s", strerror(errno));
0201 return TEST_FAIL;
0202 }
0203
0204 return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
0205 }
0206
0207 int test__bp_modify(struct test_suite *test __maybe_unused,
0208 int subtest __maybe_unused)
0209 {
0210 TEST_ASSERT_VAL("modify test 1 failed\n", !bp_modify1());
0211 TEST_ASSERT_VAL("modify test 2 failed\n", !bp_modify2());
0212
0213 return 0;
0214 }