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_permission(void)122 static bool check_permission_for_set_token_permission(void)
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 	struct token_perm_node *target_node = NULL;
166 	struct token_perm_node *parent_node = NULL;
167 	find_node_by_token(root_node, node->perm_data.token, &target_node, &parent_node);
168 	if (target_node != NULL) {
169 		target_node->perm_data = node->perm_data;
170 		return 0;
171 	}
172 	if (g_total_node_num >= MAX_NODE_NUM) {
173 		pr_err("%s: the number of token nodes is exceeded.\n", __func__);
174 		return -EDQUOT;
175 	}
176 	if (parent_node == NULL) {
177 		g_token_perm_root = node;
178 	} else if (parent_node->perm_data.token > node->perm_data.token) {
179 		parent_node->left = node;
180 	} else {
181 		parent_node->right = node;
182 	}
183 	g_total_node_num++;
184 	return 1;
185 }
186 
remove_node_by_token(struct token_perm_node *root_node, uint32_t token)187 static struct token_perm_node *remove_node_by_token(struct token_perm_node *root_node, uint32_t token)
188 {
189 	struct token_perm_node *target_node = NULL;
190 	struct token_perm_node *parent_node = NULL;
191 	find_node_by_token(root_node, token, &target_node, &parent_node);
192 	if (target_node == NULL) {
193 		pr_err("%s: target token to be removed not found.\n", __func__);
194 		return NULL;
195 	}
196 
197 	struct token_perm_node **new_node_addr = NULL;
198 	if (parent_node == NULL) {
199 		new_node_addr = &root_node;
200 	} else if (parent_node->perm_data.token > token) {
201 		new_node_addr = &(parent_node->left);
202 	} else {
203 		new_node_addr = &(parent_node->right);
204 	}
205 	if (target_node->right != NULL) {
206 		*new_node_addr = target_node->right;
207 		add_node_to_left_tree_tail(target_node->right, target_node->left);
208 	} else {
209 		*new_node_addr = target_node->left;
210 	}
211 	g_total_node_num--;
212 	return target_node;
213 }
214 
access_tokenid_add_permission(struct file *file, void __user *uarg)215 int access_tokenid_add_permission(struct file *file, void __user *uarg)
216 {
217 	if (!check_permission_for_set_token_permission())
218 		return -EPERM;
219 
220 	struct token_perm_node *node = kmem_cache_zalloc(g_cache, GFP_KERNEL);
221 	if (node == NULL)
222 		return -ENOMEM;
223 	if (copy_from_user(&(node->perm_data), uarg, sizeof(ioctl_add_perm_data))) {
224 		kmem_cache_free(g_cache, node);
225 		return -EFAULT;
226 	}
227 
228 	write_lock(&token_rwlock);
229 	int ret = add_node_to_tree(g_token_perm_root, node);
230 	write_unlock(&token_rwlock);
231 	if (ret <= 0) {
232 		kmem_cache_free(g_cache, node);
233 		return ret;
234 	}
235 	return 0;
236 }
237 
access_tokenid_remove_permission(struct file *file, void __user *uarg)238 int access_tokenid_remove_permission(struct file *file, void __user *uarg)
239 {
240 	if (!check_permission_for_set_token_permission())
241 		return -EPERM;
242 
243 	uint32_t token = 0;
244 	if (copy_from_user(&token, uarg, sizeof(token)))
245 		return -EFAULT;
246 
247 	write_lock(&token_rwlock);
248 	struct token_perm_node *target_node = remove_node_by_token(g_token_perm_root, token);
249 	write_unlock(&token_rwlock);
250 
251 	if (target_node != NULL)
252 		kmem_cache_free(g_cache, target_node);
253 
254 	return 0;
255 }
256 
access_tokenid_set_permission(struct file *file, void __user *uarg)257 int access_tokenid_set_permission(struct file *file, void __user *uarg)
258 {
259 	if (!check_permission_for_set_token_permission())
260 		return -EPERM;
261 
262 	ioctl_set_get_perm_data set_perm_data;
263 	if (copy_from_user(&set_perm_data, uarg, sizeof(set_perm_data)))
264 		return -EFAULT;
265 
266 	uint32_t idx = set_perm_data.op_code / UINT32_T_BITS;
267 	if (idx >= MAX_PERM_GROUP_NUM) {
268 		pr_err("%s: invalid op_code.\n", __func__);
269 		return -EINVAL;
270 	}
271 
272 	struct token_perm_node *target_node = NULL;
273 	struct token_perm_node *parent_node = NULL;
274 	write_lock(&token_rwlock);
275 	find_node_by_token(g_token_perm_root, set_perm_data.token, &target_node, &parent_node);
276 	if (target_node == NULL) {
277 		write_unlock(&token_rwlock);
278 		pr_err("%s: token not found.\n", __func__);
279 		return -ENODATA;
280 	}
281 	uint32_t bit_idx = set_perm_data.op_code % UINT32_T_BITS;
282 	if (set_perm_data.is_granted) {
283 		target_node->perm_data.perm[idx] |= (uint32_t)0x01 << bit_idx;
284 	} else {
285 		target_node->perm_data.perm[idx] &= ~((uint32_t)0x01 << bit_idx);
286 	}
287 	write_unlock(&token_rwlock);
288 	return 0;
289 }
290 
access_tokenid_get_permission(struct file *file, void __user *uarg)291 int access_tokenid_get_permission(struct file *file, void __user *uarg)
292 {
293 	ioctl_set_get_perm_data get_perm_data;
294 	if (copy_from_user(&get_perm_data, uarg, sizeof(get_perm_data)))
295 		return -EFAULT;
296 
297 	uint32_t idx = get_perm_data.op_code / UINT32_T_BITS;
298 	if (idx >= MAX_PERM_GROUP_NUM) {
299 		pr_err("%s: invalid op_code.\n", __func__);
300 		return -EINVAL;
301 	}
302 
303 	struct token_perm_node *target_node = NULL;
304 	struct token_perm_node *parent_node = NULL;
305 	read_lock(&token_rwlock);
306 	find_node_by_token(g_token_perm_root, get_perm_data.token, &target_node, &parent_node);
307 	read_unlock(&token_rwlock);
308 	if (target_node == NULL)
309 		return -ENODATA;
310 
311 	uint32_t bit_idx = get_perm_data.op_code % UINT32_T_BITS;
312 	return (target_node->perm_data.perm[idx] & ((uint32_t)0x01 << bit_idx)) >> bit_idx;
313 }
314 
315 typedef int (*access_token_id_func)(struct file *file, void __user *arg);
316 
317 static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = {
318 	NULL, /* reserved */
319 	access_tokenid_get_tokenid,
320 	access_tokenid_set_tokenid,
321 	access_tokenid_get_ftokenid,
322 	access_tokenid_set_ftokenid,
323 	access_tokenid_add_permission,
324 	access_tokenid_remove_permission,
325 	access_tokenid_get_permission,
326 	access_tokenid_set_permission,
327 };
328 
access_tokenid_ioctl(struct file *file, unsigned int cmd, unsigned long arg)329 static long access_tokenid_ioctl(struct file *file, unsigned int cmd,
330 				 unsigned long arg)
331 {
332 	void __user *uarg = (void __user *)arg;
333 	unsigned int func_cmd = _IOC_NR(cmd);
334 
335 	if (uarg == NULL) {
336 		pr_err("%s: invalid user uarg\n", __func__);
337 		return -EINVAL;
338 	}
339 
340 	if (_IOC_TYPE(cmd) != ACCESS_TOKEN_ID_IOCTL_BASE) {
341 		pr_err("%s: access tokenid magic fail, TYPE=%d\n",
342 		       __func__, _IOC_TYPE(cmd));
343 		return -EINVAL;
344 	}
345 
346 	if (func_cmd >= ACCESS_TOKENID_MAX_NR) {
347 		pr_err("%s: access tokenid cmd error, cmd:%d\n",
348 			__func__, func_cmd);
349 		return -EINVAL;
350 	}
351 
352 	if (g_func_array[func_cmd])
353 		return (*g_func_array[func_cmd])(file, uarg);
354 
355 	return -EINVAL;
356 }
357 
358 static const struct file_operations access_tokenid_fops = {
359 	.owner		= THIS_MODULE,
360 	.unlocked_ioctl	= access_tokenid_ioctl,
361 	.compat_ioctl	= access_tokenid_ioctl,
362 };
363 
364 static struct miscdevice access_tokenid_device = {
365 	.minor	= MISC_DYNAMIC_MINOR,
366 	.name	= "access_token_id",
367 	.fops	= &access_tokenid_fops,
368 };
369 
access_tokenid_init_module(void)370 static int access_tokenid_init_module(void)
371 {
372 	int err;
373 
374 	err = misc_register(&access_tokenid_device);
375 	if (err < 0) {
376 		pr_err("access_tokenid register failed\n");
377 		return err;
378 	}
379 
380 	g_cache = kmem_cache_create("access_token_node", sizeof(struct token_perm_node), 0, SLAB_HWCACHE_ALIGN, NULL);
381 	if (g_cache == NULL) {
382 		pr_err("access_tokenid kmem_cache create failed\n");
383 		return -ENOMEM;
384 	}
385 	pr_info("access_tokenid init success\n");
386 	return 0;
387 }
388 
access_tokenid_exit_module(void)389 static void access_tokenid_exit_module(void)
390 {
391 	kmem_cache_destroy(g_cache);
392 	misc_deregister(&access_tokenid_device);
393 }
394 
395 /* module entry points */
396 module_init(access_tokenid_init_module);
397 module_exit(access_tokenid_exit_module);
398