• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
4  * OpenHarmony Common Kernel Vendor Hook Support
5  * Based on include/trace/hooks/lite_vendor_hooks.h
6  *
7  */
8 
9 #ifndef LITE_VENDOR_HOOK_H
10 #define LITE_VENDOR_HOOK_H
11 
12 #include <asm/bug.h>
13 #include <linux/slab.h>
14 #include <linux/spinlock.h>
15 #include <linux/rcupdate.h>
16 #include <linux/tracepoint.h>
17 #include <linux/module.h>
18 
19 struct __lvh_func {
20         void *func;
21         void *data;
22         bool has_data;
23 };
24 
25 struct lite_vendor_hook {
26         struct mutex mutex;
27         struct __lvh_func *funcs;
28 };
29 #endif // LITE_VENDOR_HOOK_H
30 
31 #ifdef CREATE_LITE_VENDOR_HOOK
32 
33 #define DEFINE_HCK_LITE_HOOK(name, proto, args) \
34         struct lite_vendor_hook __lvh_##name __used     \
35         __section("__vendor_hooks") = { \
36                 .mutex = __MUTEX_INITIALIZER(__lvh_##name.mutex),       \
37                 .funcs = NULL };        \
38         EXPORT_SYMBOL(__lvh_##name);    \
39         void lvh_probe_##name(proto) { return; }        \
40         void lvh_probe_data_##name(void *lvh_data, proto) { return; }
41 
42 #undef DECLARE_HCK_LITE_HOOK
43 #define DECLARE_HCK_LITE_HOOK(name, proto, args)        \
44         DEFINE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args))
45 
46 #else // #ifndef CREATE_LITE_VENDOR_HOOK
47 
48 #define REGISTER_HCK_LITE_HOOK(name, probe)     \
49         extern typeof(lvh_probe_##name) (probe);  \
50         do {    \
51                 if (register_lvh_##name(probe)) \
52                         WARN_ONCE(1, "LVH register failed!\n"); \
53         } while (0)
54 
55 #define REGISTER_HCK_LITE_DATA_HOOK(name, probe, data)  \
56         extern typeof(lvh_probe_data_##name) (probe);     \
57         do {    \
58                 if (register_lvh_data_##name(probe, data))      \
59                         WARN_ONCE(1, "LVH register failed!\n"); \
60         } while (0)
61 
62 #define CALL_HCK_LITE_HOOK(name, args...)       \
63         call_lvh_##name(args)
64 
65 #define __DECLARE_HCK_LITE_HOOK(name, proto, args)      \
66         extern struct lite_vendor_hook __lvh_##name;    \
67         extern void lvh_probe_##name(proto);    \
68         extern void lvh_probe_data_##name(void *lvh_data, proto);       \
69         static inline void      \
70         call_lvh_##name(proto)  \
71         {       \
72                 struct __lvh_func *funcs = (&__lvh_##name)->funcs;      \
73                 if (funcs && funcs->func) {     \
74                         if (funcs->has_data)    \
75                                 ((void(*)(void *, proto))funcs->func)(funcs->data, args);       \
76                         else    \
77                                 ((void(*)(proto))funcs->func)(args);    \
78                 }       \
79         }       \
80         static inline int       \
81         __register_lvh_##name(void *probe, void *data, bool has_data)   \
82         {       \
83                 int err = 0;    \
84                 struct __lvh_func *funcs;       \
85                 struct module *mod;     \
86                 mutex_lock(&__lvh_##name.mutex);        \
87                 funcs = (&__lvh_##name)->funcs; \
88                 if (funcs) {    \
89                         if (funcs->func != probe || funcs->data != data)        \
90                                 err = -EBUSY;   \
91                         goto out;       \
92                 }       \
93                 \
94                 funcs = (struct __lvh_func*)kmalloc(sizeof(struct __lvh_func), GFP_KERNEL);     \
95                 if (!funcs) {   \
96                         err = -ENOMEM;  \
97                         goto out;       \
98                 }       \
99                 \
100                 funcs->func = probe;    \
101                 funcs->data = data;     \
102                 funcs->has_data = has_data;     \
103                 mod = __module_address((uintptr_t)probe);       \
104                 if (mod)        \
105                         (void)try_module_get(mod);      \
106                 (&__lvh_##name)->funcs = funcs; \
107         out:    \
108                 mutex_unlock(&__lvh_##name.mutex);      \
109                 return err;     \
110         }       \
111         static inline int       \
112         register_lvh_##name(void (*probe)(proto))       \
113         {       \
114                 return __register_lvh_##name((void *)probe, NULL, false);       \
115         }       \
116         static inline int       \
117         register_lvh_data_##name(void (*probe)(void *lvh_data, proto), void *data)      \
118         {       \
119                 return __register_lvh_##name((void *)probe, data, true);        \
120         }
121 
122 #undef DECLARE_HCK_LITE_HOOK
123 #define DECLARE_HCK_LITE_HOOK(name, proto, args)        \
124         __DECLARE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args))
125 
126 #endif // CREATE_LITE_VENDOR_HOOK
127