• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * access_tokenid.c
4  *
5  * Copyright (C) 2022 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/sched.h>
16 #include "access_tokenid.h"
17 
access_tokenid_get_tokenid(struct file * file,void __user * uarg)18 int access_tokenid_get_tokenid(struct file *file, void __user *uarg)
19 {
20 	return copy_to_user(uarg, &current->token,
21 			    sizeof(current->token)) ? -EFAULT : 0;
22 }
23 
check_permission_for_set_tokenid(struct file * file,unsigned long long tokenid)24 static bool check_permission_for_set_tokenid(struct file *file, unsigned long long tokenid)
25 {
26 	kuid_t uid = current_uid();
27 	struct inode *inode = file->f_inode;
28 	access_tokenid_inner *tokenid_inner = (access_tokenid_inner *)&tokenid;
29 
30 	if (inode == NULL) {
31 		pr_err("%s: file inode is null\n", __func__);
32 		return false;
33 	}
34 
35 	if (uid_eq(uid, GLOBAL_ROOT_UID) ||
36 	    uid_eq(uid, inode->i_uid)) {
37 		return true;
38 	} else if (uid_eq(uid, NWEBSPAWN_UID) && (tokenid_inner->render_flag == 1)) {
39 		return true;
40 	}
41 
42 	return false;
43 }
44 
access_tokenid_set_tokenid(struct file * file,void __user * uarg)45 int access_tokenid_set_tokenid(struct file *file, void __user *uarg)
46 {
47 	unsigned long long tmp = 0;
48 
49 	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
50 		return -EFAULT;
51 
52 	if (!check_permission_for_set_tokenid(file, tmp))
53 		return -EPERM;
54 
55 	current->token = tmp;
56 	return 0;
57 }
58 
check_permission_for_ftokenid(struct file * file)59 static bool check_permission_for_ftokenid(struct file *file)
60 {
61 	int i;
62 	struct group_info *group_info;
63 	kuid_t uid = current_uid();
64 	struct inode *inode = file->f_inode;
65 
66 	if (inode == NULL) {
67 		pr_err("%s: file inode is null\n", __func__);
68 		return false;
69 	}
70 
71 	if (uid_eq(uid, GLOBAL_ROOT_UID))
72 		return true;
73 
74 	group_info = get_current_groups();
75 	for (i = 0; i < group_info->ngroups; i++) {
76 		kgid_t gid = group_info->gid[i];
77 
78 		if (gid_eq(gid, inode->i_gid)) {
79 			put_group_info(group_info);
80 			return true;
81 		}
82 	}
83 
84 	put_group_info(group_info);
85 	return false;
86 }
87 
access_tokenid_get_ftokenid(struct file * file,void __user * uarg)88 int access_tokenid_get_ftokenid(struct file *file, void __user *uarg)
89 {
90 	if (!check_permission_for_ftokenid(file))
91 		return -EPERM;
92 
93 	return copy_to_user(uarg, &current->ftoken,
94 			    sizeof(current->ftoken)) ? -EFAULT : 0;
95 }
96 
access_tokenid_set_ftokenid(struct file * file,void __user * uarg)97 int access_tokenid_set_ftokenid(struct file *file, void __user *uarg)
98 {
99 	unsigned long long tmp = 0;
100 
101 	if (!check_permission_for_ftokenid(file))
102 		return -EPERM;
103 
104 	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
105 		return -EFAULT;
106 
107 	current->ftoken = tmp;
108 	return 0;
109 }
110 
111 typedef int (*access_token_id_func)(struct file *file, void __user *arg);
112 
113 static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = {
114 	NULL, /* reserved */
115 	access_tokenid_get_tokenid,
116 	access_tokenid_set_tokenid,
117 	access_tokenid_get_ftokenid,
118 	access_tokenid_set_ftokenid,
119 };
120 
access_tokenid_ioctl(struct file * file,unsigned int cmd,unsigned long arg)121 static long access_tokenid_ioctl(struct file *file, unsigned int cmd,
122 				 unsigned long arg)
123 {
124 	void __user *uarg = (void __user *)arg;
125 	unsigned int func_cmd = _IOC_NR(cmd);
126 
127 	if (uarg == NULL) {
128 		pr_err("%s: invalid user uarg\n", __func__);
129 		return -EINVAL;
130 	}
131 
132 	if (_IOC_TYPE(cmd) != ACCESS_TOKEN_ID_IOCTL_BASE) {
133 		pr_err("%s: access tokenid magic fail, TYPE=%d\n",
134 		       __func__, _IOC_TYPE(cmd));
135 		return -EINVAL;
136 	}
137 
138 	if (func_cmd >= ACCESS_TOKENID_MAX_NR) {
139 		pr_err("%s: access tokenid cmd error, cmd:%d\n",
140 			__func__, func_cmd);
141 		return -EINVAL;
142 	}
143 
144 	if (g_func_array[func_cmd])
145 		return (*g_func_array[func_cmd])(file, uarg);
146 
147 	return -EINVAL;
148 }
149 
150 static const struct file_operations access_tokenid_fops = {
151 	.owner		= THIS_MODULE,
152 	.unlocked_ioctl	= access_tokenid_ioctl,
153 	.compat_ioctl	= access_tokenid_ioctl,
154 };
155 
156 static struct miscdevice access_tokenid_device = {
157 	.minor	= MISC_DYNAMIC_MINOR,
158 	.name	= "access_token_id",
159 	.fops	= &access_tokenid_fops,
160 };
161 
access_tokenid_init_module(void)162 static int access_tokenid_init_module(void)
163 {
164 	int err;
165 
166 	err = misc_register(&access_tokenid_device);
167 	if (err < 0) {
168 		pr_err("access_tokenid register failed\n");
169 		return err;
170 	}
171 
172 	pr_info("access_tokenid init success\n");
173 	return 0;
174 }
175 
access_tokenid_exit_module(void)176 static void access_tokenid_exit_module(void)
177 {
178 	misc_deregister(&access_tokenid_device);
179 }
180 
181 /* module entry points */
182 module_init(access_tokenid_init_module);
183 module_exit(access_tokenid_exit_module);
184