1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * access_tokenid.c
4  *
5  * Copyright (C) 2022-2023 Huawei Technologies Co., Ltd. All rights reserved.
6  *
7  */
8 
9 #define pr_fmt(fmt) "access_token_id: " fmt
10 
11 #include <linux/errno.h>
12 #include <linux/fs.h>
13 #include <linux/miscdevice.h>
14 #include <linux/module.h>
15 #include <linux/rwlock.h>
16 #include <linux/sched.h>
17 #include <linux/slab.h>
18 #include "access_tokenid.h"
19 
20 DEFINE_RWLOCK(token_rwlock);
21 #define ACCESS_TOKEN_UID KUIDT_INIT(3020)
22 #define MAX_NODE_NUM 500
23 #define UINT32_T_BITS 32
24 
25 static struct kmem_cache *g_cache = NULL;
26 static struct token_perm_node *g_token_perm_root = NULL;
27 static size_t g_total_node_num = 0;
28 
access_tokenid_get_tokenid(struct file *file, void __user *uarg)29 int access_tokenid_get_tokenid(struct file *file, void __user *uarg)
30 {
31 	return copy_to_user(uarg, &current->token,
32 			    sizeof(current->token)) ? -EFAULT : 0;
33 }
34 
check_permission_for_set_tokenid(struct file *file, unsigned long long tokenid)35 static bool check_permission_for_set_tokenid(struct file *file, unsigned long long tokenid)
36 {
37 	kuid_t uid = current_uid();
38 	struct inode *inode = file->f_inode;
39 	access_tokenid_inner *tokenid_inner = (access_tokenid_inner *)&tokenid;
40 
41 	if (inode == NULL) {
42 		pr_err("%s: file inode is null\n", __func__);
43 		return false;
44 	}
45 
46 	if (uid_eq(uid, GLOBAL_ROOT_UID) ||
47 	    uid_eq(uid, inode->i_uid)) {
48 		return true;
49 	} else if (uid_eq(uid, NWEBSPAWN_UID) && (tokenid_inner->render_flag == 1)) {
50 		return true;
51 	}
52 
53 	return false;
54 }
55 
access_tokenid_set_tokenid(struct file *file, void __user *uarg)56 int access_tokenid_set_tokenid(struct file *file, void __user *uarg)
57 {
58 	unsigned long long tmp = 0;
59 
60 	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
61 		return -EFAULT;
62 
63 	if (!check_permission_for_set_tokenid(file, tmp))
64 		return -EPERM;
65 
66 	current->token = tmp;
67 	return 0;
68 }
69 
check_permission_for_ftokenid(struct file *file)70 static bool check_permission_for_ftokenid(struct file *file)
71 {
72 	int i;
73 	struct group_info *group_info;
74 	kuid_t uid = current_uid();
75 	struct inode *inode = file->f_inode;
76 
77 	if (inode == NULL) {
78 		pr_err("%s: file inode is null\n", __func__);
79 		return false;
80 	}
81 
82 	if (uid_eq(uid, GLOBAL_ROOT_UID))
83 		return true;
84 
85 	group_info = get_current_groups();
86 	for (i = 0; i < group_info->ngroups; i++) {
87 		kgid_t gid = group_info->gid[i];
88 
89 		if (gid_eq(gid, inode->i_gid)) {
90 			put_group_info(group_info);
91 			return true;
92 		}
93 	}
94 
95 	put_group_info(group_info);
96 	return false;
97 }
98 
access_tokenid_get_ftokenid(struct file *file, void __user *uarg)99 int access_tokenid_get_ftokenid(struct file *file, void __user *uarg)
100 {
101 	if (!check_permission_for_ftokenid(file))
102 		return -EPERM;
103 
104 	return copy_to_user(uarg, &current->ftoken,
105 			    sizeof(current->ftoken)) ? -EFAULT : 0;
106 }
107 
access_tokenid_set_ftokenid(struct file *file, void __user *uarg)108 int access_tokenid_set_ftokenid(struct file *file, void __user *uarg)
109 {
110 	unsigned long long tmp = 0;
111 
112 	if (!check_permission_for_ftokenid(file))
113 		return -EPERM;
114 
115 	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
116 		return -EFAULT;
117 
118 	current->ftoken = tmp;
119 	return 0;
120 }
121 
check_permission_for_set_token_permissionnull122 static bool check_permission_for_set_token_permission()
123 {
124 	kuid_t uid = current_uid();
125 	return uid_eq(uid, ACCESS_TOKEN_UID);
126 }
127 
add_node_to_left_tree_tail(struct token_perm_node *root_node, struct token_perm_node *node)128 static void add_node_to_left_tree_tail(struct token_perm_node *root_node, struct token_perm_node *node)
129 {
130 	if ((root_node == NULL) || (node == NULL))
131 		return;
132 
133 	struct token_perm_node *current_node = root_node;
134 	while (true) {
135 		if (current_node->left == NULL) {
136 			current_node->left = node;
137 			break;
138 		}
139 		current_node = current_node->left;
140 	}
141 }
142 
find_node_by_token(struct token_perm_node *root_node, uint32_t token, struct token_perm_node **target_node, struct token_perm_node **parent_node)143 static void find_node_by_token(struct token_perm_node *root_node, uint32_t token,
144 	struct token_perm_node **target_node, struct token_perm_node **parent_node)
145 {
146 	*target_node = NULL;
147 	*parent_node = NULL;
148 	struct token_perm_node *current_node = root_node;
149 	while (current_node != NULL) {
150 		if (current_node->perm_data.token == token) {
151 			*target_node = current_node;
152 			break;
153 		}
154 		*parent_node = current_node;
155 		if (current_node->perm_data.token > token) {
156 			current_node = current_node->left;
157 		} else {
158 			current_node = current_node->right;
159 		}
160 	}
161 }
162 
add_node_to_tree(struct token_perm_node **root_node, struct token_perm_node *node)163 static int add_node_to_tree(struct token_perm_node **root_node, struct token_perm_node *node)
164 {
165 	if (root_node == NULL) {
166 		pr_err("%s: invalid root_node.\n", __func__);
167 		return -EINVAL;
168 	}
169 	struct token_perm_node *target_node = NULL;
170 	struct token_perm_node *parent_node = NULL;
171 	find_node_by_token(*root_node, node->perm_data.token, &target_node, &parent_node);
172 	if (target_node != NULL) {
173 		target_node->perm_data = node->perm_data;
174 		return 0;
175 	}
176 	if (g_total_node_num >= MAX_NODE_NUM) {
177 		pr_err("%s: the number of token nodes is exceeded.\n", __func__);
178 		return -EDQUOT;
179 	}
180 	if (parent_node == NULL) {
181 		*root_node = node;
182 	} else if (parent_node->perm_data.token > node->perm_data.token) {
183 		parent_node->left = node;
184 	} else {
185 		parent_node->right = node;
186 	}
187 	g_total_node_num++;
188 	return 1;
189 }
190 
remove_node_by_token(struct token_perm_node **root_node, uint32_t token)191 static struct token_perm_node *remove_node_by_token(struct token_perm_node **root_node, uint32_t token)
192 {
193 	if (root_node == NULL) {
194 		pr_err("%s: invalid root_node.\n", __func__);
195 		return NULL;
196 	}
197 	struct token_perm_node *target_node = NULL;
198 	struct token_perm_node *parent_node = NULL;
199 	find_node_by_token(*root_node, token, &target_node, &parent_node);
200 	if (target_node == NULL) {
201 		pr_err("%s: target token to be removed not found.\n", __func__);
202 		return NULL;
203 	}
204 
205 	struct token_perm_node **new_node_addr = NULL;
206 	if (parent_node == NULL) {
207 		new_node_addr = root_node;
208 	} else if (parent_node->perm_data.token > token) {
209 		new_node_addr = &(parent_node->left);
210 	} else {
211 		new_node_addr = &(parent_node->right);
212 	}
213 	if (target_node->right != NULL) {
214 		*new_node_addr = target_node->right;
215 		add_node_to_left_tree_tail(target_node->right, target_node->left);
216 	} else {
217 		*new_node_addr = target_node->left;
218 	}
219 	g_total_node_num--;
220 	return target_node;
221 }
222 
access_tokenid_add_permission(struct file *file, void __user *uarg)223 int access_tokenid_add_permission(struct file *file, void __user *uarg)
224 {
225 	if (!check_permission_for_set_token_permission())
226 		return -EPERM;
227 
228 	struct token_perm_node *node = kmem_cache_zalloc(g_cache, GFP_KERNEL);
229 	if (node == NULL)
230 		return -ENOMEM;
231 	if (copy_from_user(&(node->perm_data), uarg, sizeof(ioctl_add_perm_data))) {
232 		kmem_cache_free(g_cache, node);
233 		return -EFAULT;
234 	}
235 
236 	write_lock(&token_rwlock);
237 	int ret = add_node_to_tree(&g_token_perm_root, node);
238 	write_unlock(&token_rwlock);
239 	if (ret <= 0) {
240 		kmem_cache_free(g_cache, node);
241 		return ret;
242 	}
243 	return 0;
244 }
245 
access_tokenid_remove_permission(struct file *file, void __user *uarg)246 int access_tokenid_remove_permission(struct file *file, void __user *uarg)
247 {
248 	if (!check_permission_for_set_token_permission())
249 		return -EPERM;
250 
251 	uint32_t token = 0;
252 	if (copy_from_user(&token, uarg, sizeof(token)))
253 		return -EFAULT;
254 
255 	write_lock(&token_rwlock);
256 	struct token_perm_node *target_node = remove_node_by_token(&g_token_perm_root, token);
257 	if (target_node != NULL)
258 		kmem_cache_free(g_cache, target_node);
259 	write_unlock(&token_rwlock);
260 
261 	return 0;
262 }
263 
access_tokenid_set_permission(struct file *file, void __user *uarg)264 int access_tokenid_set_permission(struct file *file, void __user *uarg)
265 {
266 	if (!check_permission_for_set_token_permission())
267 		return -EPERM;
268 
269 	ioctl_set_get_perm_data set_perm_data;
270 	if (copy_from_user(&set_perm_data, uarg, sizeof(set_perm_data)))
271 		return -EFAULT;
272 
273 	uint32_t idx = set_perm_data.op_code / UINT32_T_BITS;
274 	if (idx >= MAX_PERM_GROUP_NUM) {
275 		pr_err("%s: invalid op_code.\n", __func__);
276 		return -EINVAL;
277 	}
278 
279 	struct token_perm_node *target_node = NULL;
280 	struct token_perm_node *parent_node = NULL;
281 	write_lock(&token_rwlock);
282 	find_node_by_token(g_token_perm_root, set_perm_data.token, &target_node, &parent_node);
283 	if (target_node == NULL) {
284 		write_unlock(&token_rwlock);
285 		pr_err("%s: token not found.\n", __func__);
286 		return -ENODATA;
287 	}
288 	uint32_t bit_idx = set_perm_data.op_code % UINT32_T_BITS;
289 	if (set_perm_data.is_granted) {
290 		target_node->perm_data.perm[idx] |= (uint32_t)0x01 << bit_idx;
291 	} else {
292 		target_node->perm_data.perm[idx] &= ~((uint32_t)0x01 << bit_idx);
293 	}
294 	write_unlock(&token_rwlock);
295 	return 0;
296 }
297 
access_tokenid_get_permission(struct file *file, void __user *uarg)298 int access_tokenid_get_permission(struct file *file, void __user *uarg)
299 {
300 	ioctl_set_get_perm_data get_perm_data;
301 	if (copy_from_user(&get_perm_data, uarg, sizeof(get_perm_data)))
302 		return -EFAULT;
303 
304 	uint32_t idx = get_perm_data.op_code / UINT32_T_BITS;
305 	if (idx >= MAX_PERM_GROUP_NUM) {
306 		pr_err("%s: invalid op_code.\n", __func__);
307 		return -EINVAL;
308 	}
309 
310 	struct token_perm_node *target_node = NULL;
311 	struct token_perm_node *parent_node = NULL;
312 	read_lock(&token_rwlock);
313 	find_node_by_token(g_token_perm_root, get_perm_data.token, &target_node, &parent_node);
314 	if (target_node == NULL) {
315 		read_unlock(&token_rwlock);
316 		return -ENODATA;
317 	}
318 
319 	uint32_t bit_idx = get_perm_data.op_code % UINT32_T_BITS;
320 	int ret = (target_node->perm_data.perm[idx] & ((uint32_t)0x01 << bit_idx)) >> bit_idx;
321 	read_unlock(&token_rwlock);
322 	return ret;
323 }
324 
325 typedef int (*access_token_id_func)(struct file *file, void __user *arg);
326 
327 static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = {
328 	NULL, /* reserved */
329 	access_tokenid_get_tokenid,
330 	access_tokenid_set_tokenid,
331 	access_tokenid_get_ftokenid,
332 	access_tokenid_set_ftokenid,
333 	access_tokenid_add_permission,
334 	access_tokenid_remove_permission,
335 	access_tokenid_get_permission,
336 	access_tokenid_set_permission,
337 };
338 
access_tokenid_ioctl(struct file *file, unsigned int cmd, unsigned long arg)339 static long access_tokenid_ioctl(struct file *file, unsigned int cmd,
340 				 unsigned long arg)
341 {
342 	void __user *uarg = (void __user *)arg;
343 	unsigned int func_cmd = _IOC_NR(cmd);
344 
345 	if (uarg == NULL) {
346 		pr_err("%s: invalid user uarg\n", __func__);
347 		return -EINVAL;
348 	}
349 
350 	if (_IOC_TYPE(cmd) != ACCESS_TOKEN_ID_IOCTL_BASE) {
351 		pr_err("%s: access tokenid magic fail, TYPE=%d\n",
352 		       __func__, _IOC_TYPE(cmd));
353 		return -EINVAL;
354 	}
355 
356 	if (func_cmd >= ACCESS_TOKENID_MAX_NR) {
357 		pr_err("%s: access tokenid cmd error, cmd:%d\n",
358 			__func__, func_cmd);
359 		return -EINVAL;
360 	}
361 
362 	if (g_func_array[func_cmd])
363 		return (*g_func_array[func_cmd])(file, uarg);
364 
365 	return -EINVAL;
366 }
367 
368 static const struct file_operations access_tokenid_fops = {
369 	.owner		= THIS_MODULE,
370 	.unlocked_ioctl	= access_tokenid_ioctl,
371 	.compat_ioctl	= access_tokenid_ioctl,
372 };
373 
374 static struct miscdevice access_tokenid_device = {
375 	.minor	= MISC_DYNAMIC_MINOR,
376 	.name	= "access_token_id",
377 	.fops	= &access_tokenid_fops,
378 };
379 
access_tokenid_init_module(void)380 static int access_tokenid_init_module(void)
381 {
382 	int err;
383 
384 	err = misc_register(&access_tokenid_device);
385 	if (err < 0) {
386 		pr_err("access_tokenid register failed\n");
387 		return err;
388 	}
389 
390 	g_cache = kmem_cache_create("access_token_node", sizeof(struct token_perm_node), 0, SLAB_HWCACHE_ALIGN, NULL);
391 	if (g_cache == NULL) {
392 		pr_err("access_tokenid kmem_cache create failed\n");
393 		return -ENOMEM;
394 	}
395 	pr_info("access_tokenid init success\n");
396 	return 0;
397 }
398 
access_tokenid_exit_module(void)399 static void access_tokenid_exit_module(void)
400 {
401 	kmem_cache_destroy(g_cache);
402 	misc_deregister(&access_tokenid_device);
403 }
404 
405 /* module entry points */
406 module_init(access_tokenid_init_module);
407 module_exit(access_tokenid_exit_module);
408