From 6a43e037faab2f3d084fce8b16d864f18b033a48 Mon Sep 17 00:00:00 2001
From: liqiang <liqiang64@huawei.com>
Date: Mon, 17 Jun 2024 11:18:43 +0800
Subject: [PATCH] refactor syscall wrapper for aarch64, reduce the memory range
 to o be writable

Signed-off-by: liqiang <liqiang64@huawei.com>
---
 qtfs/include/symbol_wrapper.h     | 14 ++++++++++++--
 qtfs/qtfs/syscall.c               | 25 ++++++++++++-------------
 qtfs/qtfs_common/symbol_wrapper.c | 18 ++++++------------
 3 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/qtfs/include/symbol_wrapper.h b/qtfs/include/symbol_wrapper.h
index cef2cd9..4ce500f 100644
--- a/qtfs/include/symbol_wrapper.h
+++ b/qtfs/include/symbol_wrapper.h
@@ -72,8 +72,18 @@ static inline int make_ro(unsigned long address)
 
 #ifdef __aarch64__
 extern void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);
-extern unsigned long start_rodata, end_rodata;
-#define section_size (end_rodata - start_rodata)
+static inline int make_rw(unsigned long address)
+{
+	update_mapping_prot(__pa_symbol(address & PAGE_MASK), (unsigned long)(address & PAGE_MASK), PAGE_SIZE, PAGE_KERNEL);
+	return 0;
+}
+
+static inline int make_ro(unsigned long address)
+{
+	update_mapping_prot(__pa_symbol(address & PAGE_MASK), (unsigned long)(address & PAGE_MASK), PAGE_SIZE, PAGE_KERNEL_RO);
+	return 0;
+}
+
 #endif
 
 int qtfs_syscall_replace_start(void);
diff --git a/qtfs/qtfs/syscall.c b/qtfs/qtfs/syscall.c
index a02a225..7b139a4 100644
--- a/qtfs/qtfs/syscall.c
+++ b/qtfs/qtfs/syscall.c
@@ -441,22 +441,22 @@ int qtfs_syscall_init(void)
 	symbols_origin[SYMBOL_SYSCALL_MOUNT] = qtfs_kern_syms.sys_call_table[__NR_mount];
 	symbols_origin[SYMBOL_SYSCALL_UMOUNT] = qtfs_kern_syms.sys_call_table[__NR_umount2];
 	symbols_origin[SYMBOL_SYSCALL_EPOLL_CTL] = qtfs_kern_syms.sys_call_table[__NR_epoll_ctl];
-#ifdef __x86_64__
+
 	make_rw((unsigned long)qtfs_kern_syms.sys_call_table);
+	make_rw((unsigned long)qtfs_kern_syms.sys_call_table + PAGE_SIZE);
+#ifdef __x86_64__
 	qtfs_kern_syms.sys_call_table[__NR_mount] = (unsigned long *)__x64_sys_qtfs_mount;
 	qtfs_kern_syms.sys_call_table[__NR_umount2] = (unsigned long *)__x64_sys_qtfs_umount;
 	qtfs_kern_syms.sys_call_table[__NR_epoll_ctl] = (unsigned long *)__x64_sys_qtfs_epoll_ctl;
-	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
 #endif
 #ifdef __aarch64__
-	// disable write protection
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL);
 	qtfs_kern_syms.sys_call_table[__NR_mount] = (unsigned long *)__arm64_sys_qtfs_mount;
 	qtfs_kern_syms.sys_call_table[__NR_umount2] = (unsigned long *)__arm64_sys_qtfs_umount;
 	qtfs_kern_syms.sys_call_table[__NR_epoll_ctl] = (unsigned long *)__arm64_sys_qtfs_epoll_ctl;
-	// enable write protection
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL_RO);
 #endif
+	// enable write protection
+	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
+	make_ro((unsigned long)qtfs_kern_syms.sys_call_table + PAGE_SIZE);
 	qtfs_debug("qtfs use qtfs_mount instead of mount and umount\n");
 	qtfs_debug("qtfs use qtfs_epoll_ctl instead of epoll_ctl\n");
 	return 0;
@@ -464,23 +464,22 @@ int qtfs_syscall_init(void)
 
 int qtfs_syscall_fini(void)
 {
-#ifdef __x86_64__
 	make_rw((unsigned long)qtfs_kern_syms.sys_call_table);
+	make_rw((unsigned long)qtfs_kern_syms.sys_call_table + PAGE_SIZE);
+#ifdef __x86_64__
 	qtfs_kern_syms.sys_call_table[__NR_mount] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_MOUNT];
 	qtfs_kern_syms.sys_call_table[__NR_umount2] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_UMOUNT];
 	qtfs_kern_syms.sys_call_table[__NR_epoll_ctl] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_EPOLL_CTL];
