# 2025 NCU Linux Project 2 [Group 5] ### 組長:林緯宸(114525001) ### 組員:簡文勝(114522008)、林暐智(114522014)、張文瀚(114522087) ## ## Part 1: Source Code ```c #include <linux/kernel.h> #include <linux/syscalls.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/uaccess.h> // copy_to_user struct my_thread_info_record { unsigned long pid; unsigned long tgid; void *process_descriptor_address; void *kernel_mode_stack_address; void *pgd_table_address; }; SYSCALL_DEFINE1(my_get_thread_kernel_info, void __user *, ubuf) { struct my_thread_info_record info; struct task_struct *task = current; void *stack_addr; void *pgd_addr; if (!ubuf) return 0; // 0 means that an error occurs when executing this system call info.pid = task->pid; info.tgid = task->tgid; info.process_descriptor_address = (void *)task; // get the kernel stack address stack_addr = task_stack_page(task); info.kernel_mode_stack_address = stack_addr; // get the pgd (page global directory) if (task->mm) pgd_addr = (void *)task->mm->pgd; // user thread using mm else if (task->active_mm) pgd_addr = (void *)task->active_mm->pgd; // kernel thread using active_mm else pgd_addr = NULL; info.pgd_table_address = pgd_addr; // copy to user-space buffer if (copy_to_user(ubuf, &info, sizeof(info)) != 0) return 0; // 0 means that an error occurs when executing this system call return 1; // A non-zero value means that the system is executed successfully. } ``` ### 說明 - 新增了名為my_get_thread_kernel_info的System Call,接受一個型別為void __user * 的參數ubuf,其中__user代表必須是指向user space的指標 - Process Id可透過task->tgid獲取 - Thread Id可透過task->pid獲取 - process_descriptor的位址就是當前運行的Process current所指向的task_struct - Kernel mode stack起始位址(stack bottom)可透過task_stack_page巨集獲取 - User Process有自己的mm_struct,故可直接取得其中的gdt - Kernel Process沒有自己的mm_struct,故會使用前一個User Process的mm,即task->active_mm - 最後使用copy_to_user將以上取得的my_thread_info_record複製到user space的ubuf中 ## Part2: Tests ### Test 1 ```c #define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <sys/syscall.h> #define __NR_my_get_thread_kernel_info 548 struct my_thread_info_record{ unsigned long pid; unsigned long tgid; void * process_descriptor_address; void * kernel_mode_stack_address; void * pgd_table_address; }; int main(void) { struct my_thread_info_record data; long ret = syscall(__NR_my_get_thread_kernel_info, &data); if (ret != 0) { printf("pid=%lu\n", data.pid); printf("tgid=%lu\n", data.tgid); printf("process descriptor address=%p\n", data.process_descriptor_address); printf("kernel mode stack address=%p\n", data.kernel_mode_stack_address); printf("pgd table address=%p\n", data.pgd_table_address); } else { printf("Cannot execute the new system call correctly\n"); } return 0; } ``` ![messageImage_1765481943237](https://hackmd.io/_uploads/B1hhhEnGZe.jpg) ### Test 2 ```c #define _GNU_SOURCE #include <stdio.h> #include <pthread.h> #include <string.h> #include <sys/syscall.h> #include <unistd.h> #define __NR_my_get_thread_kernel_info 548 struct my_thread_info_record{ unsigned long pid; unsigned long tgid; void * process_descriptor_address; void * kernel_mode_stack_address; void * pgd_table_address; } data; struct data_ { int id ; char name[16] ; }; typedef struct data_ sdata ; static __thread sdata tx ; // thread local variable void hello(int tid) { long ret = syscall(__NR_my_get_thread_kernel_info, &data); if (ret != 0) { printf("[tid=%d] pid=%lu\n", tid, data.pid); printf("[tid=%d] tgid=%lu\n", tid, data.tgid); printf("[tid=%d] process descriptor address=%p\n", tid, data.process_descriptor_address); printf("[tid=%d] kernel mode stack address=%p\n", tid, data.kernel_mode_stack_address); printf("[tid=%d] pgd table address=%p\n", tid, data.pgd_table_address); } else { printf("[tid=%d] Cannot execute the new system call correctly\n", tid); } } void *func1(void *arg) { char *p = (char*) arg ; int pid = syscall(__NR_gettid); tx.id = pid ; strcpy(tx.name,p) ; printf("I am thread with ID %d executing func1().\n",pid); hello(pid); while(1) sleep(1); } void *func2(void *arg) { char *p = (char*) arg ; int pid = syscall(__NR_gettid); tx.id = pid ; strcpy(tx.name,p) ; printf("I am thread with ID %d executing func2().\n",pid); hello(pid); while(1) sleep(2); } int main(void) { pthread_t id[2]; char p[2][16] ; int pid; strcpy(p[0],"Thread1"); pthread_create(&id[0],NULL,func1,(void *)p[0]); strcpy(p[1],"Thread2"); pthread_create(&id[1],NULL,func2,(void *)p[1]); pid = syscall(__NR_gettid); tx.id = pid ; strcpy(tx.name,"MAIN"); printf("I am main thread with ID %d.\n", pid); hello(pid); while(1) sleep(5); return 0; } ``` ![messageImage_1765482043077](https://hackmd.io/_uploads/SJVT34hzbg.jpg)