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, ¤t->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, ¤t->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