From e8920ff9a13e33bcdc99f6392187c0976a15616a Mon Sep 17 00:00:00 2001 From: gc1202 Date: Fri, 31 Dec 2021 15:34:01 +0800 Subject: [PATCH] category: feature issue: #I4OWTZ CVE: NA Signed-off-by: gaochao --- arch/arm/tools/syscall.tbl | 6 +++ arch/arm64/include/asm/unistd.h | 5 +++ arch/arm64/include/asm/unistd32.h | 9 ++++ fs/proc/base.c | 15 +++++++ include/linux/sched.h | 5 +++ include/linux/syscalls.h | 5 +++ include/uapi/asm-generic/unistd.h | 11 ++++- include/uapi/linux/capability.h | 4 +- init/Kconfig | 4 ++ kernel/Makefile | 2 + kernel/fork.c | 5 +++ kernel/sys_ni.c | 7 ++++ kernel/tokenid.c | 69 +++++++++++++++++++++++++++++++ 13 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 kernel/tokenid.c diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index d056a548358e..dafc50453c9e 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -454,3 +454,9 @@ 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 440 common process_madvise sys_process_madvise + +641 common settokenid sys_settokenid +642 common gettokenid sys_gettokenid +643 common setftokenid sys_setftokenid +644 common getftokenid sys_getftokenid + diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index b3b2019f8d16..79ad71c0eeb0 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -30,6 +30,11 @@ #define __NR_compat_clock_gettime64 403 #define __NR_compat_clock_getres_time64 406 +#define __NR_settokenid 641 +#define __NR_gettokenid 642 +#define __NR_setftokenid 643 +#define __NR_getftokenid 644 + /* * The following SVCs are ARM private. */ diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 107f08e03b9f..e09a7e9e1009 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -890,6 +890,15 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2) #define __NR_process_madvise 440 __SYSCALL(__NR_process_madvise, sys_process_madvise) +#define __NR_settokenid 641 +__SYSCALL(__NR_settokenid, sys_settokenid) +#define __NR_gettokenid 642 +__SYSCALL(__NR_gettokenid, sys_gettokenid) +#define __NR_setftokenid 643 +__SYSCALL(__NR_setftokenid, sys_setftokenid) +#define __NR_getftokenid 644 +__SYSCALL(__NR_getftokenid, sys_getftokenid) + /* * Please add new compat syscalls above this comment and update * __NR_compat_syscalls in asm/unistd.h. diff --git a/fs/proc/base.c b/fs/proc/base.c index 9b3038f1b9b5..d832475889c9 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_TASK_TOKEN +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_TASK_TOKEN */ + /* * 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_TASK_TOKEN + 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_TASK_TOKEN + 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 b85b26d9ccef..95670db9500c 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_TASK_TOKEN + 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/include/linux/syscalls.h b/include/linux/syscalls.h index aea0ce9f3b74..492c835bc382 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1033,6 +1033,11 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, unsigned int flags); asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); +asmlinkage long sys_settokenid(unsigned long long __user *tokenId, int flags); +asmlinkage long sys_gettokenid(unsigned long long __user *tokenId, int flags); +asmlinkage long sys_setftokenid(unsigned long long __user *ftokenId, int flags); +asmlinkage long sys_getftokenid(unsigned long long __user *ftokenId, int flags); + /* * Architecture-specific system calls */ diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 2056318988f7..be613493e976 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -860,8 +860,17 @@ __SYSCALL(__NR_faccessat2, sys_faccessat2) #define __NR_process_madvise 440 __SYSCALL(__NR_process_madvise, sys_process_madvise) +#define __NR_settokenid 641 +__SYSCALL(__NR_settokenid, sys_settokenid) +#define __NR_gettokenid 642 +__SYSCALL(__NR_gettokenid, sys_gettokenid) +#define __NR_setftokenid 643 +__SYSCALL(__NR_setftokenid, sys_setftokenid) +#define __NR_getftokenid 644 +__SYSCALL(__NR_getftokenid, sys_getftokenid) + #undef __NR_syscalls -#define __NR_syscalls 441 +#define __NR_syscalls 645 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index 2ddb4226cd23..a10f58422969 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h @@ -411,12 +411,14 @@ struct vfs_ns_cap_data { */ #define CAP_BPF 39 +#define CAP_TOKEN_SET 61 +#define CAP_FTOKEN_SET 62 /* Allow checkpoint/restore related operations */ /* Allow PID selection during clone3() */ /* Allow writing to ns_last_pid */ -#define CAP_CHECKPOINT_RESTORE 40 +#define CAP_CHECKPOINT_RESTORE 63 #define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE diff --git a/init/Kconfig b/init/Kconfig index fc4c9f416fad..b51e31dc6f68 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -432,6 +432,10 @@ config AUDITSYSCALL depends on AUDIT && HAVE_ARCH_AUDITSYSCALL select FSNOTIFY +config ACCESS_TASK_TOKEN + bool "access task's token" + default y + source "kernel/irq/Kconfig" source "kernel/time/Kconfig" source "kernel/Kconfig.preempt" diff --git a/kernel/Makefile b/kernel/Makefile index e7905bdf6e97..122f01956327 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -124,6 +124,8 @@ obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o +obj-$(CONFIG_ACCESS_TASK_TOKEN) += tokenid.o + CFLAGS_stackleak.o += $(DISABLE_STACKLEAK_PLUGIN) obj-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak.o KASAN_SANITIZE_stackleak.o := n diff --git a/kernel/fork.c b/kernel/fork.c index f019852b2e61..7c885f836117 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -874,6 +874,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) err = arch_dup_task_struct(tsk, orig); +#ifdef CONFIG_ACCESS_TASK_TOKEN + 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 diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index f27ac94d5fa7..ae713ece7cf3 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -471,3 +471,10 @@ COND_SYSCALL(setuid16); /* restartable sequence */ COND_SYSCALL(rseq); + +/* access task's token */ +COND_SYSCALL(settokenid); +COND_SYSCALL(gettokenid); +COND_SYSCALL(setftokenid); +COND_SYSCALL(getftokenid); + diff --git a/kernel/tokenid.c b/kernel/tokenid.c new file mode 100644 index 000000000000..845436cf29ed --- /dev/null +++ b/kernel/tokenid.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * linux/kernel/tkenid.c + * + * Copyright (C) 2022, 2023 huawei + */ + +#include +#include + +SYSCALL_DEFINE2(settokenid, unsigned long long __user *, tokenId, int, flags) +{ + int err; + + /* flags is currently unused - make sure it's unset */ + if (flags || tokenId == NULL) + return -EINVAL; + + if (!ns_capable(task_active_pid_ns(current)->user_ns, CAP_TOKEN_SET)) { +#if 0 + return -EPERM; +#endif + } + + err = copy_from_user(¤t->token, tokenId, sizeof(current->token)); + + return err; +} + + +SYSCALL_DEFINE2(gettokenid, unsigned long long __user *, tokenId, int, flags) +{ + /* flags is currently unused - make sure it's unset */ + if (flags || tokenId == NULL) + return -EINVAL; + + return copy_to_user(tokenId, ¤t->token, + sizeof(*tokenId)) ? -EFAULT : 0; +} + +SYSCALL_DEFINE2(setftokenid, unsigned long long __user *, ftokenId, int, flags) +{ + int err; + + /* flags is currently unused - make sure it's unset */ + if (flags || ftokenId == NULL) + return -EINVAL; + + if (!ns_capable(task_active_pid_ns(current)->user_ns, CAP_TOKEN_SET)) { +#if 0 + return -EPERM; +#endif + } + + err = copy_from_user(¤t->ftoken, ftokenId, + sizeof(current->ftoken)); + + return err; +} + +SYSCALL_DEFINE2(getftokenid, unsigned long long __user *, ftokenId, int, flags) +{ + /* flags is currently unused - make sure it's unset */ + if (flags || ftokenId == NULL) + return -EINVAL; + + return copy_to_user(ftokenId, ¤t->ftoken, + sizeof(*ftokenId)) ? -EFAULT : 0; +} -- Gitee