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