-	/*set mkdir syscall to the original one */
-	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
 #endif
 #ifdef __aarch64__
-	// disable write protection
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL);
 	qtfs_kern_syms.sys_call_table[__NR_mount] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_MOUNT];
 	qtfs_kern_syms.sys_call_table[__NR_umount2] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_UMOUNT];
 	qtfs_kern_syms.sys_call_table[__NR_epoll_ctl] = (unsigned long *)symbols_origin[SYMBOL_SYSCALL_EPOLL_CTL];
-	// enable write protection
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL_RO);
 #endif
+	// enable write protection
+	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
+	make_ro((unsigned long)qtfs_kern_syms.sys_call_table + PAGE_SIZE);
+
 	qtfs_info("qtfs mount umount and epoll_ctl resumed\n");
 	atomic_inc(&replace_available);
 	return 0;
diff --git a/qtfs/qtfs_common/symbol_wrapper.c b/qtfs/qtfs_common/symbol_wrapper.c
index 84c1bd5..5ceaf5f 100644
--- a/qtfs/qtfs_common/symbol_wrapper.c
+++ b/qtfs/qtfs_common/symbol_wrapper.c
@@ -55,7 +55,6 @@ struct pt_regs;
 #endif
 #ifdef __aarch64__
 void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);
-unsigned long start_rodata, end_rodata;
 
 // symbols not finded in sys call table
 enum qtfs_sym_a64 {
@@ -132,9 +131,7 @@ int qtfs_kallsyms_hack_init(void)
 
 #ifdef __aarch64__
 	update_mapping_prot = (void *)qtfs_kallsyms_lookup_name("update_mapping_prot");
-	start_rodata = (unsigned long)qtfs_kallsyms_lookup_name("__start_rodata");
-	end_rodata = (unsigned long)qtfs_kallsyms_lookup_name("__end_rodata");
-	if (update_mapping_prot == NULL || (void *)start_rodata == NULL || (void *)end_rodata == NULL) {
+	if (update_mapping_prot == NULL) {
 		qtfs_err("failed to init memory protect handler");
 		return -1;
 	}
@@ -170,33 +167,30 @@ int qtfs_syscall_replace_start(void)
 	}
 
 	symbols_origin[SYMBOL_SYSCALL_CONNECT] = qtfs_kern_syms.sys_call_table[__NR_connect];
+	make_rw((unsigned long)&qtfs_kern_syms.sys_call_table[__NR_connect]);
 #ifdef __x86_64__
-	make_rw((unsigned long)qtfs_kern_syms.sys_call_table);
 	qtfs_kern_syms.sys_call_table[__NR_connect] = (unsigned long *)__x64_sys_qtfs_connect;
-	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
 #endif
 
 #ifdef __aarch64__
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL);
 	qtfs_kern_syms.sys_call_table[__NR_connect] = (unsigned long *)__arm64_sys_qtfs_connect;
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL_RO);
 #endif
+	make_ro((unsigned long)&qtfs_kern_syms.sys_call_table[__NR_connect]);
 	return 0;
 }
 
 void qtfs_syscall_replace_stop(void)
 {
+	make_rw((unsigned long)&qtfs_kern_syms.sys_call_table[__NR_connect]);
 #ifdef __x86_64__
-	make_rw((unsigned long)qtfs_kern_syms.sys_call_table);
 	qtfs_kern_syms.sys_call_table[__NR_connect] = (void *)qtfs_kallsyms_lookup_name("__x64_sys_connect");
-	make_ro((unsigned long)qtfs_kern_syms.sys_call_table);
 #endif
 
 #ifdef __aarch64__
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL);
 	qtfs_kern_syms.sys_call_table[__NR_connect] = (void *)qtfs_kallsyms_lookup_name("__arm64_sys_connect");
-	update_mapping_prot(__pa_symbol(start_rodata), (unsigned long)start_rodata, section_size, PAGE_KERNEL_RO);
 #endif
+	make_ro((unsigned long)&qtfs_kern_syms.sys_call_table[__NR_connect]);
+
 	atomic_inc(&replace_available);
 }
 
-- 
2.37.1 (Apple Git-137.1)