1 // SPDX-License-Identifier: GPL-2.0 !! 1 /* ptrace.c */ >> 2 /* By Ross Biro 1/23/92 */ >> 3 /* >> 4 * Pentium III FXSR, SSE support >> 5 * Gareth Hughes <gareth@valinux.com>, May 2000 >> 6 */ >> 7 >> 8 #include <linux/kernel.h> >> 9 #include <linux/sched.h> >> 10 #include <linux/mm.h> >> 11 #include <linux/smp.h> >> 12 #include <linux/smp_lock.h> >> 13 #include <linux/errno.h> 2 #include <linux/ptrace.h> 14 #include <linux/ptrace.h> >> 15 #include <linux/user.h> >> 16 #include <linux/security.h> 3 17 4 /** !! 18 #include <asm/uaccess.h> 5 * regs_query_register_offset() - query regist !! 19 #include <asm/pgtable.h> 6 * @name: the name of a register !! 20 #include <asm/system.h> 7 * !! 21 #include <asm/processor.h> 8 * regs_query_register_offset() returns the of !! 22 #include <asm/i387.h> 9 * pt_regs from its name. If the name is inval !! 23 #include <asm/debugreg.h> >> 24 #include <asm/ldt.h> >> 25 #include <asm/desc.h> >> 26 >> 27 /* >> 28 * does not yet catch signals sent when the child dies. >> 29 * in exit.c or in signal.c. 10 */ 30 */ 11 int regs_query_register_offset(const char *nam !! 31 >> 32 /* determines which flags the user has access to. */ >> 33 /* 1 = access 0 = no access */ >> 34 #define FLAG_MASK 0x00044dd5 >> 35 >> 36 /* set's the trap flag. */ >> 37 #define TRAP_FLAG 0x100 >> 38 >> 39 /* >> 40 * Offset of eflags on child stack.. >> 41 */ >> 42 #define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs)) >> 43 >> 44 /* >> 45 * this routine will get a word off of the processes privileged stack. >> 46 * the offset is how far from the base addr as stored in the TSS. >> 47 * this routine assumes that all the privileged stacks are in our >> 48 * data space. >> 49 */ >> 50 static inline int get_stack_long(struct task_struct *task, int offset) >> 51 { >> 52 unsigned char *stack; >> 53 >> 54 stack = (unsigned char *)task->thread.esp0; >> 55 stack += offset; >> 56 return (*((int *)stack)); >> 57 } >> 58 >> 59 /* >> 60 * this routine will put a word on the processes privileged stack. >> 61 * the offset is how far from the base addr as stored in the TSS. >> 62 * this routine assumes that all the privileged stacks are in our >> 63 * data space. >> 64 */ >> 65 static inline int put_stack_long(struct task_struct *task, int offset, >> 66 unsigned long data) >> 67 { >> 68 unsigned char * stack; >> 69 >> 70 stack = (unsigned char *) task->thread.esp0; >> 71 stack += offset; >> 72 *(unsigned long *) stack = data; >> 73 return 0; >> 74 } >> 75 >> 76 static int putreg(struct task_struct *child, >> 77 unsigned long regno, unsigned long value) >> 78 { >> 79 switch (regno >> 2) { >> 80 case FS: >> 81 if (value && (value & 3) != 3) >> 82 return -EIO; >> 83 child->thread.fs = value; >> 84 return 0; >> 85 case GS: >> 86 if (value && (value & 3) != 3) >> 87 return -EIO; >> 88 child->thread.gs = value; >> 89 return 0; >> 90 case DS: >> 91 case ES: >> 92 if (value && (value & 3) != 3) >> 93 return -EIO; >> 94 value &= 0xffff; >> 95 break; >> 96 case SS: >> 97 case CS: >> 98 if ((value & 3) != 3) >> 99 return -EIO; >> 100 value &= 0xffff; >> 101 break; >> 102 case EFL: >> 103 value &= FLAG_MASK; >> 104 value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK; >> 105 break; >> 106 } >> 107 if (regno > GS*4) >> 108 regno -= 2*4; >> 109 put_stack_long(child, regno - sizeof(struct pt_regs), value); >> 110 return 0; >> 111 } >> 112 >> 113 static unsigned long getreg(struct task_struct *child, >> 114 unsigned long regno) 12 { 115 { 13 const struct pt_regs_offset *roff; !! 116 unsigned long retval = ~0UL; 14 for (roff = regoffset_table; roff->nam !! 117 15 if (!strcmp(roff->name, name)) !! 118 switch (regno >> 2) { 16 return roff->offset; !! 119 case FS: 17 return -EINVAL; !! 120 retval = child->thread.fs; >> 121 break; >> 122 case GS: >> 123 retval = child->thread.gs; >> 124 break; >> 125 case DS: >> 126 case ES: >> 127 case SS: >> 128 case CS: >> 129 retval = 0xffff; >> 130 /* fall through */ >> 131 default: >> 132 if (regno > GS*4) >> 133 regno -= 2*4; >> 134 regno = regno - sizeof(struct pt_regs); >> 135 retval &= get_stack_long(child, regno); >> 136 } >> 137 return retval; 18 } 138 } 19 139 20 /** !! 140 /* 21 * regs_query_register_name() - query register !! 141 * Called by kernel/ptrace.c when detaching.. 22 * @offset: the offset of a register in st << 23 * 142 * 24 * regs_query_register_name() returns the name !! 143 * Make sure the single step bit is not set. 25 * offset in struct pt_regs. If the @offset is !! 144 */ >> 145 void ptrace_disable(struct task_struct *child) >> 146 { >> 147 long tmp; >> 148 >> 149 tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; >> 150 put_stack_long(child, EFL_OFFSET, tmp); >> 151 } >> 152 >> 153 /* >> 154 * Perform get_thread_area on behalf of the traced child. >> 155 */ >> 156 static int >> 157 ptrace_get_thread_area(struct task_struct *child, >> 158 int idx, struct user_desc __user *user_desc) >> 159 { >> 160 struct user_desc info; >> 161 struct desc_struct *desc; >> 162 >> 163 /* >> 164 * Get the current Thread-Local Storage area: >> 165 */ >> 166 >> 167 #define GET_BASE(desc) ( \ >> 168 (((desc)->a >> 16) & 0x0000ffff) | \ >> 169 (((desc)->b << 16) & 0x00ff0000) | \ >> 170 ( (desc)->b & 0xff000000) ) >> 171 >> 172 #define GET_LIMIT(desc) ( \ >> 173 ((desc)->a & 0x0ffff) | \ >> 174 ((desc)->b & 0xf0000) ) >> 175 >> 176 #define GET_32BIT(desc) (((desc)->b >> 23) & 1) >> 177 #define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) >> 178 #define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) >> 179 #define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) >> 180 #define GET_PRESENT(desc) (((desc)->b >> 15) & 1) >> 181 #define GET_USEABLE(desc) (((desc)->b >> 20) & 1) >> 182 >> 183 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) >> 184 return -EINVAL; >> 185 >> 186 desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; >> 187 >> 188 info.entry_number = idx; >> 189 info.base_addr = GET_BASE(desc); >> 190 info.limit = GET_LIMIT(desc); >> 191 info.seg_32bit = GET_32BIT(desc); >> 192 info.contents = GET_CONTENTS(desc); >> 193 info.read_exec_only = !GET_WRITABLE(desc); >> 194 info.limit_in_pages = GET_LIMIT_PAGES(desc); >> 195 info.seg_not_present = !GET_PRESENT(desc); >> 196 info.useable = GET_USEABLE(desc); >> 197 >> 198 if (copy_to_user(user_desc, &info, sizeof(info))) >> 199 return -EFAULT; >> 200 >> 201 return 0; >> 202 } >> 203 >> 204 /* >> 205 * Perform set_thread_area on behalf of the traced child. >> 206 */ >> 207 static int >> 208 ptrace_set_thread_area(struct task_struct *child, >> 209 int idx, struct user_desc __user *user_desc) >> 210 { >> 211 struct user_desc info; >> 212 struct desc_struct *desc; >> 213 >> 214 if (copy_from_user(&info, user_desc, sizeof(info))) >> 215 return -EFAULT; >> 216 >> 217 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) >> 218 return -EINVAL; >> 219 >> 220 desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; >> 221 if (LDT_empty(&info)) { >> 222 desc->a = 0; >> 223 desc->b = 0; >> 224 } else { >> 225 desc->a = LDT_entry_a(&info); >> 226 desc->b = LDT_entry_b(&info); >> 227 } >> 228 >> 229 return 0; >> 230 } >> 231 >> 232 asmlinkage int sys_ptrace(long request, long pid, long addr, long data) >> 233 { >> 234 struct task_struct *child; >> 235 struct user * dummy = NULL; >> 236 int i, ret; >> 237 >> 238 lock_kernel(); >> 239 ret = -EPERM; >> 240 if (request == PTRACE_TRACEME) { >> 241 /* are we already being traced? */ >> 242 if (current->ptrace & PT_PTRACED) >> 243 goto out; >> 244 ret = security_ptrace(current->parent, current); >> 245 if (ret) >> 246 goto out; >> 247 /* set the ptrace bit in the process flags. */ >> 248 current->ptrace |= PT_PTRACED; >> 249 ret = 0; >> 250 goto out; >> 251 } >> 252 ret = -ESRCH; >> 253 read_lock(&tasklist_lock); >> 254 child = find_task_by_pid(pid); >> 255 if (child) >> 256 get_task_struct(child); >> 257 read_unlock(&tasklist_lock); >> 258 if (!child) >> 259 goto out; >> 260 >> 261 ret = -EPERM; >> 262 if (pid == 1) /* you may not mess with init */ >> 263 goto out_tsk; >> 264 >> 265 if (request == PTRACE_ATTACH) { >> 266 ret = ptrace_attach(child); >> 267 goto out_tsk; >> 268 } >> 269 >> 270 ret = ptrace_check_attach(child, request == PTRACE_KILL); >> 271 if (ret < 0) >> 272 goto out_tsk; >> 273 >> 274 switch (request) { >> 275 /* when I and D space are separate, these will need to be fixed. */ >> 276 case PTRACE_PEEKTEXT: /* read word at location addr. */ >> 277 case PTRACE_PEEKDATA: { >> 278 unsigned long tmp; >> 279 int copied; >> 280 >> 281 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); >> 282 ret = -EIO; >> 283 if (copied != sizeof(tmp)) >> 284 break; >> 285 ret = put_user(tmp,(unsigned long *) data); >> 286 break; >> 287 } >> 288 >> 289 /* read the word at location addr in the USER area. */ >> 290 case PTRACE_PEEKUSR: { >> 291 unsigned long tmp; >> 292 >> 293 ret = -EIO; >> 294 if ((addr & 3) || addr < 0 || >> 295 addr > sizeof(struct user) - 3) >> 296 break; >> 297 >> 298 tmp = 0; /* Default return condition */ >> 299 if(addr < FRAME_SIZE*sizeof(long)) >> 300 tmp = getreg(child, addr); >> 301 if(addr >= (long) &dummy->u_debugreg[0] && >> 302 addr <= (long) &dummy->u_debugreg[7]){ >> 303 addr -= (long) &dummy->u_debugreg[0]; >> 304 addr = addr >> 2; >> 305 tmp = child->thread.debugreg[addr]; >> 306 } >> 307 ret = put_user(tmp,(unsigned long *) data); >> 308 break; >> 309 } >> 310 >> 311 /* when I and D space are separate, this will have to be fixed. */ >> 312 case PTRACE_POKETEXT: /* write the word at location addr. */ >> 313 case PTRACE_POKEDATA: >> 314 ret = 0; >> 315 if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) >> 316 break; >> 317 ret = -EIO; >> 318 break; >> 319 >> 320 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ >> 321 ret = -EIO; >> 322 if ((addr & 3) || addr < 0 || >> 323 addr > sizeof(struct user) - 3) >> 324 break; >> 325 >> 326 if (addr < FRAME_SIZE*sizeof(long)) { >> 327 ret = putreg(child, addr, data); >> 328 break; >> 329 } >> 330 /* We need to be very careful here. We implicitly >> 331 want to modify a portion of the task_struct, and we >> 332 have to be selective about what portions we allow someone >> 333 to modify. */ >> 334 >> 335 ret = -EIO; >> 336 if(addr >= (long) &dummy->u_debugreg[0] && >> 337 addr <= (long) &dummy->u_debugreg[7]){ >> 338 >> 339 if(addr == (long) &dummy->u_debugreg[4]) break; >> 340 if(addr == (long) &dummy->u_debugreg[5]) break; >> 341 if(addr < (long) &dummy->u_debugreg[4] && >> 342 ((unsigned long) data) >= TASK_SIZE-3) break; >> 343 >> 344 if(addr == (long) &dummy->u_debugreg[7]) { >> 345 data &= ~DR_CONTROL_RESERVED; >> 346 for(i=0; i<4; i++) >> 347 if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) >> 348 goto out_tsk; >> 349 } >> 350 >> 351 addr -= (long) &dummy->u_debugreg; >> 352 addr = addr >> 2; >> 353 child->thread.debugreg[addr] = data; >> 354 ret = 0; >> 355 } >> 356 break; >> 357 >> 358 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ >> 359 case PTRACE_CONT: { /* restart after signal. */ >> 360 long tmp; >> 361 >> 362 ret = -EIO; >> 363 if ((unsigned long) data > _NSIG) >> 364 break; >> 365 if (request == PTRACE_SYSCALL) { >> 366 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); >> 367 } >> 368 else { >> 369 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); >> 370 } >> 371 child->exit_code = data; >> 372 /* make sure the single step bit is not set. */ >> 373 tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; >> 374 put_stack_long(child, EFL_OFFSET,tmp); >> 375 wake_up_process(child); >> 376 ret = 0; >> 377 break; >> 378 } >> 379 >> 380 /* >> 381 * make the child exit. Best I can do is send it a sigkill. >> 382 * perhaps it should be put in the status that it wants to >> 383 * exit. 26 */ 384 */ 27 const char *regs_query_register_name(unsigned !! 385 case PTRACE_KILL: { >> 386 long tmp; >> 387 >> 388 ret = 0; >> 389 if (child->state == TASK_ZOMBIE) /* already dead */ >> 390 break; >> 391 child->exit_code = SIGKILL; >> 392 /* make sure the single step bit is not set. */ >> 393 tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; >> 394 put_stack_long(child, EFL_OFFSET, tmp); >> 395 wake_up_process(child); >> 396 break; >> 397 } >> 398 >> 399 case PTRACE_SINGLESTEP: { /* set the trap flag. */ >> 400 long tmp; >> 401 >> 402 ret = -EIO; >> 403 if ((unsigned long) data > _NSIG) >> 404 break; >> 405 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); >> 406 if ((child->ptrace & PT_DTRACE) == 0) { >> 407 /* Spurious delayed TF traps may occur */ >> 408 child->ptrace |= PT_DTRACE; >> 409 } >> 410 tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; >> 411 put_stack_long(child, EFL_OFFSET, tmp); >> 412 child->exit_code = data; >> 413 /* give it a chance to run. */ >> 414 wake_up_process(child); >> 415 ret = 0; >> 416 break; >> 417 } >> 418 >> 419 case PTRACE_DETACH: >> 420 /* detach a process that was attached. */ >> 421 ret = ptrace_detach(child, data); >> 422 break; >> 423 >> 424 case PTRACE_GETREGS: { /* Get all gp regs from the child. */ >> 425 if (!access_ok(VERIFY_WRITE, (unsigned *)data, FRAME_SIZE*sizeof(long))) { >> 426 ret = -EIO; >> 427 break; >> 428 } >> 429 for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) { >> 430 __put_user(getreg(child, i),(unsigned long *) data); >> 431 data += sizeof(long); >> 432 } >> 433 ret = 0; >> 434 break; >> 435 } >> 436 >> 437 case PTRACE_SETREGS: { /* Set all gp regs in the child. */ >> 438 unsigned long tmp; >> 439 if (!access_ok(VERIFY_READ, (unsigned *)data, FRAME_SIZE*sizeof(long))) { >> 440 ret = -EIO; >> 441 break; >> 442 } >> 443 for ( i = 0; i < FRAME_SIZE*sizeof(long); i += sizeof(long) ) { >> 444 __get_user(tmp, (unsigned long *) data); >> 445 putreg(child, i, tmp); >> 446 data += sizeof(long); >> 447 } >> 448 ret = 0; >> 449 break; >> 450 } >> 451 >> 452 case PTRACE_GETFPREGS: { /* Get the child FPU state. */ >> 453 if (!access_ok(VERIFY_WRITE, (unsigned *)data, >> 454 sizeof(struct user_i387_struct))) { >> 455 ret = -EIO; >> 456 break; >> 457 } >> 458 ret = 0; >> 459 if (!child->used_math) >> 460 init_fpu(child); >> 461 get_fpregs((struct user_i387_struct __user *)data, child); >> 462 break; >> 463 } >> 464 >> 465 case PTRACE_SETFPREGS: { /* Set the child FPU state. */ >> 466 if (!access_ok(VERIFY_READ, (unsigned *)data, >> 467 sizeof(struct user_i387_struct))) { >> 468 ret = -EIO; >> 469 break; >> 470 } >> 471 child->used_math = 1; >> 472 set_fpregs(child, (struct user_i387_struct __user *)data); >> 473 ret = 0; >> 474 break; >> 475 } >> 476 >> 477 case PTRACE_GETFPXREGS: { /* Get the child extended FPU state. */ >> 478 if (!access_ok(VERIFY_WRITE, (unsigned *)data, >> 479 sizeof(struct user_fxsr_struct))) { >> 480 ret = -EIO; >> 481 break; >> 482 } >> 483 if (!child->used_math) >> 484 init_fpu(child); >> 485 ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); >> 486 break; >> 487 } >> 488 >> 489 case PTRACE_SETFPXREGS: { /* Set the child extended FPU state. */ >> 490 if (!access_ok(VERIFY_READ, (unsigned *)data, >> 491 sizeof(struct user_fxsr_struct))) { >> 492 ret = -EIO; >> 493 break; >> 494 } >> 495 child->used_math = 1; >> 496 ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data); >> 497 break; >> 498 } >> 499 >> 500 case PTRACE_GET_THREAD_AREA: >> 501 ret = ptrace_get_thread_area(child, >> 502 addr, (struct user_desc __user *) data); >> 503 break; >> 504 >> 505 case PTRACE_SET_THREAD_AREA: >> 506 ret = ptrace_set_thread_area(child, >> 507 addr, (struct user_desc __user *) data); >> 508 break; >> 509 >> 510 default: >> 511 ret = ptrace_request(child, request, addr, data); >> 512 break; >> 513 } >> 514 out_tsk: >> 515 put_task_struct(child); >> 516 out: >> 517 unlock_kernel(); >> 518 return ret; >> 519 } >> 520 >> 521 /* notification of system call entry/exit >> 522 * - triggered by current->work.syscall_trace >> 523 */ >> 524 __attribute__((regparm(3))) >> 525 void do_syscall_trace(struct pt_regs *regs, int entryexit) 28 { 526 { 29 const struct pt_regs_offset *roff; !! 527 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 30 for (roff = regoffset_table; roff->nam !! 528 return; 31 if (roff->offset == offset) !! 529 if (!(current->ptrace & PT_PTRACED)) 32 return roff->name; !! 530 return; 33 return NULL; !! 531 /* the 0x80 provides a way for the tracing parent to distinguish >> 532 between a syscall stop and SIGTRAP delivery */ >> 533 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) >> 534 ? 0x80 : 0)); >> 535 >> 536 /* >> 537 * this isn't the same as continuing with a signal, but it will do >> 538 * for normal use. strace only continues with a signal if the >> 539 * stopping signal is not SIGTRAP. -brl >> 540 */ >> 541 if (current->exit_code) { >> 542 send_sig(current->exit_code, current, 1); >> 543 current->exit_code = 0; >> 544 } 34 } 545 } 35 546
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.