diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 7093ee21c..b0d25489c 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -386,6 +386,7 @@ 460 common lsm_set_self_attr sys_lsm_set_self_attr 461 common lsm_list_modules sys_lsm_list_modules 462 common mseal sys_mseal +463 common get_pid_info sys_get_pid_info # # Due to a historical design error, certain syscalls are numbered differently diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 575810492..6c211aabc 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1197,6 +1197,20 @@ asmlinkage long sys_ni_syscall(void); asmlinkage long sys_ni_posix_timers(void); +/* CONFIG GET PID INFO */ +struct pid_info { + int pid; + u32 state; + const void *stack; + u64 age; + int *children; + int parent_pid; + char root_path[PATH_MAX]; + char working_directory[PATH_MAX]; +}; + +asmlinkage long sys_get_pid_info(struct pid_info * p_info_struct, int pid); + /* * Kernel code should not call syscalls (i.e., sys_xyzyyz()) directly. * Instead, use one of the functions which work equivalently, such as diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 5bf6148ca..52599890a 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -841,8 +841,11 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) #define __NR_mseal 462 __SYSCALL(__NR_mseal, sys_mseal) +#define __NR_get_pid_info 463 +__SYSCALL(__NR_get_pid_info, sys_get_pid_info) + #undef __NR_syscalls -#define __NR_syscalls 463 +#define __NR_syscalls 464 /* * 32 bit systems traditionally used different @@ -866,7 +869,7 @@ __SYSCALL(__NR_mseal, sys_mseal) #define __NR_newfstatat __NR3264_fstatat #define __NR_fstat __NR3264_fstat #endif -#define __NR_mmap __NR3264_mmap +#define __NR_mmap __NR3264_mmapmseal #define __NR_fadvise64 __NR3264_fadvise64 #ifdef __NR3264_stat #define __NR_stat __NR3264_stat diff --git a/kernel/Makefile b/kernel/Makefile index 87866b037..15b5167fc 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -50,6 +50,7 @@ obj-y += rcu/ obj-y += livepatch/ obj-y += dma/ obj-y += entry/ +obj-y += get_pid_info/ obj-$(CONFIG_MODULES) += module/ obj-$(CONFIG_KCMP) += kcmp.o diff --git a/kernel/get_pid_info/Makefile b/kernel/get_pid_info/Makefile new file mode 100644 index 000000000..2139af568 --- /dev/null +++ b/kernel/get_pid_info/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y += get_pid_info.o diff --git a/kernel/get_pid_info/get_pid_info.c b/kernel/get_pid_info/get_pid_info.c new file mode 100644 index 000000000..f14b7e4d3 --- /dev/null +++ b/kernel/get_pid_info/get_pid_info.c @@ -0,0 +1,123 @@ +// +// Created by jrathelo on 11/18/24. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static long __sys_get_pid_info(struct pid_info __user * p_info_struct, int pid) { + struct task_struct *task; + char * path; + struct timespec64 current_time; + size_t size = 0; + int *child_list = NULL; + + if (p_info_struct == NULL) { + rcu_read_lock(); + task = pid_task(find_vpid(pid), PIDTYPE_PID); + if (task) { + size = list_count_nodes(&(task->children)); + rcu_read_unlock(); + return size; + } + rcu_read_unlock(); + return 0; + } + + struct pid_info *data = (struct pid_info *) kzalloc(sizeof(struct pid_info), GFP_KERNEL); + if (data == NULL) { + return -ENOMEM; + } + memset(data, 0, sizeof(struct pid_info)); + + int error = copy_from_user(data, p_info_struct, sizeof(struct pid_info)); + if (error) { + kfree(data); + return -EFAULT; + } + + rcu_read_lock(); + task = pid_task(find_vpid(pid), PIDTYPE_PID); + if (task) { + data->pid = pid; + data->state = task->__state; + data->stack = task->stack; + ktime_get_boottime_ts64(¤t_time); + data->age = (timespec64_to_ns(¤t_time) - task->start_time); + if (task->parent) { + data->parent_pid = task->parent->pid; + } else { + data->parent_pid = 0; + } + if (!task->fs) { + memset(data->root_path, 0, PATH_MAX); + memset(data->working_directory, 0, PATH_MAX); + rcu_read_unlock(); + return 0; + } + path = d_path(&task->fs->root, data->root_path, PATH_MAX); + if (IS_ERR(path)) { + memset(data->root_path, 0, PATH_MAX); + } else { + memcpy(data->root_path, path, PATH_MAX); + } + path = d_path(&task->fs->pwd, data->working_directory, PATH_MAX); + if (IS_ERR(path)) { + memset(data->working_directory, 0, PATH_MAX); + } else { + memcpy(data->working_directory, path, PATH_MAX); + } + size = list_count_nodes(&(task->children)); + if (size == 0) { + child_list = NULL; + } else { + child_list = kzalloc(sizeof(int) * size, GFP_KERNEL); + if (child_list == NULL){ + kfree(data); + rcu_read_unlock(); + return -ENOMEM; + } + struct task_struct *child_task; + size_t index = 0; + list_for_each_entry(child_task, &task->children, sibling) { + child_list[index] = child_task->pid; + + pr_info("%d\n", child_list[index]); + index ++; + } + } + } + rcu_read_unlock(); + if (child_list != NULL) { + pr_info("HERE: %d\n", child_list[0]); + error = copy_to_user(data->children, child_list, sizeof(int) * size); + if (error) { + pr_info("HERE?\n"); + kfree(child_list); + kfree(data); + return -EFAULT; + } + kfree(child_list); + } + pr_info("HERE6\n"); + error = copy_to_user(p_info_struct, data, sizeof(struct pid_info)); + if (error) { + kfree(data); + return -EFAULT; + } + kfree(data); + pr_info("HERE7\n"); + return 0; +} + +SYSCALL_DEFINE2(get_pid_info, struct pid_info __user *, p_info_struct, int, pid) { + return __sys_get_pid_info(p_info_struct, pid); +} diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index c00a86931..95daa731d 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c @@ -392,3 +392,5 @@ COND_SYSCALL(setuid16); COND_SYSCALL(rseq); COND_SYSCALL(uretprobe); + +COND_SYSCALL(get_pid_info);