blob: 830e6e16097d2aa89c527d8b4cdd5c0df1116520 [file] [log] [blame]
Roland McGrath88ac2922008-07-25 19:45:43 -07001/*
2 * Tracing hooks
3 *
4 * Copyright (C) 2008 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 *
10 * This file defines hook entry points called by core code where
11 * user tracing/debugging support might need to do something. These
12 * entry points are called tracehook_*(). Each hook declared below
13 * has a detailed kerneldoc comment giving the context (locking et
14 * al) from which it is called, and the meaning of its return value.
15 *
16 * Each function here typically has only one call site, so it is ok
17 * to have some nontrivial tracehook_*() inlines. In all cases, the
18 * fast path when no tracing is enabled should be very short.
19 *
20 * The purpose of this file and the tracehook_* layer is to consolidate
21 * the interface that the kernel core and arch code uses to enable any
22 * user debugging or tracing facility (such as ptrace). The interfaces
23 * here are carefully documented so that maintainers of core and arch
24 * code do not need to think about the implementation details of the
25 * tracing facilities. Likewise, maintainers of the tracing code do not
26 * need to understand all the calling core or arch code in detail, just
27 * documented circumstances of each call, such as locking conditions.
28 *
29 * If the calling core code changes so that locking is different, then
30 * it is ok to change the interface documented here. The maintainer of
31 * core code changing should notify the maintainers of the tracing code
32 * that they need to work out the change.
33 *
34 * Some tracehook_*() inlines take arguments that the current tracing
35 * implementations might not necessarily use. These function signatures
36 * are chosen to pass in all the information that is on hand in the
37 * caller and might conceivably be relevant to a tracer, so that the
38 * core code won't have to be updated when tracing adds more features.
39 * If a call site changes so that some of those parameters are no longer
40 * already on hand without extra work, then the tracehook_* interface
41 * can change so there is no make-work burden on the core code. The
42 * maintainer of core code changing should notify the maintainers of the
43 * tracing code that they need to work out the change.
44 */
45
46#ifndef _LINUX_TRACEHOOK_H
47#define _LINUX_TRACEHOOK_H 1
48
49#include <linux/sched.h>
50#include <linux/ptrace.h>
Roland McGrath6341c392008-07-25 19:45:44 -070051#include <linux/security.h>
52struct linux_binprm;
53
54/**
55 * tracehook_unsafe_exec - check for exec declared unsafe due to tracing
56 * @task: current task doing exec
57 *
58 * Return %LSM_UNSAFE_* bits applied to an exec because of tracing.
59 *
60 * Called with task_lock() held on @task.
61 */
62static inline int tracehook_unsafe_exec(struct task_struct *task)
63{
64 int unsafe = 0;
65 int ptrace = task_ptrace(task);
66 if (ptrace & PT_PTRACED) {
67 if (ptrace & PT_PTRACE_CAP)
68 unsafe |= LSM_UNSAFE_PTRACE_CAP;
69 else
70 unsafe |= LSM_UNSAFE_PTRACE;
71 }
72 return unsafe;
73}
74
75/**
76 * tracehook_report_exec - a successful exec was completed
77 * @fmt: &struct linux_binfmt that performed the exec
78 * @bprm: &struct linux_binprm containing exec details
79 * @regs: user-mode register state
80 *
81 * An exec just completed, we are shortly going to return to user mode.
82 * The freshly initialized register state can be seen and changed in @regs.
83 * The name, file and other pointers in @bprm are still on hand to be
84 * inspected, but will be freed as soon as this returns.
85 *
86 * Called with no locks, but with some kernel resources held live
87 * and a reference on @fmt->module.
88 */
89static inline void tracehook_report_exec(struct linux_binfmt *fmt,
90 struct linux_binprm *bprm,
91 struct pt_regs *regs)
92{
93 if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) &&
94 unlikely(task_ptrace(current) & PT_PTRACED))
95 send_sig(SIGTRAP, current, 0);
96}
Roland McGrath88ac2922008-07-25 19:45:43 -070097
Roland McGrath30199f52008-07-25 19:45:46 -070098/**
99 * tracehook_report_exit - task has begun to exit
100 * @exit_code: pointer to value destined for @current->exit_code
101 *
102 * @exit_code points to the value passed to do_exit(), which tracing
103 * might change here. This is almost the first thing in do_exit(),
104 * before freeing any resources or setting the %PF_EXITING flag.
105 *
106 * Called with no locks held.
107 */
108static inline void tracehook_report_exit(long *exit_code)
109{
110 ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code);
111}
112
Roland McGrath09a05392008-07-25 19:45:47 -0700113/**
114 * tracehook_prepare_clone - prepare for new child to be cloned
115 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call
116 *
117 * This is called before a new user task is to be cloned.
118 * Its return value will be passed to tracehook_finish_clone().
119 *
120 * Called with no locks held.
121 */
122static inline int tracehook_prepare_clone(unsigned clone_flags)
123{
124 if (clone_flags & CLONE_UNTRACED)
125 return 0;
126
127 if (clone_flags & CLONE_VFORK) {
128 if (current->ptrace & PT_TRACE_VFORK)
129 return PTRACE_EVENT_VFORK;
130 } else if ((clone_flags & CSIGNAL) != SIGCHLD) {
131 if (current->ptrace & PT_TRACE_CLONE)
132 return PTRACE_EVENT_CLONE;
133 } else if (current->ptrace & PT_TRACE_FORK)
134 return PTRACE_EVENT_FORK;
135
136 return 0;
137}
138
139/**
140 * tracehook_finish_clone - new child created and being attached
141 * @child: new child task
142 * @clone_flags: %CLONE_* flags from clone/fork/vfork system call
143 * @trace: return value from tracehook_clone_prepare()
144 *
145 * This is called immediately after adding @child to its parent's children list.
146 * The @trace value is that returned by tracehook_prepare_clone().
147 *
148 * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
149 */
150static inline void tracehook_finish_clone(struct task_struct *child,
151 unsigned long clone_flags, int trace)
152{
153 ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace);
154}
155
156/**
157 * tracehook_report_clone - in parent, new child is about to start running
158 * @trace: return value from tracehook_clone_prepare()
159 * @regs: parent's user register state
160 * @clone_flags: flags from parent's system call
161 * @pid: new child's PID in the parent's namespace
162 * @child: new child task
163 *
164 * Called after a child is set up, but before it has been started running.
165 * The @trace value is that returned by tracehook_clone_prepare().
166 * This is not a good place to block, because the child has not started yet.
167 * Suspend the child here if desired, and block in tracehook_clone_complete().
168 * This must prevent the child from self-reaping if tracehook_clone_complete()
169 * uses the @child pointer; otherwise it might have died and been released by
170 * the time tracehook_report_clone_complete() is called.
171 *
172 * Called with no locks held, but the child cannot run until this returns.
173 */
174static inline void tracehook_report_clone(int trace, struct pt_regs *regs,
175 unsigned long clone_flags,
176 pid_t pid, struct task_struct *child)
177{
178 if (unlikely(trace)) {
179 /*
180 * The child starts up with an immediate SIGSTOP.
181 */
182 sigaddset(&child->pending.signal, SIGSTOP);
183 set_tsk_thread_flag(child, TIF_SIGPENDING);
184 }
185}
186
187/**
188 * tracehook_report_clone_complete - new child is running
189 * @trace: return value from tracehook_clone_prepare()
190 * @regs: parent's user register state
191 * @clone_flags: flags from parent's system call
192 * @pid: new child's PID in the parent's namespace
193 * @child: child task, already running
194 *
195 * This is called just after the child has started running. This is
196 * just before the clone/fork syscall returns, or blocks for vfork
197 * child completion if @clone_flags has the %CLONE_VFORK bit set.
198 * The @child pointer may be invalid if a self-reaping child died and
199 * tracehook_report_clone() took no action to prevent it from self-reaping.
200 *
201 * Called with no locks held.
202 */
203static inline void tracehook_report_clone_complete(int trace,
204 struct pt_regs *regs,
205 unsigned long clone_flags,
206 pid_t pid,
207 struct task_struct *child)
208{
209 if (unlikely(trace))
210 ptrace_event(0, trace, pid);
211}
212
Roland McGrathdaded342008-07-25 19:45:47 -0700213/**
214 * tracehook_report_vfork_done - vfork parent's child has exited or exec'd
215 * @child: child task, already running
216 * @pid: new child's PID in the parent's namespace
217 *
218 * Called after a %CLONE_VFORK parent has waited for the child to complete.
219 * The clone/vfork system call will return immediately after this.
220 * The @child pointer may be invalid if a self-reaping child died and
221 * tracehook_report_clone() took no action to prevent it from self-reaping.
222 *
223 * Called with no locks held.
224 */
225static inline void tracehook_report_vfork_done(struct task_struct *child,
226 pid_t pid)
227{
228 ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid);
229}
230
Roland McGrath88ac2922008-07-25 19:45:43 -0700231#endif /* <linux/tracehook.h> */