diff options
-rw-r--r-- | drivers/connector/cn_proc.c | 35 | ||||
-rw-r--r-- | include/linux/cn_proc.h | 13 | ||||
-rw-r--r-- | kernel/ptrace.c | 7 |
3 files changed, 54 insertions, 1 deletions
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 2b46a7efa0ac..281902d3f7ec 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/connector.h> | 29 | #include <linux/connector.h> |
30 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/ptrace.h> | ||
31 | #include <asm/atomic.h> | 32 | #include <asm/atomic.h> |
32 | #include <asm/unaligned.h> | 33 | #include <asm/unaligned.h> |
33 | 34 | ||
@@ -166,6 +167,40 @@ void proc_sid_connector(struct task_struct *task) | |||
166 | cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); | 167 | cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); |
167 | } | 168 | } |
168 | 169 | ||
170 | void proc_ptrace_connector(struct task_struct *task, int ptrace_id) | ||
171 | { | ||
172 | struct cn_msg *msg; | ||
173 | struct proc_event *ev; | ||
174 | struct timespec ts; | ||
175 | __u8 buffer[CN_PROC_MSG_SIZE]; | ||
176 | struct task_struct *tracer; | ||
177 | |||
178 | if (atomic_read(&proc_event_num_listeners) < 1) | ||
179 | return; | ||
180 | |||
181 | msg = (struct cn_msg *)buffer; | ||
182 | ev = (struct proc_event *)msg->data; | ||
183 | get_seq(&msg->seq, &ev->cpu); | ||
184 | ktime_get_ts(&ts); /* get high res monotonic timestamp */ | ||
185 | put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); | ||
186 | ev->what = PROC_EVENT_PTRACE; | ||
187 | ev->event_data.ptrace.process_pid = task->pid; | ||
188 | ev->event_data.ptrace.process_tgid = task->tgid; | ||
189 | if (ptrace_id == PTRACE_ATTACH) { | ||
190 | ev->event_data.ptrace.tracer_pid = current->pid; | ||
191 | ev->event_data.ptrace.tracer_tgid = current->tgid; | ||
192 | } else if (ptrace_id == PTRACE_DETACH) { | ||
193 | ev->event_data.ptrace.tracer_pid = 0; | ||
194 | ev->event_data.ptrace.tracer_tgid = 0; | ||
195 | } else | ||
196 | return; | ||
197 | |||
198 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); | ||
199 | msg->ack = 0; /* not used */ | ||
200 | msg->len = sizeof(*ev); | ||
201 | cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); | ||
202 | } | ||
203 | |||
169 | void proc_exit_connector(struct task_struct *task) | 204 | void proc_exit_connector(struct task_struct *task) |
170 | { | 205 | { |
171 | struct cn_msg *msg; | 206 | struct cn_msg *msg; |
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h index 47dac5ea8d3a..12c517b51ca2 100644 --- a/include/linux/cn_proc.h +++ b/include/linux/cn_proc.h | |||
@@ -53,6 +53,7 @@ struct proc_event { | |||
53 | PROC_EVENT_UID = 0x00000004, | 53 | PROC_EVENT_UID = 0x00000004, |
54 | PROC_EVENT_GID = 0x00000040, | 54 | PROC_EVENT_GID = 0x00000040, |
55 | PROC_EVENT_SID = 0x00000080, | 55 | PROC_EVENT_SID = 0x00000080, |
56 | PROC_EVENT_PTRACE = 0x00000100, | ||
56 | /* "next" should be 0x00000400 */ | 57 | /* "next" should be 0x00000400 */ |
57 | /* "last" is the last process event: exit */ | 58 | /* "last" is the last process event: exit */ |
58 | PROC_EVENT_EXIT = 0x80000000 | 59 | PROC_EVENT_EXIT = 0x80000000 |
@@ -95,6 +96,13 @@ struct proc_event { | |||
95 | __kernel_pid_t process_tgid; | 96 | __kernel_pid_t process_tgid; |
96 | } sid; | 97 | } sid; |
97 | 98 | ||
99 | struct ptrace_proc_event { | ||
100 | __kernel_pid_t process_pid; | ||
101 | __kernel_pid_t process_tgid; | ||
102 | __kernel_pid_t tracer_pid; | ||
103 | __kernel_pid_t tracer_tgid; | ||
104 | } ptrace; | ||
105 | |||
98 | struct exit_proc_event { | 106 | struct exit_proc_event { |
99 | __kernel_pid_t process_pid; | 107 | __kernel_pid_t process_pid; |
100 | __kernel_pid_t process_tgid; | 108 | __kernel_pid_t process_tgid; |
@@ -109,6 +117,7 @@ void proc_fork_connector(struct task_struct *task); | |||
109 | void proc_exec_connector(struct task_struct *task); | 117 | void proc_exec_connector(struct task_struct *task); |
110 | void proc_id_connector(struct task_struct *task, int which_id); | 118 | void proc_id_connector(struct task_struct *task, int which_id); |
111 | void proc_sid_connector(struct task_struct *task); | 119 | void proc_sid_connector(struct task_struct *task); |
120 | void proc_ptrace_connector(struct task_struct *task, int which_id); | ||
112 | void proc_exit_connector(struct task_struct *task); | 121 | void proc_exit_connector(struct task_struct *task); |
113 | #else | 122 | #else |
114 | static inline void proc_fork_connector(struct task_struct *task) | 123 | static inline void proc_fork_connector(struct task_struct *task) |
@@ -124,6 +133,10 @@ static inline void proc_id_connector(struct task_struct *task, | |||
124 | static inline void proc_sid_connector(struct task_struct *task) | 133 | static inline void proc_sid_connector(struct task_struct *task) |
125 | {} | 134 | {} |
126 | 135 | ||
136 | static inline void proc_ptrace_connector(struct task_struct *task, | ||
137 | int ptrace_id) | ||
138 | {} | ||
139 | |||
127 | static inline void proc_exit_connector(struct task_struct *task) | 140 | static inline void proc_exit_connector(struct task_struct *task) |
128 | {} | 141 | {} |
129 | #endif /* CONFIG_PROC_EVENTS */ | 142 | #endif /* CONFIG_PROC_EVENTS */ |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index d7ccc79454f5..9de3ecfd20f9 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <linux/regset.h> | 24 | #include <linux/regset.h> |
25 | #include <linux/hw_breakpoint.h> | 25 | #include <linux/hw_breakpoint.h> |
26 | #include <linux/cn_proc.h> | ||
26 | 27 | ||
27 | 28 | ||
28 | static int ptrace_trapping_sleep_fn(void *flags) | 29 | static int ptrace_trapping_sleep_fn(void *flags) |
@@ -305,9 +306,12 @@ unlock_tasklist: | |||
305 | unlock_creds: | 306 | unlock_creds: |
306 | mutex_unlock(&task->signal->cred_guard_mutex); | 307 | mutex_unlock(&task->signal->cred_guard_mutex); |
307 | out: | 308 | out: |
308 | if (!retval) | 309 | if (!retval) { |
309 | wait_on_bit(&task->jobctl, JOBCTL_TRAPPING_BIT, | 310 | wait_on_bit(&task->jobctl, JOBCTL_TRAPPING_BIT, |
310 | ptrace_trapping_sleep_fn, TASK_UNINTERRUPTIBLE); | 311 | ptrace_trapping_sleep_fn, TASK_UNINTERRUPTIBLE); |
312 | proc_ptrace_connector(task, PTRACE_ATTACH); | ||
313 | } | ||
314 | |||
311 | return retval; | 315 | return retval; |
312 | } | 316 | } |
313 | 317 | ||
@@ -415,6 +419,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data) | |||
415 | } | 419 | } |
416 | write_unlock_irq(&tasklist_lock); | 420 | write_unlock_irq(&tasklist_lock); |
417 | 421 | ||
422 | proc_ptrace_connector(child, PTRACE_DETACH); | ||
418 | if (unlikely(dead)) | 423 | if (unlikely(dead)) |
419 | release_task(child); | 424 | release_task(child); |
420 | 425 | ||