.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Tracing hooks |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * This copyrighted material is made available to anyone wishing to use, |
---|
7 | | - * modify, copy, or redistribute it subject to the terms and conditions |
---|
8 | | - * of the GNU General Public License v.2. |
---|
9 | 6 | * |
---|
10 | 7 | * This file defines hook entry points called by core code where |
---|
11 | 8 | * user tracing/debugging support might need to do something. These |
---|
.. | .. |
---|
57 | 54 | /* |
---|
58 | 55 | * ptrace report for syscall entry and exit looks identical. |
---|
59 | 56 | */ |
---|
60 | | -static inline int ptrace_report_syscall(struct pt_regs *regs) |
---|
| 57 | +static inline int ptrace_report_syscall(struct pt_regs *regs, |
---|
| 58 | + unsigned long message) |
---|
61 | 59 | { |
---|
62 | 60 | int ptrace = current->ptrace; |
---|
63 | 61 | |
---|
64 | 62 | if (!(ptrace & PT_PTRACED)) |
---|
65 | 63 | return 0; |
---|
66 | 64 | |
---|
| 65 | + current->ptrace_message = message; |
---|
67 | 66 | ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); |
---|
68 | 67 | |
---|
69 | 68 | /* |
---|
.. | .. |
---|
76 | 75 | current->exit_code = 0; |
---|
77 | 76 | } |
---|
78 | 77 | |
---|
| 78 | + current->ptrace_message = 0; |
---|
79 | 79 | return fatal_signal_pending(current); |
---|
80 | 80 | } |
---|
81 | 81 | |
---|
.. | .. |
---|
83 | 83 | * tracehook_report_syscall_entry - task is about to attempt a system call |
---|
84 | 84 | * @regs: user register state of current task |
---|
85 | 85 | * |
---|
86 | | - * This will be called if %TIF_SYSCALL_TRACE has been set, when the |
---|
87 | | - * current task has just entered the kernel for a system call. |
---|
| 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 | 88 | * Full user register state is available here. Changing the values |
---|
89 | 89 | * in @regs can affect the system call number and arguments to be tried. |
---|
90 | 90 | * It is safe to block here, preventing the system call from beginning. |
---|
.. | .. |
---|
101 | 101 | static inline __must_check int tracehook_report_syscall_entry( |
---|
102 | 102 | struct pt_regs *regs) |
---|
103 | 103 | { |
---|
104 | | - return ptrace_report_syscall(regs); |
---|
| 104 | + return ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_ENTRY); |
---|
105 | 105 | } |
---|
106 | 106 | |
---|
107 | 107 | /** |
---|
.. | .. |
---|
123 | 123 | */ |
---|
124 | 124 | static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) |
---|
125 | 125 | { |
---|
126 | | - if (step) { |
---|
127 | | - siginfo_t info; |
---|
128 | | - clear_siginfo(&info); |
---|
129 | | - user_single_step_siginfo(current, regs, &info); |
---|
130 | | - force_sig_info(SIGTRAP, &info, current); |
---|
131 | | - return; |
---|
132 | | - } |
---|
133 | | - |
---|
134 | | - ptrace_report_syscall(regs); |
---|
| 126 | + if (step) |
---|
| 127 | + user_single_step_report(regs); |
---|
| 128 | + else |
---|
| 129 | + ptrace_report_syscall(regs, PTRACE_EVENTMSG_SYSCALL_EXIT); |
---|
135 | 130 | } |
---|
136 | 131 | |
---|
137 | 132 | /** |
---|
.. | .. |
---|
183 | 178 | */ |
---|
184 | 179 | static inline void tracehook_notify_resume(struct pt_regs *regs) |
---|
185 | 180 | { |
---|
| 181 | + clear_thread_flag(TIF_NOTIFY_RESUME); |
---|
186 | 182 | /* |
---|
187 | | - * The caller just cleared TIF_NOTIFY_RESUME. This barrier |
---|
188 | | - * pairs with task_work_add()->set_notify_resume() after |
---|
| 183 | + * This barrier pairs with task_work_add()->set_notify_resume() after |
---|
189 | 184 | * hlist_add_head(task->task_works); |
---|
190 | 185 | */ |
---|
191 | 186 | smp_mb__after_atomic(); |
---|
192 | 187 | if (unlikely(current->task_works)) |
---|
193 | 188 | task_work_run(); |
---|
194 | 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 | + |
---|
195 | 197 | mem_cgroup_handle_over_high(); |
---|
196 | 198 | blkcg_maybe_throttle_current(); |
---|
197 | 199 | } |
---|
198 | 200 | |
---|
| 201 | +/* |
---|
| 202 | + * called by exit_to_user_mode_loop() if ti_work & _TIF_NOTIFY_SIGNAL. This |
---|
| 203 | + * is currently used by TWA_SIGNAL based task_work, which requires breaking |
---|
| 204 | + * wait loops to ensure that task_work is noticed and run. |
---|
| 205 | + */ |
---|
| 206 | +static inline void tracehook_notify_signal(void) |
---|
| 207 | +{ |
---|
| 208 | + clear_thread_flag(TIF_NOTIFY_SIGNAL); |
---|
| 209 | + smp_mb__after_atomic(); |
---|
| 210 | + if (current->task_works) |
---|
| 211 | + task_work_run(); |
---|
| 212 | +} |
---|
| 213 | + |
---|
| 214 | +/* |
---|
| 215 | + * Called when we have work to process from exit_to_user_mode_loop() |
---|
| 216 | + */ |
---|
| 217 | +static inline void set_notify_signal(struct task_struct *task) |
---|
| 218 | +{ |
---|
| 219 | + if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_SIGNAL) && |
---|
| 220 | + !wake_up_state(task, TASK_INTERRUPTIBLE)) |
---|
| 221 | + kick_process(task); |
---|
| 222 | +} |
---|
| 223 | + |
---|
199 | 224 | #endif /* <linux/tracehook.h> */ |
---|