1 /*
2 * ko_adapt.c
3 *
4 * function for find symbols not exported
5 *
6 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17 #include "ko_adapt.h"
18 #include <linux/types.h>
19 #include <linux/mm_types.h>
20 #include <linux/stddef.h>
21 #include <linux/cred.h>
22 #include <linux/version.h>
23 #if (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
24 #include <linux/sched/task.h>
25 #endif
26 #include <linux/cpumask.h>
27 #include <linux/syscalls.h>
28 #include <linux/fs.h>
29 #include "tc_ns_log.h"
30
31 typedef const struct cred *(get_task_cred_func)(struct task_struct *);
32 typedef void (kthread_bind_mask_func)(struct task_struct *, const struct cpumask *);
33 typedef struct page *(alloc_pages_func)(gfp_t gfp_mask, unsigned int order);
34 typedef struct workqueue_attrs *(alloc_workqueue_attrs_func)(gfp_t gfp_mask);
35 typedef void (free_workqueue_attrs_func)(struct workqueue_attrs *attrs);
36
koadpt_get_task_cred(struct task_struct *task)37 const struct cred *koadpt_get_task_cred(struct task_struct *task)
38 {
39 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
40 return get_task_cred(task);
41 #else
42 static get_task_cred_func *get_task_cred_pt = NULL;
43
44 if (!task)
45 return NULL;
46
47 if (!get_task_cred_pt) {
48 get_task_cred_pt = (get_task_cred_func *)
49 (uintptr_t)kallsyms_lookup_name("get_task_cred");
50 if (IS_ERR_OR_NULL(get_task_cred_pt)) {
51 tloge("fail to find symbol get task cred\n");
52 return NULL;
53 }
54 }
55 return get_task_cred_pt(task);
56 #endif
57 }
58
koadpt_kthread_bind_mask(struct task_struct *task, const struct cpumask *mask)59 void koadpt_kthread_bind_mask(struct task_struct *task,
60 const struct cpumask *mask)
61 {
62 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
63 (void)set_cpus_allowed_ptr(task, mask);
64 #else
65 static kthread_bind_mask_func *kthread_bind_mask_pt = NULL;
66
67 if (!task || !mask)
68 return;
69
70 if (!kthread_bind_mask_pt) {
71 kthread_bind_mask_pt = (kthread_bind_mask_func *)
72 (uintptr_t)kallsyms_lookup_name("kthread_bind_mask");
73 if (IS_ERR_OR_NULL(kthread_bind_mask_pt)) {
74 tloge("fail to find symbol kthread bind mask\n");
75 return;
76 }
77 }
78 kthread_bind_mask_pt(task, mask);
79 #endif
80 }
81
koadpt_alloc_pages(gfp_t gfp_mask, unsigned int order)82 struct page *koadpt_alloc_pages(gfp_t gfp_mask, unsigned int order)
83 {
84 #ifdef CONFIG_NUMA
85 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
86 return alloc_pages(gfp_mask, order);
87 #else
88 static alloc_pages_func *alloc_pages_pt = NULL;
89
90 if (!alloc_pages_pt) {
91 alloc_pages_pt = (alloc_pages_func *)
92 (uintptr_t)kallsyms_lookup_name("alloc_pages_current");
93 if (IS_ERR_OR_NULL(alloc_pages_pt)) {
94 tloge("fail to find symbol alloc pages current\n");
95 return NULL;
96 }
97 }
98 return alloc_pages_pt(gfp_mask, order);
99 #endif
100 #else
101 return alloc_pages(gfp_mask, order);
102 #endif
103 }
104
koadpt_alloc_workqueue_attrs(gfp_t gfp_mask)105 struct workqueue_attrs *koadpt_alloc_workqueue_attrs(gfp_t gfp_mask)
106 {
107 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
108 struct workqueue_attrs *attrs;
109 (void)gfp_mask;
110
111 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
112 if (!attrs) {
113 tloge("alloc workqueue attr fail\n");
114 return NULL;
115 }
116
117 if (alloc_cpumask_var(&attrs->cpumask, GFP_KERNEL) == false) {
118 tloge("alloc cpumask var fail\n");
119 kfree(attrs);
120 return NULL;
121 }
122
123 cpumask_copy(attrs->cpumask, cpu_possible_mask);
124
125 return attrs;
126 #else
127 static alloc_workqueue_attrs_func *alloc_workqueue_attrs_pt = NULL;
128
129 if (!alloc_workqueue_attrs_pt) {
130 alloc_workqueue_attrs_pt = (alloc_workqueue_attrs_func *)
131 (uintptr_t)kallsyms_lookup_name("alloc_workqueue_attrs");
132 if (IS_ERR_OR_NULL(alloc_workqueue_attrs_pt)) {
133 tloge("fail to find symbol alloc workqueue attrs\n");
134 return NULL;
135 }
136 }
137 return alloc_workqueue_attrs_pt(gfp_mask);
138 #endif
139 }
140
koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs)141 void koadpt_free_workqueue_attrs(struct workqueue_attrs *attrs)
142 {
143 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
144 if (!attrs)
145 return;
146
147 free_cpumask_var(attrs->cpumask);
148 kfree(attrs);
149 #else
150 static free_workqueue_attrs_func *free_workqueue_attrs_pt = NULL;
151
152 if (!attrs)
153 return;
154
155 if (!free_workqueue_attrs_pt) {
156 free_workqueue_attrs_pt = (free_workqueue_attrs_func *)
157 (uintptr_t)kallsyms_lookup_name("free_workqueue_attrs");
158 if (IS_ERR_OR_NULL(free_workqueue_attrs_pt)) {
159 tloge("fail to find symbol free workqueue attrs\n");
160 return;
161 }
162 }
163 free_workqueue_attrs_pt(attrs);
164 #endif
165 }