diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index d056a548358ea024fc64f3a107849951a26838d7..dafc50453c9e17a1c19f023f10293047c9e149a9 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 b3b2019f8d16bbeef51948c249dcfb6dbd97a0fb..79ad71c0eeb0535b521556fc576ce6f845fb3931 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 107f08e03b9fdc4d54b41c7fca707727e1524c92..e09a7e9e100977a3f2604b450253e792ca103394 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 9b3038f1b9b5051bd666a8257957462196fb2e07..d832475889c9924cae8ece019f651d6158579146 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 b85b26d9ccefeda08bb8be7d5d2f54f89d66741b..95670db9500cffaf4ae51ec804e22bd588d702f1 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 aea0ce9f3b745ad8f8bfeed1b74ad9c1307f1c28..492c835bc38297730c5b243d4e147d8722829939 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 2056318988f774931c4e0a3104144bf4a75ff52f..be613493e976779703ee05ccbabe67258fb146ef 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 2ddb4226cd231105b9b8d1ed1a530b65a01f7405..a10f58422969e53bf76fc3648886e708e0ec0b73 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 fc4c9f416fadbb36ca025d824805ccb9c641a9d3..b51e31dc6f68f94f0d365e13be6fc398acb936df 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 e7905bdf6e972c60aa26ab879d1772002e5e870a..122f01956327cf8abbd36dc55f9a70e6c785ad5f 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 f019852b2e611150438d06e7fde23b1345c97619..7c885f83611703e9c05caa0f665302e825478f99 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 f27ac94d5fa7270ba9f272be1bcba6a903149206..ae713ece7cf3c39a52bdec0f0da44f40a86e598a 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 0000000000000000000000000000000000000000..845436cf29ed7b275002ba429ac8ee08777cbe3c --- /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; +}