LCOV - code coverage report
Current view: top level - arch/um/kernel - ptrace.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 4 51 7.8 %
Date: 2023-04-06 08:38:28 Functions: 1 6 16.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       4             :  */
       5             : 
       6             : #include <linux/audit.h>
       7             : #include <linux/ptrace.h>
       8             : #include <linux/sched.h>
       9             : #include <linux/uaccess.h>
      10             : #include <asm/ptrace-abi.h>
      11             : 
      12           0 : void user_enable_single_step(struct task_struct *child)
      13             : {
      14           0 :         set_tsk_thread_flag(child, TIF_SINGLESTEP);
      15           0 :         child->thread.singlestep_syscall = 0;
      16             : 
      17             : #ifdef SUBARCH_SET_SINGLESTEPPING
      18             :         SUBARCH_SET_SINGLESTEPPING(child, 1);
      19             : #endif
      20           0 : }
      21             : 
      22         348 : void user_disable_single_step(struct task_struct *child)
      23             : {
      24         696 :         clear_tsk_thread_flag(child, TIF_SINGLESTEP);
      25         348 :         child->thread.singlestep_syscall = 0;
      26             : 
      27             : #ifdef SUBARCH_SET_SINGLESTEPPING
      28             :         SUBARCH_SET_SINGLESTEPPING(child, 0);
      29             : #endif
      30         348 : }
      31             : 
      32             : /*
      33             :  * Called by kernel/ptrace.c when detaching..
      34             :  */
      35           0 : void ptrace_disable(struct task_struct *child)
      36             : {
      37           0 :         user_disable_single_step(child);
      38           0 : }
      39             : 
      40             : extern int peek_user(struct task_struct * child, long addr, long data);
      41             : extern int poke_user(struct task_struct * child, long addr, long data);
      42             : 
      43           0 : long arch_ptrace(struct task_struct *child, long request,
      44             :                  unsigned long addr, unsigned long data)
      45             : {
      46             :         int i, ret;
      47           0 :         unsigned long __user *p = (void __user *)data;
      48           0 :         void __user *vp = p;
      49             : 
      50           0 :         switch (request) {
      51             :         /* read the word at location addr in the USER area. */
      52             :         case PTRACE_PEEKUSR:
      53           0 :                 ret = peek_user(child, addr, data);
      54           0 :                 break;
      55             : 
      56             :         /* write the word at location addr in the USER area */
      57             :         case PTRACE_POKEUSR:
      58           0 :                 ret = poke_user(child, addr, data);
      59           0 :                 break;
      60             : 
      61             :         case PTRACE_SYSEMU:
      62             :         case PTRACE_SYSEMU_SINGLESTEP:
      63             :                 ret = -EIO;
      64             :                 break;
      65             : 
      66             : #ifdef PTRACE_GETREGS
      67             :         case PTRACE_GETREGS: { /* Get all gp regs from the child. */
      68           0 :                 if (!access_ok(p, MAX_REG_OFFSET)) {
      69             :                         ret = -EIO;
      70             :                         break;
      71             :                 }
      72           0 :                 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
      73           0 :                         __put_user(getreg(child, i), p);
      74           0 :                         p++;
      75             :                 }
      76             :                 ret = 0;
      77             :                 break;
      78             :         }
      79             : #endif
      80             : #ifdef PTRACE_SETREGS
      81             :         case PTRACE_SETREGS: { /* Set all gp regs in the child. */
      82           0 :                 unsigned long tmp = 0;
      83           0 :                 if (!access_ok(p, MAX_REG_OFFSET)) {
      84             :                         ret = -EIO;
      85             :                         break;
      86             :                 }
      87           0 :                 for ( i = 0; i < MAX_REG_OFFSET; i += sizeof(long) ) {
      88           0 :                         __get_user(tmp, p);
      89           0 :                         putreg(child, i, tmp);
      90           0 :                         p++;
      91             :                 }
      92             :                 ret = 0;
      93             :                 break;
      94             :         }
      95             : #endif
      96             :         case PTRACE_GET_THREAD_AREA:
      97           0 :                 ret = ptrace_get_thread_area(child, addr, vp);
      98           0 :                 break;
      99             : 
     100             :         case PTRACE_SET_THREAD_AREA:
     101           0 :                 ret = ptrace_set_thread_area(child, addr, vp);
     102           0 :                 break;
     103             : 
     104             :         default:
     105           0 :                 ret = ptrace_request(child, request, addr, data);
     106           0 :                 if (ret == -EIO)
     107           0 :                         ret = subarch_ptrace(child, request, addr, data);
     108             :                 break;
     109             :         }
     110             : 
     111           0 :         return ret;
     112             : }
     113             : 
     114             : static void send_sigtrap(struct uml_pt_regs *regs, int error_code)
     115             : {
     116             :         /* Send us the fake SIGTRAP */
     117           0 :         force_sig_fault(SIGTRAP, TRAP_BRKPT,
     118             :                         /* User-mode eip? */
     119             :                         UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL);
     120             : }
     121             : 
     122             : /*
     123             :  * XXX Check TIF_SINGLESTEP for singlestepping check and
     124             :  * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
     125             :  */
     126           0 : int syscall_trace_enter(struct pt_regs *regs)
     127             : {
     128           0 :         audit_syscall_entry(UPT_SYSCALL_NR(&regs->regs),
     129             :                             UPT_SYSCALL_ARG1(&regs->regs),
     130             :                             UPT_SYSCALL_ARG2(&regs->regs),
     131             :                             UPT_SYSCALL_ARG3(&regs->regs),
     132             :                             UPT_SYSCALL_ARG4(&regs->regs));
     133             : 
     134           0 :         if (!test_thread_flag(TIF_SYSCALL_TRACE))
     135             :                 return 0;
     136             : 
     137           0 :         return ptrace_report_syscall_entry(regs);
     138             : }
     139             : 
     140           0 : void syscall_trace_leave(struct pt_regs *regs)
     141             : {
     142           0 :         int ptraced = current->ptrace;
     143             : 
     144           0 :         audit_syscall_exit(regs);
     145             : 
     146             :         /* Fake a debug trap */
     147           0 :         if (test_thread_flag(TIF_SINGLESTEP))
     148           0 :                 send_sigtrap(&regs->regs, 0);
     149             : 
     150           0 :         if (!test_thread_flag(TIF_SYSCALL_TRACE))
     151             :                 return;
     152             : 
     153           0 :         ptrace_report_syscall_exit(regs, 0);
     154             :         /* force do_signal() --> is_syscall() */
     155           0 :         if (ptraced & PT_PTRACED)
     156           0 :                 set_thread_flag(TIF_SIGPENDING);
     157             : }

Generated by: LCOV version 1.14