224 lines
6.7 KiB
Diff
224 lines
6.7 KiB
Diff
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 <linux/syscalls.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/pid.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/fs_struct.h>
|
|
+#include <linux/timekeeping.h>
|
|
+#include <linux/dcache.h>
|
|
+#include <linux/rcupdate.h>
|
|
+#include <linux/path.h>
|
|
+
|
|
+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);
|