From: gaochao <gaochao49(a)huawei.com>
ohos inclusion
category: feature
issue: #I4OWTZ
CVE: NA
-----------
tokendid is used for special app security control
Signed-off-by: gaochao <gaochao49(a)huawei.com>
---
 drivers/Kconfig                        |   2 +
 drivers/Makefile                       |   1 +
 drivers/accesstokenid/Kconfig          |   5 +
 drivers/accesstokenid/Makefile         |   2 +
 drivers/accesstokenid/access_tokenid.c | 187 +++++++++++++++++++++++++
 drivers/accesstokenid/access_tokenid.h |  43 ++++++
 fs/proc/base.c                         |  15 ++
 include/linux/sched.h                  |   4 +
 kernel/fork.c                          |   4 +
 9 files changed, 263 insertions(+)
 create mode 100644 drivers/accesstokenid/Kconfig
 create mode 100644 drivers/accesstokenid/Makefile
 create mode 100644 drivers/accesstokenid/access_tokenid.c
 create mode 100644 drivers/accesstokenid/access_tokenid.h
diff --git a/drivers/Kconfig b/drivers/Kconfig
index dcecc9f6e33f..c9a22b041303 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -235,4 +235,6 @@ source "drivers/interconnect/Kconfig"
 source "drivers/counter/Kconfig"
 
 source "drivers/most/Kconfig"
+
+source "drivers/accesstokenid/Kconfig"
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 576228037718..71da48160b09 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -189,3 +189,4 @@ obj-$(CONFIG_GNSS)		+= gnss/
 obj-$(CONFIG_INTERCONNECT)	+= interconnect/
 obj-$(CONFIG_COUNTER)		+= counter/
 obj-$(CONFIG_MOST)		+= most/
+obj-$(CONFIG_ACCESS_TOKENID)	+= accesstokenid/
diff --git a/drivers/accesstokenid/Kconfig b/drivers/accesstokenid/Kconfig
new file mode 100644
index 000000000000..814c095678e9
--- /dev/null
+++ b/drivers/accesstokenid/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+config ACCESS_TOKENID
+	bool "Access task's token"
+	default y
+
diff --git a/drivers/accesstokenid/Makefile b/drivers/accesstokenid/Makefile
new file mode 100644
index 000000000000..738a550f86cf
--- /dev/null
+++ b/drivers/accesstokenid/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ACCESS_TOKENID)		+= access_tokenid.o
diff --git a/drivers/accesstokenid/access_tokenid.c b/drivers/accesstokenid/access_tokenid.c
new file mode 100644
index 000000000000..94e5310521ec
--- /dev/null
+++ b/drivers/accesstokenid/access_tokenid.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * access_tokenid.c
+ *
+ * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "access_token_id: " fmt
+
+#include <linux/cred.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "access_tokenid.h"
+
+int access_tokenid_get_tokenid(struct file *file, void __user *uarg)
+{
+	return copy_to_user(uarg, ¤t->token,
+			    sizeof(current->token)) ? -EFAULT : 0;
+}
+
+static bool check_permission_for_set_tokenid(struct file *file)
+{
+	const struct cred *cred = get_task_cred(current);
+	struct inode *inode = file->f_inode;
+
+	if (inode == NULL) {
+		pr_err("%s: file inode is null\n", __func__);
+		return false;
+	}
+
+	if (uid_eq(cred->uid, GLOBAL_ROOT_UID) ||
+	    uid_eq(cred->uid, inode->i_uid)) {
+		return true;
+	}
+
+	return false;
+}
+
+int access_tokenid_set_tokenid(struct file *file, void __user *uarg)
+{
+	unsigned long long tmp = 0;
+
+	if (!check_permission_for_set_tokenid(file))
+		return -EPERM;
+
+	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
+		return -EFAULT;
+
+	current->token = tmp;
+	return 0;
+}
+
+static bool check_permission_for_ftokenid(struct file *file)
+{
+	int i;
+	struct group_info *group_info;
+	const struct cred *cred = get_task_cred(current);
+	struct inode *inode = file->f_inode;
+
+	if (inode == NULL) {
+		pr_err("%s: file inode is null\n", __func__);
+		return false;
+	}
+
+	if (uid_eq(cred->uid, GLOBAL_ROOT_UID))
+		return true;
+
+	group_info = get_current_groups();
+	for (i = 0; i < group_info->ngroups; i++) {
+		kgid_t gid = group_info->gid[i];
+
+		if (gid_eq(gid, inode->i_gid))
+			return true;
+	}
+
+	return false;
+}
+
+int access_tokenid_get_ftokenid(struct file *file, void __user *uarg)
+{
+	if (!check_permission_for_ftokenid(file))
+		return -EPERM;
+
+	return copy_to_user(uarg, ¤t->ftoken,
+			    sizeof(current->ftoken)) ? -EFAULT : 0;
+}
+
+int access_tokenid_set_ftokenid(struct file *file, void __user *uarg)
+{
+	unsigned long long tmp = 0;
+
+	if (!check_permission_for_ftokenid(file))
+		return -EPERM;
+
+	if (copy_from_user(&tmp, uarg, sizeof(tmp)))
+		return -EFAULT;
+
+	current->ftoken = tmp;
+	return 0;
+}
+
+typedef int (*access_token_id_func)(struct file *file, void __user *arg);
+
+static access_token_id_func g_func_array[ACCESS_TOKENID_MAX_NR] = {
+	NULL, /* reserved */
+	access_tokenid_get_tokenid,
+	access_tokenid_set_tokenid,
+	access_tokenid_get_ftokenid,
+	access_tokenid_set_ftokenid,
+};
+
+static long access_tokenid_ioctl(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	void __user *uarg = (void __user *)arg;
+	unsigned int func_cmd = _IOC_NR(cmd);
+
+	if (uarg == NULL) {
+		pr_err("%s: invalid user uarg\n", __func__);
+		return -EINVAL;
+	}
+
+	if (_IOC_TYPE(cmd) != ACCESS_TOKEN_ID_IOCTL_BASE) {
+		pr_err("%s: access tokenid magic fail, TYPE=%d\n",
+		       __func__, _IOC_TYPE(cmd));
+		return -EINVAL;
+	}
+
+	if (func_cmd >= ACCESS_TOKENID_MAX_NR) {
+		pr_err("%s: access tokenid cmd error, cmd:%d\n",
+			__func__, func_cmd);
+		return -EINVAL;
+	}
+
+	if (g_func_array[func_cmd] != NULL)
+		return (*g_func_array[func_cmd])(file, uarg);
+
+	return -EINVAL;
+}
+
+static const struct file_operations access_tokenid_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= access_tokenid_ioctl,
+	.compat_ioctl	= access_tokenid_ioctl,
+};
+
+static struct miscdevice access_tokenid_device = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "access_token_id",
+	.fops	= &access_tokenid_fops,
+};
+
+static int access_tokenid_init_module(void)
+{
+	int err;
+
+	err = misc_register(&access_tokenid_device);
+	if (err < 0) {
+		pr_err("access_tokenid register failed\n");
+		return err;
+	}
+
+	pr_info("access_tokenid init success\n");
+	return 0;
+}
+
+static void access_tokenid_exit_module(void)
+{
+	misc_deregister(&access_tokenid_device);
+}
+
+/* module entry points */
+module_init(access_tokenid_init_module);
+module_exit(access_tokenid_exit_module);
diff --git a/drivers/accesstokenid/access_tokenid.h b/drivers/accesstokenid/access_tokenid.h
new file mode 100644
index 000000000000..1b3906f993b7
--- /dev/null
+++ b/drivers/accesstokenid/access_tokenid.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * access_tokenid.h
+ *
+ * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ACCESS_TOKEN_ID_H
+#define _ACCESS_TOKEN_ID_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define	ACCESS_TOKEN_ID_IOCTL_BASE	'A'
+
+enum {
+	GET_TOKEN_ID = 1,
+	SET_TOKEN_ID,
+	GET_FTOKEN_ID,
+	SET_FTOKEN_ID,
+	ACCESS_TOKENID_MAX_NR
+};
+
+#define	ACCESS_TOKENID_GET_TOKENID \
+	_IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_TOKEN_ID, unsigned long long)
+#define	ACCESS_TOKENID_SET_TOKENID \
+	_IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_TOKEN_ID, unsigned long long)
+#define	ACCESS_TOKENID_GET_FTOKENID \
+	_IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_FTOKEN_ID, unsigned long long)
+#define	ACCESS_TOKENID_SET_FTOKENID \
+	_IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_FTOKEN_ID, unsigned long long)
+
+#endif /* _ACCESS_TOKEN_ID_H */
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9b3038f1b9b5..9478b78f53ce 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -3179,6 +3179,15 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
 }
 #endif /* CONFIG_STACKLEAK_METRICS */
 
