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 }