1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * cn_proc.c - process events connector |
4 | * |
5 | * Copyright (C) Matt Helsley, IBM Corp. 2005 |
6 | * Based on cn_fork.c by Guillaume Thouvenin <guillaume.thouvenin@bull.net> |
7 | * Original copyright notice follows: |
8 | * Copyright (C) 2005 BULL SA. |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/ktime.h> |
13 | #include <linux/init.h> |
14 | #include <linux/connector.h> |
15 | #include <linux/gfp.h> |
16 | #include <linux/ptrace.h> |
17 | #include <linux/atomic.h> |
18 | #include <linux/pid_namespace.h> |
19 | |
20 | #include <linux/cn_proc.h> |
21 | #include <linux/local_lock.h> |
22 | |
23 | /* |
24 | * Size of a cn_msg followed by a proc_event structure. Since the |
25 | * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we |
26 | * add one 4-byte word to the size here, and then start the actual |
27 | * cn_msg structure 4 bytes into the stack buffer. The result is that |
28 | * the immediately following proc_event structure is aligned to 8 bytes. |
29 | */ |
30 | #define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4) |
31 | |
32 | /* See comment above; we test our assumption about sizeof struct cn_msg here. */ |
33 | static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer) |
34 | { |
35 | BUILD_BUG_ON(sizeof(struct cn_msg) != 20); |
36 | return (struct cn_msg *)(buffer + 4); |
37 | } |
38 | |
39 | static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); |
40 | static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; |
41 | |
42 | /* local_event.count is used as the sequence number of the netlink message */ |
43 | struct local_event { |
44 | local_lock_t lock; |
45 | __u32 count; |
46 | }; |
47 | static DEFINE_PER_CPU(struct local_event, local_event) = { |
48 | .lock = INIT_LOCAL_LOCK(lock), |
49 | }; |
50 | |
51 | static int cn_filter(struct sock *dsk, struct sk_buff *skb, void *data) |
52 | { |
53 | __u32 what, exit_code, *ptr; |
54 | enum proc_cn_mcast_op mc_op; |
55 | uintptr_t val; |
56 | |
57 | if (!dsk || !dsk->sk_user_data || !data) |
58 | return 0; |
59 | |
60 | ptr = (__u32 *)data; |
61 | what = *ptr++; |
62 | exit_code = *ptr; |
63 | val = ((struct proc_input *)(dsk->sk_user_data))->event_type; |
64 | mc_op = ((struct proc_input *)(dsk->sk_user_data))->mcast_op; |
65 | |
66 | if (mc_op == PROC_CN_MCAST_IGNORE) |
67 | return 1; |
68 | |
69 | if ((__u32)val == PROC_EVENT_ALL) |
70 | return 0; |
71 | |
72 | /* |
73 | * Drop packet if we have to report only non-zero exit status |
74 | * (PROC_EVENT_NONZERO_EXIT) and exit status is 0 |
75 | */ |
76 | if (((__u32)val & PROC_EVENT_NONZERO_EXIT) && |
77 | (what == PROC_EVENT_EXIT)) { |
78 | if (exit_code) |
79 | return 0; |
80 | } |
81 | |
82 | if ((__u32)val & what) |
83 | return 0; |
84 | |
85 | return 1; |
86 | } |
87 | |
88 | static inline void send_msg(struct cn_msg *msg) |
89 | { |
90 | __u32 filter_data[2]; |
91 | |
92 | local_lock(&local_event.lock); |
93 | |
94 | msg->seq = __this_cpu_inc_return(local_event.count) - 1; |
95 | ((struct proc_event *)msg->data)->cpu = smp_processor_id(); |
96 | |
97 | /* |
98 | * local_lock() disables preemption during send to ensure the messages |
99 | * are ordered according to their sequence numbers. |
100 | * |
101 | * If cn_netlink_send() fails, the data is not sent. |
102 | */ |
103 | filter_data[0] = ((struct proc_event *)msg->data)->what; |
104 | if (filter_data[0] == PROC_EVENT_EXIT) { |
105 | filter_data[1] = |
106 | ((struct proc_event *)msg->data)->event_data.exit.exit_code; |
107 | } else { |
108 | filter_data[1] = 0; |
109 | } |
110 | |
111 | cn_netlink_send_mult(msg, len: msg->len, portid: 0, CN_IDX_PROC, GFP_NOWAIT, |
112 | filter: cn_filter, filter_data: (void *)filter_data); |
113 | |
114 | local_unlock(&local_event.lock); |
115 | } |
116 | |
117 | void proc_fork_connector(struct task_struct *task) |
118 | { |
119 | struct cn_msg *msg; |
120 | struct proc_event *ev; |
121 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
122 | struct task_struct *parent; |
123 | |
124 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
125 | return; |
126 | |
127 | msg = buffer_to_cn_msg(buffer); |
128 | ev = (struct proc_event *)msg->data; |
129 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
130 | ev->timestamp_ns = ktime_get_ns(); |
131 | ev->what = PROC_EVENT_FORK; |
132 | rcu_read_lock(); |
133 | parent = rcu_dereference(task->real_parent); |
134 | ev->event_data.fork.parent_pid = parent->pid; |
135 | ev->event_data.fork.parent_tgid = parent->tgid; |
136 | rcu_read_unlock(); |
137 | ev->event_data.fork.child_pid = task->pid; |
138 | ev->event_data.fork.child_tgid = task->tgid; |
139 | |
140 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
141 | msg->ack = 0; /* not used */ |
142 | msg->len = sizeof(*ev); |
143 | msg->flags = 0; /* not used */ |
144 | send_msg(msg); |
145 | } |
146 | |
147 | void proc_exec_connector(struct task_struct *task) |
148 | { |
149 | struct cn_msg *msg; |
150 | struct proc_event *ev; |
151 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
152 | |
153 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
154 | return; |
155 | |
156 | msg = buffer_to_cn_msg(buffer); |
157 | ev = (struct proc_event *)msg->data; |
158 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
159 | ev->timestamp_ns = ktime_get_ns(); |
160 | ev->what = PROC_EVENT_EXEC; |
161 | ev->event_data.exec.process_pid = task->pid; |
162 | ev->event_data.exec.process_tgid = task->tgid; |
163 | |
164 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
165 | msg->ack = 0; /* not used */ |
166 | msg->len = sizeof(*ev); |
167 | msg->flags = 0; /* not used */ |
168 | send_msg(msg); |
169 | } |
170 | |
171 | void proc_id_connector(struct task_struct *task, int which_id) |
172 | { |
173 | struct cn_msg *msg; |
174 | struct proc_event *ev; |
175 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
176 | const struct cred *cred; |
177 | |
178 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
179 | return; |
180 | |
181 | msg = buffer_to_cn_msg(buffer); |
182 | ev = (struct proc_event *)msg->data; |
183 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
184 | ev->what = which_id; |
185 | ev->event_data.id.process_pid = task->pid; |
186 | ev->event_data.id.process_tgid = task->tgid; |
187 | rcu_read_lock(); |
188 | cred = __task_cred(task); |
189 | if (which_id == PROC_EVENT_UID) { |
190 | ev->event_data.id.r.ruid = from_kuid_munged(to: &init_user_ns, uid: cred->uid); |
191 | ev->event_data.id.e.euid = from_kuid_munged(to: &init_user_ns, uid: cred->euid); |
192 | } else if (which_id == PROC_EVENT_GID) { |
193 | ev->event_data.id.r.rgid = from_kgid_munged(to: &init_user_ns, gid: cred->gid); |
194 | ev->event_data.id.e.egid = from_kgid_munged(to: &init_user_ns, gid: cred->egid); |
195 | } else { |
196 | rcu_read_unlock(); |
197 | return; |
198 | } |
199 | rcu_read_unlock(); |
200 | ev->timestamp_ns = ktime_get_ns(); |
201 | |
202 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
203 | msg->ack = 0; /* not used */ |
204 | msg->len = sizeof(*ev); |
205 | msg->flags = 0; /* not used */ |
206 | send_msg(msg); |
207 | } |
208 | |
209 | void proc_sid_connector(struct task_struct *task) |
210 | { |
211 | struct cn_msg *msg; |
212 | struct proc_event *ev; |
213 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
214 | |
215 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
216 | return; |
217 | |
218 | msg = buffer_to_cn_msg(buffer); |
219 | ev = (struct proc_event *)msg->data; |
220 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
221 | ev->timestamp_ns = ktime_get_ns(); |
222 | ev->what = PROC_EVENT_SID; |
223 | ev->event_data.sid.process_pid = task->pid; |
224 | ev->event_data.sid.process_tgid = task->tgid; |
225 | |
226 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
227 | msg->ack = 0; /* not used */ |
228 | msg->len = sizeof(*ev); |
229 | msg->flags = 0; /* not used */ |
230 | send_msg(msg); |
231 | } |
232 | |
233 | void proc_ptrace_connector(struct task_struct *task, int ptrace_id) |
234 | { |
235 | struct cn_msg *msg; |
236 | struct proc_event *ev; |
237 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
238 | |
239 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
240 | return; |
241 | |
242 | msg = buffer_to_cn_msg(buffer); |
243 | ev = (struct proc_event *)msg->data; |
244 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
245 | ev->timestamp_ns = ktime_get_ns(); |
246 | ev->what = PROC_EVENT_PTRACE; |
247 | ev->event_data.ptrace.process_pid = task->pid; |
248 | ev->event_data.ptrace.process_tgid = task->tgid; |
249 | if (ptrace_id == PTRACE_ATTACH) { |
250 | ev->event_data.ptrace.tracer_pid = current->pid; |
251 | ev->event_data.ptrace.tracer_tgid = current->tgid; |
252 | } else if (ptrace_id == PTRACE_DETACH) { |
253 | ev->event_data.ptrace.tracer_pid = 0; |
254 | ev->event_data.ptrace.tracer_tgid = 0; |
255 | } else |
256 | return; |
257 | |
258 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
259 | msg->ack = 0; /* not used */ |
260 | msg->len = sizeof(*ev); |
261 | msg->flags = 0; /* not used */ |
262 | send_msg(msg); |
263 | } |
264 | |
265 | void proc_comm_connector(struct task_struct *task) |
266 | { |
267 | struct cn_msg *msg; |
268 | struct proc_event *ev; |
269 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
270 | |
271 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
272 | return; |
273 | |
274 | msg = buffer_to_cn_msg(buffer); |
275 | ev = (struct proc_event *)msg->data; |
276 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
277 | ev->timestamp_ns = ktime_get_ns(); |
278 | ev->what = PROC_EVENT_COMM; |
279 | ev->event_data.comm.process_pid = task->pid; |
280 | ev->event_data.comm.process_tgid = task->tgid; |
281 | get_task_comm(ev->event_data.comm.comm, task); |
282 | |
283 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
284 | msg->ack = 0; /* not used */ |
285 | msg->len = sizeof(*ev); |
286 | msg->flags = 0; /* not used */ |
287 | send_msg(msg); |
288 | } |
289 | |
290 | void proc_coredump_connector(struct task_struct *task) |
291 | { |
292 | struct cn_msg *msg; |
293 | struct proc_event *ev; |
294 | struct task_struct *parent; |
295 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
296 | |
297 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
298 | return; |
299 | |
300 | msg = buffer_to_cn_msg(buffer); |
301 | ev = (struct proc_event *)msg->data; |
302 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
303 | ev->timestamp_ns = ktime_get_ns(); |
304 | ev->what = PROC_EVENT_COREDUMP; |
305 | ev->event_data.coredump.process_pid = task->pid; |
306 | ev->event_data.coredump.process_tgid = task->tgid; |
307 | |
308 | rcu_read_lock(); |
309 | if (pid_alive(p: task)) { |
310 | parent = rcu_dereference(task->real_parent); |
311 | ev->event_data.coredump.parent_pid = parent->pid; |
312 | ev->event_data.coredump.parent_tgid = parent->tgid; |
313 | } |
314 | rcu_read_unlock(); |
315 | |
316 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
317 | msg->ack = 0; /* not used */ |
318 | msg->len = sizeof(*ev); |
319 | msg->flags = 0; /* not used */ |
320 | send_msg(msg); |
321 | } |
322 | |
323 | void proc_exit_connector(struct task_struct *task) |
324 | { |
325 | struct cn_msg *msg; |
326 | struct proc_event *ev; |
327 | struct task_struct *parent; |
328 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
329 | |
330 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
331 | return; |
332 | |
333 | msg = buffer_to_cn_msg(buffer); |
334 | ev = (struct proc_event *)msg->data; |
335 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
336 | ev->timestamp_ns = ktime_get_ns(); |
337 | ev->what = PROC_EVENT_EXIT; |
338 | ev->event_data.exit.process_pid = task->pid; |
339 | ev->event_data.exit.process_tgid = task->tgid; |
340 | ev->event_data.exit.exit_code = task->exit_code; |
341 | ev->event_data.exit.exit_signal = task->exit_signal; |
342 | |
343 | rcu_read_lock(); |
344 | if (pid_alive(p: task)) { |
345 | parent = rcu_dereference(task->real_parent); |
346 | ev->event_data.exit.parent_pid = parent->pid; |
347 | ev->event_data.exit.parent_tgid = parent->tgid; |
348 | } |
349 | rcu_read_unlock(); |
350 | |
351 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
352 | msg->ack = 0; /* not used */ |
353 | msg->len = sizeof(*ev); |
354 | msg->flags = 0; /* not used */ |
355 | send_msg(msg); |
356 | } |
357 | |
358 | /* |
359 | * Send an acknowledgement message to userspace |
360 | * |
361 | * Use 0 for success, EFOO otherwise. |
362 | * Note: this is the negative of conventional kernel error |
363 | * values because it's not being returned via syscall return |
364 | * mechanisms. |
365 | */ |
366 | static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) |
367 | { |
368 | struct cn_msg *msg; |
369 | struct proc_event *ev; |
370 | __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); |
371 | |
372 | if (atomic_read(v: &proc_event_num_listeners) < 1) |
373 | return; |
374 | |
375 | msg = buffer_to_cn_msg(buffer); |
376 | ev = (struct proc_event *)msg->data; |
377 | memset(&ev->event_data, 0, sizeof(ev->event_data)); |
378 | msg->seq = rcvd_seq; |
379 | ev->timestamp_ns = ktime_get_ns(); |
380 | ev->cpu = -1; |
381 | ev->what = PROC_EVENT_NONE; |
382 | ev->event_data.ack.err = err; |
383 | memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); |
384 | msg->ack = rcvd_ack + 1; |
385 | msg->len = sizeof(*ev); |
386 | msg->flags = 0; /* not used */ |
387 | send_msg(msg); |
388 | } |
389 | |
390 | /** |
391 | * cn_proc_mcast_ctl |
392 | * @msg: message sent from userspace via the connector |
393 | * @nsp: NETLINK_CB of the client's socket buffer |
394 | */ |
395 | static void cn_proc_mcast_ctl(struct cn_msg *msg, |
396 | struct netlink_skb_parms *nsp) |
397 | { |
398 | enum proc_cn_mcast_op mc_op = 0, prev_mc_op = 0; |
399 | struct proc_input *pinput = NULL; |
400 | enum proc_cn_event ev_type = 0; |
401 | int err = 0, initial = 0; |
402 | struct sock *sk = NULL; |
403 | |
404 | /* |
405 | * Events are reported with respect to the initial pid |
406 | * and user namespaces so ignore requestors from |
407 | * other namespaces. |
408 | */ |
409 | if ((current_user_ns() != &init_user_ns) || |
410 | !task_is_in_init_pid_ns(current)) |
411 | return; |
412 | |
413 | if (msg->len == sizeof(*pinput)) { |
414 | pinput = (struct proc_input *)msg->data; |
415 | mc_op = pinput->mcast_op; |
416 | ev_type = pinput->event_type; |
417 | } else if (msg->len == sizeof(mc_op)) { |
418 | mc_op = *((enum proc_cn_mcast_op *)msg->data); |
419 | ev_type = PROC_EVENT_ALL; |
420 | } else { |
421 | return; |
422 | } |
423 | |
424 | ev_type = valid_event(ev_type: (enum proc_cn_event)ev_type); |
425 | |
426 | if (ev_type == PROC_EVENT_NONE) |
427 | ev_type = PROC_EVENT_ALL; |
428 | |
429 | if (nsp->sk) { |
430 | sk = nsp->sk; |
431 | if (sk->sk_user_data == NULL) { |
432 | sk->sk_user_data = kzalloc(size: sizeof(struct proc_input), |
433 | GFP_KERNEL); |
434 | if (sk->sk_user_data == NULL) { |
435 | err = ENOMEM; |
436 | goto out; |
437 | } |
438 | initial = 1; |
439 | } else { |
440 | prev_mc_op = |
441 | ((struct proc_input *)(sk->sk_user_data))->mcast_op; |
442 | } |
443 | ((struct proc_input *)(sk->sk_user_data))->event_type = |
444 | ev_type; |
445 | ((struct proc_input *)(sk->sk_user_data))->mcast_op = mc_op; |
446 | } |
447 | |
448 | switch (mc_op) { |
449 | case PROC_CN_MCAST_LISTEN: |
450 | if (initial || (prev_mc_op != PROC_CN_MCAST_LISTEN)) |
451 | atomic_inc(v: &proc_event_num_listeners); |
452 | break; |
453 | case PROC_CN_MCAST_IGNORE: |
454 | if (!initial && (prev_mc_op != PROC_CN_MCAST_IGNORE)) |
455 | atomic_dec(v: &proc_event_num_listeners); |
456 | ((struct proc_input *)(sk->sk_user_data))->event_type = |
457 | PROC_EVENT_NONE; |
458 | break; |
459 | default: |
460 | err = EINVAL; |
461 | break; |
462 | } |
463 | |
464 | out: |
465 | cn_proc_ack(err, rcvd_seq: msg->seq, rcvd_ack: msg->ack); |
466 | } |
467 | |
468 | /* |
469 | * cn_proc_init - initialization entry point |
470 | * |
471 | * Adds the connector callback to the connector driver. |
472 | */ |
473 | static int __init cn_proc_init(void) |
474 | { |
475 | int err = cn_add_callback(id: &cn_proc_event_id, |
476 | name: "cn_proc" , |
477 | callback: &cn_proc_mcast_ctl); |
478 | if (err) { |
479 | pr_warn("cn_proc failed to register\n" ); |
480 | return err; |
481 | } |
482 | return 0; |
483 | } |
484 | device_initcall(cn_proc_init); |
485 | |