1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2022, Microsoft Corporation.
4  *
5  * Authors:
6  *   Beau Belgrave <beaub@linux.microsoft.com>
7  */
8 
9 #ifndef _LINUX_USER_EVENTS_H
10 #define _LINUX_USER_EVENTS_H
11 
12 #include <linux/list.h>
13 #include <linux/refcount.h>
14 #include <linux/mm_types.h>
15 #include <linux/workqueue.h>
16 #include <uapi/linux/user_events.h>
17 
18 #ifdef CONFIG_USER_EVENTS
19 struct user_event_mm {
20 	struct list_head	mms_link;
21 	struct list_head	enablers;
22 	struct mm_struct	*mm;
23 	/* Used for one-shot lists, protected by event_mutex */
24 	struct user_event_mm	*next;
25 	refcount_t		refcnt;
26 	refcount_t		tasks;
27 	struct rcu_work		put_rwork;
28 };
29 
30 extern void user_event_mm_dup(struct task_struct *t,
31 			      struct user_event_mm *old_mm);
32 
33 extern void user_event_mm_remove(struct task_struct *t);
34 
user_events_fork(struct task_struct * t,unsigned long clone_flags)35 static inline void user_events_fork(struct task_struct *t,
36 				    unsigned long clone_flags)
37 {
38 	struct user_event_mm *old_mm;
39 
40 	if (!t || !current->user_event_mm)
41 		return;
42 
43 	old_mm = current->user_event_mm;
44 
45 	if (clone_flags & CLONE_VM) {
46 		t->user_event_mm = old_mm;
47 		refcount_inc(&old_mm->tasks);
48 		return;
49 	}
50 
51 	user_event_mm_dup(t, old_mm);
52 }
53 
user_events_execve(struct task_struct * t)54 static inline void user_events_execve(struct task_struct *t)
55 {
56 	if (!t || !t->user_event_mm)
57 		return;
58 
59 	user_event_mm_remove(t);
60 }
61 
user_events_exit(struct task_struct * t)62 static inline void user_events_exit(struct task_struct *t)
63 {
64 	if (!t || !t->user_event_mm)
65 		return;
66 
67 	user_event_mm_remove(t);
68 }
69 #else
user_events_fork(struct task_struct * t,unsigned long clone_flags)70 static inline void user_events_fork(struct task_struct *t,
71 				    unsigned long clone_flags)
72 {
73 }
74 
user_events_execve(struct task_struct * t)75 static inline void user_events_execve(struct task_struct *t)
76 {
77 }
78 
user_events_exit(struct task_struct * t)79 static inline void user_events_exit(struct task_struct *t)
80 {
81 }
82 #endif /* CONFIG_USER_EVENTS */
83 
84 #endif /* _LINUX_USER_EVENTS_H */
85