| .. | .. | 
|---|
|  | 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> */ | 
|---|