0001
0002
0003
0004
0005
0006
0007
0008 #include "ptrace.h"
0009 #include "child.h"
0010
0011 #ifndef __NR_pkey_alloc
0012 #define __NR_pkey_alloc 384
0013 #endif
0014
0015 #ifndef __NR_pkey_free
0016 #define __NR_pkey_free 385
0017 #endif
0018
0019 #ifndef NT_PPC_PKEY
0020 #define NT_PPC_PKEY 0x110
0021 #endif
0022
0023 #ifndef PKEY_DISABLE_EXECUTE
0024 #define PKEY_DISABLE_EXECUTE 0x4
0025 #endif
0026
0027 #define AMR_BITS_PER_PKEY 2
0028 #define PKEY_REG_BITS (sizeof(u64) * 8)
0029 #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY))
0030
0031 static const char user_read[] = "[User Read (Running)]";
0032 static const char user_write[] = "[User Write (Running)]";
0033 static const char ptrace_read_running[] = "[Ptrace Read (Running)]";
0034 static const char ptrace_write_running[] = "[Ptrace Write (Running)]";
0035
0036
0037 struct shared_info {
0038 struct child_sync child_sync;
0039
0040
0041 unsigned long amr1;
0042
0043
0044 unsigned long amr2;
0045
0046
0047 unsigned long invalid_amr;
0048
0049
0050 unsigned long expected_iamr;
0051
0052
0053 unsigned long expected_uamor;
0054
0055
0056
0057
0058
0059
0060 unsigned long invalid_iamr;
0061 unsigned long invalid_uamor;
0062 };
0063
0064 static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights)
0065 {
0066 return syscall(__NR_pkey_alloc, flags, init_access_rights);
0067 }
0068
0069 static int child(struct shared_info *info)
0070 {
0071 unsigned long reg;
0072 bool disable_execute = true;
0073 int pkey1, pkey2, pkey3;
0074 int ret;
0075
0076
0077 ret = wait_parent(&info->child_sync);
0078 if (ret)
0079 return ret;
0080
0081
0082 pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE);
0083 if (pkey1 < 0) {
0084 pkey1 = sys_pkey_alloc(0, 0);
0085 CHILD_FAIL_IF(pkey1 < 0, &info->child_sync);
0086
0087 disable_execute = false;
0088 }
0089
0090 pkey2 = sys_pkey_alloc(0, 0);
0091 CHILD_FAIL_IF(pkey2 < 0, &info->child_sync);
0092
0093 pkey3 = sys_pkey_alloc(0, 0);
0094 CHILD_FAIL_IF(pkey3 < 0, &info->child_sync);
0095
0096 info->amr1 |= 3ul << pkeyshift(pkey1);
0097 info->amr2 |= 3ul << pkeyshift(pkey2);
0098
0099
0100
0101
0102 info->invalid_amr = info->amr2 | (~0x0UL & ~info->expected_uamor);
0103
0104
0105
0106
0107 if (disable_execute)
0108 info->expected_iamr |= 1ul << pkeyshift(pkey1);
0109 else
0110 info->expected_iamr &= ~(1ul << pkeyshift(pkey1));
0111
0112
0113
0114
0115 info->expected_iamr &= ~(1ul << pkeyshift(pkey2));
0116 info->expected_iamr &= ~(1ul << pkeyshift(pkey3));
0117
0118
0119
0120
0121
0122 info->invalid_iamr = info->expected_iamr | (1ul << pkeyshift(pkey1) | 1ul << pkeyshift(pkey2));
0123 info->invalid_uamor = info->expected_uamor & ~(0x3ul << pkeyshift(pkey1));
0124
0125 printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n",
0126 user_write, info->amr1, pkey1, pkey2, pkey3);
0127
0128 set_amr(info->amr1);
0129
0130
0131 ret = prod_parent(&info->child_sync);
0132 CHILD_FAIL_IF(ret, &info->child_sync);
0133
0134 ret = wait_parent(&info->child_sync);
0135 if (ret)
0136 return ret;
0137
0138 reg = mfspr(SPRN_AMR);
0139
0140 printf("%-30s AMR: %016lx\n", user_read, reg);
0141
0142 CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
0143
0144
0145
0146
0147 ret = prod_parent(&info->child_sync);
0148 CHILD_FAIL_IF(ret, &info->child_sync);
0149
0150 ret = wait_parent(&info->child_sync);
0151 if (ret)
0152 return ret;
0153
0154 reg = mfspr(SPRN_AMR);
0155
0156 printf("%-30s AMR: %016lx\n", user_read, reg);
0157
0158 CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
0159
0160
0161
0162
0163
0164 ret = prod_parent(&info->child_sync);
0165 CHILD_FAIL_IF(ret, &info->child_sync);
0166
0167 ret = wait_parent(&info->child_sync);
0168 if (ret)
0169 return ret;
0170
0171 reg = mfspr(SPRN_AMR);
0172
0173 printf("%-30s AMR: %016lx\n", user_read, reg);
0174
0175 CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
0176
0177
0178
0179 ret = prod_parent(&info->child_sync);
0180 CHILD_FAIL_IF(ret, &info->child_sync);
0181
0182 return TEST_PASS;
0183 }
0184
0185 static int parent(struct shared_info *info, pid_t pid)
0186 {
0187 unsigned long regs[3];
0188 int ret, status;
0189
0190
0191
0192
0193
0194 ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
0195 PARENT_SKIP_IF_UNSUPPORTED(ret, &info->child_sync);
0196 PARENT_FAIL_IF(ret, &info->child_sync);
0197
0198 info->amr1 = info->amr2 = regs[0];
0199 info->expected_iamr = regs[1];
0200 info->expected_uamor = regs[2];
0201
0202
0203 ret = prod_child(&info->child_sync);
0204 PARENT_FAIL_IF(ret, &info->child_sync);
0205
0206 ret = wait_child(&info->child_sync);
0207 if (ret)
0208 return ret;
0209
0210
0211 ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
0212 PARENT_FAIL_IF(ret, &info->child_sync);
0213
0214 printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
0215 ptrace_read_running, regs[0], regs[1], regs[2]);
0216
0217 PARENT_FAIL_IF(regs[0] != info->amr1, &info->child_sync);
0218 PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
0219 PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
0220
0221
0222 ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr2, 1);
0223 PARENT_FAIL_IF(ret, &info->child_sync);
0224
0225 printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr2);
0226
0227
0228 ret = prod_child(&info->child_sync);
0229 PARENT_FAIL_IF(ret, &info->child_sync);
0230
0231 ret = wait_child(&info->child_sync);
0232 if (ret)
0233 return ret;
0234
0235
0236 ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->invalid_amr, 1);
0237 PARENT_FAIL_IF(ret, &info->child_sync);
0238
0239 printf("%-30s AMR: %016lx\n", ptrace_write_running, info->invalid_amr);
0240
0241
0242 ret = prod_child(&info->child_sync);
0243 PARENT_FAIL_IF(ret, &info->child_sync);
0244
0245 ret = wait_child(&info->child_sync);
0246 if (ret)
0247 return ret;
0248
0249
0250 regs[0] = info->amr1;
0251 regs[1] = info->invalid_iamr;
0252 ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 2);
0253 PARENT_FAIL_IF(!ret, &info->child_sync);
0254
0255 printf("%-30s AMR: %016lx IAMR: %016lx\n",
0256 ptrace_write_running, regs[0], regs[1]);
0257
0258
0259 regs[2] = info->invalid_uamor;
0260 ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 3);
0261 PARENT_FAIL_IF(!ret, &info->child_sync);
0262
0263 printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
0264 ptrace_write_running, regs[0], regs[1], regs[2]);
0265
0266
0267 ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
0268 PARENT_FAIL_IF(ret, &info->child_sync);
0269
0270 printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
0271 ptrace_read_running, regs[0], regs[1], regs[2]);
0272
0273 PARENT_FAIL_IF(regs[0] != info->amr2, &info->child_sync);
0274 PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
0275 PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
0276
0277
0278 ret = prod_child(&info->child_sync);
0279 PARENT_FAIL_IF(ret, &info->child_sync);
0280
0281 ret = wait(&status);
0282 if (ret != pid) {
0283 printf("Child's exit status not captured\n");
0284 ret = TEST_PASS;
0285 } else if (!WIFEXITED(status)) {
0286 printf("Child exited abnormally\n");
0287 ret = TEST_FAIL;
0288 } else
0289 ret = WEXITSTATUS(status) ? TEST_FAIL : TEST_PASS;
0290
0291 return ret;
0292 }
0293
0294 static int ptrace_pkey(void)
0295 {
0296 struct shared_info *info;
0297 int shm_id;
0298 int ret;
0299 pid_t pid;
0300
0301 shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT);
0302 info = shmat(shm_id, NULL, 0);
0303
0304 ret = init_child_sync(&info->child_sync);
0305 if (ret)
0306 return ret;
0307
0308 pid = fork();
0309 if (pid < 0) {
0310 perror("fork() failed");
0311 ret = TEST_FAIL;
0312 } else if (pid == 0)
0313 ret = child(info);
0314 else
0315 ret = parent(info, pid);
0316
0317 shmdt(info);
0318
0319 if (pid) {
0320 destroy_child_sync(&info->child_sync);
0321 shmctl(shm_id, IPC_RMID, NULL);
0322 }
0323
0324 return ret;
0325 }
0326
0327 int main(int argc, char *argv[])
0328 {
0329 return test_harness(ptrace_pkey, "ptrace_pkey");
0330 }