diff options
Diffstat (limited to 'include/linux/tracehook.h')
-rw-r--r-- | include/linux/tracehook.h | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 8b4c15e208fe..3548694a24db 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -66,6 +66,76 @@ static inline int tracehook_expect_breakpoints(struct task_struct *task) | |||
66 | return (task_ptrace(task) & PT_PTRACED) != 0; | 66 | return (task_ptrace(task) & PT_PTRACED) != 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | /* | ||
70 | * ptrace report for syscall entry and exit looks identical. | ||
71 | */ | ||
72 | static inline void ptrace_report_syscall(struct pt_regs *regs) | ||
73 | { | ||
74 | int ptrace = task_ptrace(current); | ||
75 | |||
76 | if (!(ptrace & PT_PTRACED)) | ||
77 | return; | ||
78 | |||
79 | ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); | ||
80 | |||
81 | /* | ||
82 | * this isn't the same as continuing with a signal, but it will do | ||
83 | * for normal use. strace only continues with a signal if the | ||
84 | * stopping signal is not SIGTRAP. -brl | ||
85 | */ | ||
86 | if (current->exit_code) { | ||
87 | send_sig(current->exit_code, current, 1); | ||
88 | current->exit_code = 0; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * tracehook_report_syscall_entry - task is about to attempt a system call | ||
94 | * @regs: user register state of current task | ||
95 | * | ||
96 | * This will be called if %TIF_SYSCALL_TRACE has been set, when the | ||
97 | * current task has just entered the kernel for a system call. | ||
98 | * Full user register state is available here. Changing the values | ||
99 | * in @regs can affect the system call number and arguments to be tried. | ||
100 | * It is safe to block here, preventing the system call from beginning. | ||
101 | * | ||
102 | * Returns zero normally, or nonzero if the calling arch code should abort | ||
103 | * the system call. That must prevent normal entry so no system call is | ||
104 | * made. If @task ever returns to user mode after this, its register state | ||
105 | * is unspecified, but should be something harmless like an %ENOSYS error | ||
106 | * return. | ||
107 | * | ||
108 | * Called without locks, just after entering kernel mode. | ||
109 | */ | ||
110 | static inline __must_check int tracehook_report_syscall_entry( | ||
111 | struct pt_regs *regs) | ||
112 | { | ||
113 | ptrace_report_syscall(regs); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * tracehook_report_syscall_exit - task has just finished a system call | ||
119 | * @regs: user register state of current task | ||
120 | * @step: nonzero if simulating single-step or block-step | ||
121 | * | ||
122 | * This will be called if %TIF_SYSCALL_TRACE has been set, when the | ||
123 | * current task has just finished an attempted system call. Full | ||
124 | * user register state is available here. It is safe to block here, | ||
125 | * preventing signals from being processed. | ||
126 | * | ||
127 | * If @step is nonzero, this report is also in lieu of the normal | ||
128 | * trap that would follow the system call instruction because | ||
129 | * user_enable_block_step() or user_enable_single_step() was used. | ||
130 | * In this case, %TIF_SYSCALL_TRACE might not be set. | ||
131 | * | ||
132 | * Called without locks, just before checking for pending signals. | ||
133 | */ | ||
134 | static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) | ||
135 | { | ||
136 | ptrace_report_syscall(regs); | ||
137 | } | ||
138 | |||
69 | /** | 139 | /** |
70 | * tracehook_unsafe_exec - check for exec declared unsafe due to tracing | 140 | * tracehook_unsafe_exec - check for exec declared unsafe due to tracing |
71 | * @task: current task doing exec | 141 | * @task: current task doing exec |