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
19struct 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
30extern void user_event_mm_dup(struct task_struct *t,
31			      struct user_event_mm *old_mm);
32
33extern void user_event_mm_remove(struct task_struct *t);
34
35static 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
54static 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
62static 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
70static inline void user_events_fork(struct task_struct *t,
71				    unsigned long clone_flags)
72{
73}
74
75static inline void user_events_execve(struct task_struct *t)
76{
77}
78
79static inline void user_events_exit(struct task_struct *t)
80{
81}
82#endif /* CONFIG_USER_EVENTS */
83
84#endif /* _LINUX_USER_EVENTS_H */
85