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 20DEFINE_RWLOCK(token_rwlock); 21#define ACCESS_TOKEN_UID KUIDT_INIT(3020) 22#define MAX_NODE_NUM 500 23#define UINT32_T_BITS 32 24 25static struct kmem_cache *g_cache = NULL; 26static struct token_perm_node *g_token_perm_root = NULL; 27static size_t g_total_node_num = 0; 28 29int access_tokenid_get_tokenid(struct file *file, void __user *uarg) 30{ 31 return copy_to_user(uarg, ¤t->token, 32 sizeof(current->token)) ? -EFAULT : 0; 33} 34 35static 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 56int 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 70static 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 99int 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, ¤t->ftoken, 105 sizeof(current->ftoken)) ? -EFAULT : 0; 106} 107 108int 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 122static bool check_permission_for_set_token_permission() 123{ 124 kuid_t uid = current_uid(); 125 return uid_eq(uid, ACCESS_TOKEN_UID); 126} 127 128static 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 143static 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 163static 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 191static 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 223int 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 246int 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 264int 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 298int 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 325typedef int (*access_token_id_func)(struct file *file, void __user *arg); 326 327static 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 339static 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 368static 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 374static struct miscdevice access_tokenid_device = { 375 .minor = MISC_DYNAMIC_MINOR, 376 .name = "access_token_id", 377 .fops = &access_tokenid_fops, 378}; 379 380static 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 399static 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 */ 406module_init(access_tokenid_init_module); 407module_exit(access_tokenid_exit_module); 408