修改内核中的只读区内容

研究到 apparmor 内核源码,其中涉及到只读变量 __lsm_ro_after_init,研究怎么修改只读区实现部分功能,这里记录一下。

思路上很简单,修改的时候禁用写保护,或者修改pte写保护属性。

实现上第一种更简单,所以采用第一种。

主要函数为 disable_write_protection,修改cr0的写保护位即可。


inline void mywrite_cr0(unsigned long cr0) {
  asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order));
}

void enable_write_protection(void) {
  unsigned long cr0 = read_cr0();
  set_bit(16, &cr0);
  mywrite_cr0(cr0);
}

void disable_write_protection(void) {
  unsigned long cr0 = read_cr0();
  clear_bit(16, &cr0);
  mywrite_cr0(cr0);
}

static int hook_apparmor_func(void *arg)
{
	union security_list_options *tmp = arg;

	disable_write_protection();
	tmp->file_permission = some_func;
	enable_write_protection();
	return 0;
}

static int recover_apparmor_func(void *arg)
{
	union security_list_options *tmp = arg;

	disable_write_protection();
	tmp->file_permission = orig_apparmor_file_permission ;
	enable_write_protection();
	return 0;
}


void hook_apparmor(void)
{
	struct security_hook_list *P; 
	struct hlist_head *head = &(orig_security_hook_heads->file_permission);
        hlist_for_each_entry(P, head, list) {
		if(strcmp(P->lsm, "apparmor") == 0){
			orig_apparmor_file_permission = P->hook.file_permission;
			stop_machine(hook_apparmor_func, (void*)&(P->hook), 0);
		}
   }
}

void recover_apparmor(void)
{
	struct security_hook_list *P; 
	struct hlist_head *head = &(orig_security_hook_heads->file_permission);
        hlist_for_each_entry(P, head, list) {
		if(strcmp(P->lsm, "apparmor") == 0){
			stop_machine(recover_apparmor_func, (void*)&(P->hook), 0);
		}
   }
}

posted @ 2022-05-12 17:57  RayWHL  阅读(154)  评论(0)    收藏  举报