+#ifdef CONFIG_ACCESS_TOKENID
+static int proc_token_operations(struct seq_file *m, struct pid_namespace *ns,
+				 struct pid *pid, struct task_struct *task)
+{
+	seq_printf(m, "%#llx %#llx\n", task->token, task->ftoken);
+	return 0;
+}
+#endif /* CONFIG_ACCESS_TOKENID */
+
 /*
  * Thread groups
  */
@@ -3292,6 +3301,9 @@ static const struct pid_entry tgid_base_stuff[] = {
 #ifdef CONFIG_PROC_PID_ARCH_STATUS
 	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
 #endif
+#ifdef CONFIG_ACCESS_TOKENID
+	ONE("tokenid", S_IRUSR, proc_token_operations),
+#endif
 };
 
 static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -3621,6 +3633,9 @@ static const struct pid_entry tid_base_stuff[] = {
 #ifdef CONFIG_PROC_PID_ARCH_STATUS
 	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
 #endif
+#ifdef CONFIG_ACCESS_TOKENID
+	ONE("tokenid", S_IRUSR, proc_token_operations),
+#endif
 };
 
 static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 53198ac3d154..d42f4addcaec 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1362,6 +1362,10 @@ struct task_struct {
 	int				mce_count;
 #endif
 
+#ifdef CONFIG_ACCESS_TOKENID
+	u64				token;
+	u64				ftoken;
+#endif
 	/*
 	 * New fields for task_struct should be added above here, so that
 	 * they are included in the randomized portion of task_struct.
diff --git a/kernel/fork.c b/kernel/fork.c
index 39b1783a7613..5d7a6821d59c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -874,6 +874,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 
 	err = arch_dup_task_struct(tsk, orig);
 
+#ifdef CONFIG_ACCESS_TOKENID
+	tsk->token = orig->token;
+	tsk->ftoken = 0;
+#endif
 	/*
 	 * arch_dup_task_struct() clobbers the stack-related fields.  Make
 	 * sure they're properly initialized before using any stack-related
-- 
2.25.1