LCOV - code coverage report
Current view: top level - include/linux - tracehook.h (source / functions) Hit Total Coverage
Test: combined.info Lines: 12 19 63.2 %
Date: 2022-03-28 15:32:58 Functions: 1 1 100.0 %
Branches: 6 12 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :            : /*
       3                 :            :  * Tracing hooks
       4                 :            :  *
       5                 :            :  * Copyright (C) 2008-2009 Red Hat, Inc.  All rights reserved.
       6                 :            :  *
       7                 :            :  * This file defines hook entry points called by core code where
       8                 :            :  * user tracing/debugging support might need to do something.  These
       9                 :            :  * entry points are called tracehook_*().  Each hook declared below
      10                 :            :  * has a detailed kerneldoc comment giving the context (locking et
      11                 :            :  * al) from which it is called, and the meaning of its return value.
      12                 :            :  *
      13                 :            :  * Each function here typically has only one call site, so it is ok
      14                 :            :  * to have some nontrivial tracehook_*() inlines.  In all cases, the
      15                 :            :  * fast path when no tracing is enabled should be very short.
      16                 :            :  *
      17                 :            :  * The purpose of this file and the tracehook_* layer is to consolidate
      18                 :            :  * the interface that the kernel core and arch code uses to enable any
      19                 :            :  * user debugging or tracing facility (such as ptrace).  The interfaces
      20                 :            :  * here are carefully documented so that maintainers of core and arch
      21                 :            :  * code do not need to think about the implementation details of the
      22                 :            :  * tracing facilities.  Likewise, maintainers of the tracing code do not
      23                 :            :  * need to understand all the calling core or arch code in detail, just
      24                 :            :  * documented circumstances of each call, such as locking conditions.
      25                 :            :  *
      26                 :            :  * If the calling core code changes so that locking is different, then
      27                 :            :  * it is ok to change the interface documented here.  The maintainer of
      28                 :            :  * core code changing should notify the maintainers of the tracing code
      29                 :            :  * that they need to work out the change.
      30                 :            :  *
      31                 :            :  * Some tracehook_*() inlines take arguments that the current tracing
      32                 :            :  * implementations might not necessarily use.  These function signatures
      33                 :            :  * are chosen to pass in all the information that is on hand in the
      34                 :            :  * caller and might conceivably be relevant to a tracer, so that the
      35                 :            :  * core code won't have to be updated when tracing adds more features.
      36                 :            :  * If a call site changes so that some of those parameters are no longer
      37                 :            :  * already on hand without extra work, then the tracehook_* interface
      38                 :            :  * can change so there is no make-work burden on the core code.  The
      39                 :            :  * maintainer of core code changing should notify the maintainers of the
      40                 :            :  * tracing code that they need to work out the change.
      41                 :            :  */
      42                 :            : 
      43                 :            : #ifndef _LINUX_TRACEHOOK_H
      44                 :            : #define _LINUX_TRACEHOOK_H      1
      45                 :            : 
      46                 :            : #include <linux/sched.h>
      47                 :            : #include <linux/ptrace.h>
      48                 :            : #include <linux/security.h>
      49                 :            : #include <linux/task_work.h>
      50                 :            : #include <linux/memcontrol.h>
      51                 :            : #include <linux/blk-cgroup.h>
      52                 :            : struct linux_binprm;
      53                 :            : 
      54                 :            : /*
      55                 :            :  * ptrace report for syscall entry and exit looks identical.
      56                 :            :  */
      57                 :            : static inline int ptrace_report_syscall(struct pt_regs *regs,
      58                 :            :                                         unsigned long message)
      59                 :            : {
      60                 :            :         int ptrace = current->ptrace;
      61                 :            : 
      62                 :            :         if (!(ptrace & PT_PTRACED))
      63                 :            :                 return 0;
      64                 :            : 
      65                 :            :         current->ptrace_message = message;
      66                 :            :         ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
      67                 :            : 
      68                 :            :         /*
      69                 :            :          * this isn't the same as continuing with a signal, but it will do
      70                 :            :          * for normal use.  strace only continues with a signal if the
      71                 :            :          * stopping signal is not SIGTRAP.  -brl
      72                 :            :          */
      73                 :            :         if (current->exit_code) {
      74                 :            :                 send_sig(current->exit_code, current, 1);
      75                 :            :                 current->exit_code = 0;
      76                 :            :         }
      77                 :            : 
      78                 :            :         current->ptrace_message = 0;
      79                 :            :         return fatal_signal_pending(current);
      80                 :            : }
      81                 :            : 
      82                 :            : /**
      83                 :            :  * tracehook_report_syscall_entry - task is about to attempt a system call
      84                 :            :  * @regs:               user register state of current task
      85                 :            :  *
      86                 :            :  * This will be called if %TIF_SYSCALL_TRACE or %TIF_SYSCALL_EMU have been set,
      87                 :            :  * when the current task has just entered the kernel for a system call.
      88                 :            :  * Full user register state is available here.  Changing the values
      89                 :            :  * in @regs can affect the system call number and arguments to be tried.
      90                 :            :  * It is safe to block here, preventing the system call from beginning.
      91                 :            :  *
      92                 :            :  * Returns zero normally, or nonzero if the calling arch code should abort
      93                 :            :  * the system call.  That must prevent normal entry so no system call is
      94                 :            :  * made.  If @task ever returns to user mode after this, its register state
      95                 :            :  * is unspecified, but should be something harmless like an %ENOSYS error
      96                 :            :  * return.  It should preserve enough information so that syscall_rollback()
      97                 :            :  * can work (see asm-generic/syscall.h).
      98                 :            :  *
      99                 :            :  * Called without locks, just after entering kernel mode.
     100                 :            :  */
     101                 :          0 : static inline __must_check int tracehook_report_syscall_entry(
     102                 :            :         struct pt_regs *regs)
     103                 :            : {
     104                 :          0 :         return ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_ENTRY);
     105                 :            : }
     106                 :            : 
     107                 :            : /**
     108                 :            :  * tracehook_report_syscall_exit - task has just finished a system call
     109                 :            :  * @regs:               user register state of current task
     110                 :            :  * @step:               nonzero if simulating single-step or block-step
     111                 :            :  *
     112                 :            :  * This will be called if %TIF_SYSCALL_TRACE has been set, when the
     113                 :            :  * current task has just finished an attempted system call.  Full
     114                 :            :  * user register state is available here.  It is safe to block here,
     115                 :            :  * preventing signals from being processed.
     116                 :            :  *
     117                 :            :  * If @step is nonzero, this report is also in lieu of the normal
     118                 :            :  * trap that would follow the system call instruction because
     119                 :            :  * user_enable_block_step() or user_enable_single_step() was used.
     120                 :            :  * In this case, %TIF_SYSCALL_TRACE might not be set.
     121                 :            :  *
     122                 :            :  * Called without locks, just before checking for pending signals.
     123                 :            :  */
     124                 :          0 : static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
     125                 :            : {
     126         [ #  # ]:          0 :         if (step)
     127                 :          0 :                 user_single_step_report(regs);
     128                 :            :         else
     129                 :          0 :                 ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_EXIT);
     130                 :            : }
     131                 :            : 
     132                 :            : /**
     133                 :            :  * tracehook_signal_handler - signal handler setup is complete
     134                 :            :  * @stepping:           nonzero if debugger single-step or block-step in use
     135                 :            :  *
     136                 :            :  * Called by the arch code after a signal handler has been set up.
     137                 :            :  * Register and stack state reflects the user handler about to run.
     138                 :            :  * Signal mask changes have already been made.
     139                 :            :  *
     140                 :            :  * Called without locks, shortly before returning to user mode
     141                 :            :  * (or handling more signals).
     142                 :            :  */
     143                 :       1344 : static inline void tracehook_signal_handler(int stepping)
     144                 :            : {
     145         [ -  + ]:       1344 :         if (stepping)
     146                 :          0 :                 ptrace_notify(SIGTRAP);
     147                 :            : }
     148                 :            : 
     149                 :            : /**
     150                 :            :  * set_notify_resume - cause tracehook_notify_resume() to be called
     151                 :            :  * @task:               task that will call tracehook_notify_resume()
     152                 :            :  *
     153                 :            :  * Calling this arranges that @task will call tracehook_notify_resume()
     154                 :            :  * before returning to user mode.  If it's already running in user mode,
     155                 :            :  * it will enter the kernel and call tracehook_notify_resume() soon.
     156                 :            :  * If it's blocked, it will not be woken.
     157                 :            :  */
     158                 :    1268577 : static inline void set_notify_resume(struct task_struct *task)
     159                 :            : {
     160                 :            : #ifdef TIF_NOTIFY_RESUME
     161         [ +  + ]:    1268577 :         if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME))
     162                 :    1089433 :                 kick_process(task);
     163                 :            : #endif
     164                 :    1268577 : }
     165                 :            : 
     166                 :            : /**
     167                 :            :  * tracehook_notify_resume - report when about to return to user mode
     168                 :            :  * @regs:               user-mode registers of @current task
     169                 :            :  *
     170                 :            :  * This is called when %TIF_NOTIFY_RESUME has been set.  Now we are
     171                 :            :  * about to return to user mode, and the user state in @regs can be
     172                 :            :  * inspected or adjusted.  The caller in arch code has cleared
     173                 :            :  * %TIF_NOTIFY_RESUME before the call.  If the flag gets set again
     174                 :            :  * asynchronously, this will be called again before we return to
     175                 :            :  * user mode.
     176                 :            :  *
     177                 :            :  * Called without locks.
     178                 :            :  */
     179                 :    1724617 : static inline void tracehook_notify_resume(struct pt_regs *regs)
     180                 :            : {
     181                 :            :         /*
     182                 :            :          * The caller just cleared TIF_NOTIFY_RESUME. This barrier
     183                 :            :          * pairs with task_work_add()->set_notify_resume() after
     184                 :            :          * hlist_add_head(task->task_works);
     185                 :            :          */
     186                 :    1724617 :         smp_mb__after_atomic();
     187         [ +  - ]:    1724617 :         if (unlikely(current->task_works))
     188                 :    1724617 :                 task_work_run();
     189                 :            : 
     190                 :            : #ifdef CONFIG_KEYS_REQUEST_CACHE
     191                 :            :         if (unlikely(current->cached_requested_key)) {
     192                 :            :                 key_put(current->cached_requested_key);
     193                 :            :                 current->cached_requested_key = NULL;
     194                 :            :         }
     195                 :            : #endif
     196                 :            : 
     197         [ -  + ]:    1724617 :         mem_cgroup_handle_over_high();
     198         [ -  + ]:    1724617 :         blkcg_maybe_throttle_current();
     199                 :            : }
     200                 :            : 
     201                 :            : #endif  /* <linux/tracehook.h> */

Generated by: LCOV version 1.14