---
# System prepended metadata

title: '2025 NCU Linux Project 2 [Group 5]'

---

# 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)
