diff options
Diffstat (limited to 'include/linux/tracehook.h')
-rw-r--r-- | include/linux/tracehook.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 967ab473afbc..3ebc58b59766 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -110,4 +110,104 @@ static inline void tracehook_report_exit(long *exit_code) | |||
110 | ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); | 110 | ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); |
111 | } | 111 | } |
112 | 112 | ||
113 | /** | ||
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 | */ | ||
122 | static 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 | */ | ||
150 | static 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 | */ | ||
174 | static 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 | */ | ||
203 | static 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 | |||
113 | #endif /* <linux/tracehook.h> */ | 213 | #endif /* <linux/tracehook.h> */ |