aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/ptrace.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/ptrace.h')
-rw-r--r--include/linux/ptrace.h104
1 files changed, 73 insertions, 31 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 9178d5cc0b01..800f113bea66 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -47,6 +47,13 @@
47#define PTRACE_GETREGSET 0x4204 47#define PTRACE_GETREGSET 0x4204
48#define PTRACE_SETREGSET 0x4205 48#define PTRACE_SETREGSET 0x4205
49 49
50#define PTRACE_SEIZE 0x4206
51#define PTRACE_INTERRUPT 0x4207
52#define PTRACE_LISTEN 0x4208
53
54/* flags in @data for PTRACE_SEIZE */
55#define PTRACE_SEIZE_DEVEL 0x80000000 /* temp flag for development */
56
50/* options set using PTRACE_SETOPTIONS */ 57/* options set using PTRACE_SETOPTIONS */
51#define PTRACE_O_TRACESYSGOOD 0x00000001 58#define PTRACE_O_TRACESYSGOOD 0x00000001
52#define PTRACE_O_TRACEFORK 0x00000002 59#define PTRACE_O_TRACEFORK 0x00000002
@@ -65,6 +72,7 @@
65#define PTRACE_EVENT_EXEC 4 72#define PTRACE_EVENT_EXEC 4
66#define PTRACE_EVENT_VFORK_DONE 5 73#define PTRACE_EVENT_VFORK_DONE 5
67#define PTRACE_EVENT_EXIT 6 74#define PTRACE_EVENT_EXIT 6
75#define PTRACE_EVENT_STOP 7
68 76
69#include <asm/ptrace.h> 77#include <asm/ptrace.h>
70 78
@@ -77,16 +85,22 @@
77 * flags. When the a task is stopped the ptracer owns task->ptrace. 85 * flags. When the a task is stopped the ptracer owns task->ptrace.
78 */ 86 */
79 87
88#define PT_SEIZED 0x00010000 /* SEIZE used, enable new behavior */
80#define PT_PTRACED 0x00000001 89#define PT_PTRACED 0x00000001
81#define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ 90#define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */
82#define PT_TRACESYSGOOD 0x00000004 91#define PT_TRACESYSGOOD 0x00000004
83#define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ 92#define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */
84#define PT_TRACE_FORK 0x00000010 93
85#define PT_TRACE_VFORK 0x00000020 94/* PT_TRACE_* event enable flags */
86#define PT_TRACE_CLONE 0x00000040 95#define PT_EVENT_FLAG_SHIFT 4
87#define PT_TRACE_EXEC 0x00000080 96#define PT_EVENT_FLAG(event) (1 << (PT_EVENT_FLAG_SHIFT + (event) - 1))
88#define PT_TRACE_VFORK_DONE 0x00000100 97
89#define PT_TRACE_EXIT 0x00000200 98#define PT_TRACE_FORK PT_EVENT_FLAG(PTRACE_EVENT_FORK)
99#define PT_TRACE_VFORK PT_EVENT_FLAG(PTRACE_EVENT_VFORK)
100#define PT_TRACE_CLONE PT_EVENT_FLAG(PTRACE_EVENT_CLONE)
101#define PT_TRACE_EXEC PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
102#define PT_TRACE_VFORK_DONE PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
103#define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
90 104
91#define PT_TRACE_MASK 0x000003f4 105#define PT_TRACE_MASK 0x000003f4
92 106
@@ -105,7 +119,7 @@ extern long arch_ptrace(struct task_struct *child, long request,
105extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); 119extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
106extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); 120extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
107extern void ptrace_disable(struct task_struct *); 121extern void ptrace_disable(struct task_struct *);
108extern int ptrace_check_attach(struct task_struct *task, int kill); 122extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
109extern int ptrace_request(struct task_struct *child, long request, 123extern int ptrace_request(struct task_struct *child, long request,
110 unsigned long addr, unsigned long data); 124 unsigned long addr, unsigned long data);
111extern void ptrace_notify(int exit_code); 125extern void ptrace_notify(int exit_code);
@@ -122,7 +136,7 @@ extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
122 136
123static inline int ptrace_reparented(struct task_struct *child) 137static inline int ptrace_reparented(struct task_struct *child)
124{ 138{
125 return child->real_parent != child->parent; 139 return !same_thread_group(child->real_parent, child->parent);
126} 140}
127 141
128static inline void ptrace_unlink(struct task_struct *child) 142static inline void ptrace_unlink(struct task_struct *child)
@@ -137,36 +151,56 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
137 unsigned long data); 151 unsigned long data);
138 152
139/** 153/**
140 * task_ptrace - return %PT_* flags that apply to a task 154 * ptrace_parent - return the task that is tracing the given task
141 * @task: pointer to &task_struct in question 155 * @task: task to consider
142 * 156 *
143 * Returns the %PT_* flags that apply to @task. 157 * Returns %NULL if no one is tracing @task, or the &struct task_struct
158 * pointer to its tracer.
159 *
160 * Must called under rcu_read_lock(). The pointer returned might be kept
161 * live only by RCU. During exec, this may be called with task_lock() held
162 * on @task, still held from when check_unsafe_exec() was called.
144 */ 163 */
145static inline int task_ptrace(struct task_struct *task) 164static inline struct task_struct *ptrace_parent(struct task_struct *task)
146{ 165{
147 return task->ptrace; 166 if (unlikely(task->ptrace))
167 return rcu_dereference(task->parent);
168 return NULL;
169}
170
171/**
172 * ptrace_event_enabled - test whether a ptrace event is enabled
173 * @task: ptracee of interest
174 * @event: %PTRACE_EVENT_* to test
175 *
176 * Test whether @event is enabled for ptracee @task.
177 *
178 * Returns %true if @event is enabled, %false otherwise.
179 */
180static inline bool ptrace_event_enabled(struct task_struct *task, int event)
181{
182 return task->ptrace & PT_EVENT_FLAG(event);
148} 183}
149 184
150/** 185/**
151 * ptrace_event - possibly stop for a ptrace event notification 186 * ptrace_event - possibly stop for a ptrace event notification
152 * @mask: %PT_* bit to check in @current->ptrace 187 * @event: %PTRACE_EVENT_* value to report
153 * @event: %PTRACE_EVENT_* value to report if @mask is set
154 * @message: value for %PTRACE_GETEVENTMSG to return 188 * @message: value for %PTRACE_GETEVENTMSG to return
155 * 189 *
156 * This checks the @mask bit to see if ptrace wants stops for this event. 190 * Check whether @event is enabled and, if so, report @event and @message
157 * If so we stop, reporting @event and @message to the ptrace parent. 191 * to the ptrace parent.
158 *
159 * Returns nonzero if we did a ptrace notification, zero if not.
160 * 192 *
161 * Called without locks. 193 * Called without locks.
162 */ 194 */
163static inline int ptrace_event(int mask, int event, unsigned long message) 195static inline void ptrace_event(int event, unsigned long message)
164{ 196{
165 if (mask && likely(!(current->ptrace & mask))) 197 if (unlikely(ptrace_event_enabled(current, event))) {
166 return 0; 198 current->ptrace_message = message;
167 current->ptrace_message = message; 199 ptrace_notify((event << 8) | SIGTRAP);
168 ptrace_notify((event << 8) | SIGTRAP); 200 } else if (event == PTRACE_EVENT_EXEC && unlikely(current->ptrace)) {
169 return 1; 201 /* legacy EXEC report via SIGTRAP */
202 send_sig(SIGTRAP, current, 0);
203 }
170} 204}
171 205
172/** 206/**
@@ -183,16 +217,24 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
183{ 217{
184 INIT_LIST_HEAD(&child->ptrace_entry); 218 INIT_LIST_HEAD(&child->ptrace_entry);
185 INIT_LIST_HEAD(&child->ptraced); 219 INIT_LIST_HEAD(&child->ptraced);
186 child->parent = child->real_parent; 220#ifdef CONFIG_HAVE_HW_BREAKPOINT
221 atomic_set(&child->ptrace_bp_refcnt, 1);
222#endif
223 child->jobctl = 0;
187 child->ptrace = 0; 224 child->ptrace = 0;
188 if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { 225 child->parent = child->real_parent;
226
227 if (unlikely(ptrace) && current->ptrace) {
189 child->ptrace = current->ptrace; 228 child->ptrace = current->ptrace;
190 __ptrace_link(child, current->parent); 229 __ptrace_link(child, current->parent);
191 }
192 230
193#ifdef CONFIG_HAVE_HW_BREAKPOINT 231 if (child->ptrace & PT_SEIZED)
194 atomic_set(&child->ptrace_bp_refcnt, 1); 232 task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
195#endif 233 else
234 sigaddset(&child->pending.signal, SIGSTOP);
235
236 set_tsk_thread_flag(child, TIF_SIGPENDING);
237 }
196} 238}
197 239
198/** 240/**