diff --git a/drivers/Kconfig b/drivers/Kconfig index ab4d43923c4dd5a6860ef81d7241003ba9bcc53b..9df9a3a600abdd0a29408ab9a3fcbd87b31ca994 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -219,4 +219,5 @@ source "drivers/siox/Kconfig" source "drivers/slimbus/Kconfig" +source "drivers/accesstokenid/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 578f469f72fbb223d903151c68c5b9cd057675ea..e455c1cb6049d59ce192ff2d20fa097b80b26e69 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -186,3 +186,4 @@ obj-$(CONFIG_MULTIPLEXER) += mux/ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/ obj-$(CONFIG_SIOX) += siox/ obj-$(CONFIG_GNSS) += gnss/ +obj-$(CONFIG_ACCESS_TOKENID) += accesstokenid/ diff --git a/drivers/accesstokenid/Kconfig b/drivers/accesstokenid/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..30d2957a18888070d259c62edf547f0527be6bf6 --- /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 n + diff --git a/drivers/accesstokenid/Makefile b/drivers/accesstokenid/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..738a550f86cf0be05547563525a323c44aee5d15 --- /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 0000000000000000000000000000000000000000..c43886e7a7a13d9417f8dceaf5b2eef9ca81a8dd --- /dev/null +++ b/drivers/accesstokenid/access_tokenid.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * access_tokenid.c + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ + +#define pr_fmt(fmt) "access_token_id: " fmt + +#include +#include +#include +#include +#include +#include +#include +#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)) { + put_group_info(group_info); + return true; + } + } + + put_group_info(group_info); + 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]) + 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 0000000000000000000000000000000000000000..318b54831ebdba6bf5d5cc9637586967a6a99815 --- /dev/null +++ b/drivers/accesstokenid/access_tokenid.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * access_tokenid.h + * + * Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved. + * + */ + +#ifndef _ACCESS_TOKEN_ID_H +#define _ACCESS_TOKEN_ID_H + +#include +#include + +#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 5e705fa9a913db3cc94f4c25e7e93ca01e603897..6b24ca880858310115603ef69080c57d39294e72 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2939,6 +2939,15 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, } #endif /* CONFIG_LIVEPATCH */ +#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 */ @@ -3040,6 +3049,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_LIVEPATCH ONE("patch_state", S_IRUSR, proc_pid_patch_state), #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) @@ -3418,6 +3430,9 @@ static const struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_LIVEPATCH ONE("patch_state", S_IRUSR, proc_pid_patch_state), #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 c69f308f3a53c7c4b3e59447d74f64fbce1ed403..ad8980af2661e1d3e71cdbd5b77d8e44847bdfc1 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1201,6 +1201,11 @@ struct task_struct { void *security; #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 3ed29bf8eb29196b9dd2ed79588bf86e0b338d92..7296438cf5ae28f9086b2e5c412cef0b80947c1f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -816,6 +816,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