diff --git a/drivers/Kconfig b/drivers/Kconfig index dcecc9f6e33f78de53cf18655624b27d2abe76c4..c9a22b0413034676f56b87906d059952d2fbaa79 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 5762280377186c47739ed9da226022b061658895..71da48160b098700d04ef86e7260788f3a9397ed 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 0000000000000000000000000000000000000000..814c095678e9e1b9173032ac88b84a800f491589 --- /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 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..996b4ce69f2bb5c888e0cf80bd8c4b691b48d601 --- /dev/null +++ b/drivers/accesstokenid/access_tokenid.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * access_tokenid.c + * + * Copyright (C) 2022-2023 Huawei Technologies Co., Ltd. + * + */ + +#define pr_fmt(fmt) "access_token_id: " fmt + +#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)) + 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 0000000000000000000000000000000000000000..b5f5a24087cc1dde2312fac2e4bf1fff5efa6a9a --- /dev/null +++ b/drivers/accesstokenid/access_tokenid.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * access_tokenid.h + * + * Copyright (C) 2022-2023 Huawei Technologies Co., Ltd. + * + */ + +#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 9b3038f1b9b5051bd666a8257957462196fb2e07..9478b78f53cea657bc9dd199fdd8fd1680d4df72 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 b85b26d9ccefeda08bb8be7d5d2f54f89d66741b..cf376af5f1c83b89ad561d01b17c0c772a3d5511 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1357,6 +1357,11 @@ 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 f019852b2e611150438d06e7fde23b1345c97619..419e7689f7c47b1f4702f2e3d854af36ee0ce4d3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -873,7 +873,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) stack_vm_area = task_stack_vm_area(tsk); 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