📄 w32init.c
字号:
/*
* w32init.c
*
* Copyright (C) 2006 Insigme Co., Ltd
*
* Authors:
* - Decao Mao, Chenzhan Hu, Lixing Chu, Zhiqiang Jiao
*
* This software has been developed while working on the Linux Unified Kernel
* project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute,
* which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn).
*
* The project is sponsored by Insigma Co., Ltd.
*
* The authors can be reached at linux@insigma.com.cn.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Revision History:
* Jan 2006 - Created.
*/
/*
* w32init.c implements the w32 module initialization and exit.
* Initialized 0x2E when the module is loaded , and restore it when the
* module is unloaded.
*/
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include "sysmap.h"
asmlinkage int w32system_call(void);
int set_w32system_gate(unsigned int, void *);
int backup_idt_entry(unsigned int n, unsigned long *a, unsigned long *b);
int restore_idt_entry(unsigned int n, unsigned long a, unsigned long b);
int init_syscall_table();
unsigned long orig_idt_2e_a, orig_idt_2e_b;
__attribute__((regparm(3)))
void do_apc(struct pt_regs *regs, sigset_t *oldset,
__u32 thread_info_flags)
{
/* deal with w32 APC, to be implemented */
}
static int w32_init(void)
{
if(init_syscall_table() != 0)
{
printk("Module not loaded.system call table initialize faild!\n");
return -1;
}
/* store the original address that the 0x2E points */
if (backup_idt_entry(0x2E, &orig_idt_2e_a, &orig_idt_2e_b) == -1) {
printk("Module not loaded. backup_idt_entry error: bad idt entry\n");
return -1;
}
/* initialize 0x2E */
if (set_w32system_gate(0x2E, &w32system_call) == -1) {
printk("Module not loaded. set_w32system_gate error: bad idt entry\n");
return -1;
}
printk("Module w32 On! vector 0x2E initialized for w32 syscall!\n");
return 0;
}
static void w32_exit(void)
{
/* restore 0x2E */
restore_idt_entry(0x2E, orig_idt_2e_a, orig_idt_2e_b);
printk("Module w32 Off!\n");
}
int backup_idt_entry(unsigned int n, unsigned long *a, unsigned long *b)
{
unsigned long *gate_addr;
struct desc_struct *idt_table;
char szidt[8];
asm("sidt %0"::"m"(*szidt));
idt_table = *(struct desc_struct**)(szidt+2);
/* 0x20 ~ 0x2f could be backup */
if ((n & 0xfffffff0) != 0x20)
return -1;
gate_addr = (unsigned long *)(idt_table + n);
*a = *gate_addr;
*b = *(gate_addr + 1);
return 0;
}
int restore_idt_entry(unsigned int n, unsigned long a, unsigned long b)
{
unsigned long *gate_addr;
struct desc_struct *idt_table;
char szidt[8];
asm("sidt %0"::"m"(*szidt));
idt_table = *(struct desc_struct**)(szidt+2);
/* 0x20 ~ 0x2f could be restore */
if ((n & 0xfffffff0) != 0x20)
return -1;
gate_addr = (unsigned long *)(idt_table + n);
*gate_addr = a;
*(gate_addr + 1) = b;
return 0;
}
static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
{
__u32 *lp = (__u32 *)((char *)dt + entry*8);
*lp = entry_a;
*(lp+1) = entry_b;
}
static inline void pack_gate(__u32 *a, __u32 *b,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
*a = (seg << 16) | (base & 0xffff);
*b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}
int set_w32system_gate(unsigned int n, void *addr)
{
__u32 a, b;
struct desc_struct *idt_table;
char szidt[8];
asm("sidt %0"::"m"(*szidt));
idt_table = *(struct desc_struct**)(szidt+2);
/* 0x20 ~ 0x2f could be set */
if ((n & 0xfffffff0) != 0x20)
return -1;
pack_gate(&a, &b, (unsigned long)addr, __KERNEL_CS, 0xef, 0);
write_dt_entry(idt_table,n,a,b);
asm("lidt %0"::"m"(*szidt));
return 0;
}
typedef int (*PDO_SYSCALL_TRACE)(struct pt_regs *regs, int entryexit);
typedef void (*PDO_NOTIFY_RESUME)(struct pt_regs *regs, void *_unused,__u32 thread_info_flags);
typedef struct pt_regs * fastcall (*PSAVE_V86_STATE)(struct kernel_vm86_regs * regs);
typedef struct _KERNEL_CALL_TABLE
{
PDO_SYSCALL_TRACE pdo_syscall_trce;/*1*/
PDO_NOTIFY_RESUME pdo_notify_resume;/*2*/
PSAVE_V86_STATE psave_v86_state;/*3*/
}KERNEL_CALL_TABLE,*PKERNEL_CALL_TABLE;
KERNEL_CALL_TABLE kct;
int init_syscall_table()
{
int i;
unsigned long *p;
/*load system map file */
if(load_system_map() != 0)
{
printk("Module not loaded.system map load faild!\n");
return -1;
}
memset(&kct,0,sizeof(KERNEL_CALL_TABLE));
kct.pdo_syscall_trce = (PDO_SYSCALL_TRACE)get_addr_from_map("do_syscall_trace");
kct.pdo_notify_resume = (PDO_NOTIFY_RESUME)get_addr_from_map("do_notify_resume");
kct.psave_v86_state = (PSAVE_V86_STATE)get_addr_from_map("save_v86_state");
unload_system_map();
/*check the table*/
p = (long *)&kct;
for (i = 0; i < 3 ; i++)
{
if(p[i] == 0)
return -1;
}
return 0;
}
int do_syscall_trace(struct pt_regs *regs, int entryexit)
{
asm("jmp %0"::"r"(kct.pdo_syscall_trce));
return 0;
}
void do_notify_resume(struct pt_regs *regs, void *_unused,
__u32 thread_info_flags)
{
asm("jmp %0"::"r"(kct.pdo_notify_resume));
return;
}
struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
{
asm("jmp %0"::"r"(kct.psave_v86_state));
return 0;
}
// fastcall void setup_x86_bogus_stack(unsigned char * stk)
// {
// unsigned long *switch16_ptr, *switch32_ptr;
// struct pt_regs *regs;
// unsigned long stack_top, stack_bot;
// unsigned short iret_frame16_off;
// int cpu = smp_processor_id();
// /* reserve the space on 32bit stack for the magic switch16 pointer */
// memmove(stk, stk + 8, sizeof(struct pt_regs));
// switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
// regs = (struct pt_regs *)stk;
// /* now the switch32 on 16bit stack */
// stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
// stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
// switch32_ptr = (unsigned long *)(stack_top - 8);
// iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
// /* copy iret frame on 16bit stack */
// memcpy((void *)(stack_bot + iret_frame16_off), ®s->eip, 20);
// /* fill in the switch pointers */
// switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
// switch16_ptr[1] = __ESPFIX_SS;
// switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
// 8 - CPU_16BIT_STACK_SIZE;
// switch32_ptr[1] = __KERNEL_DS;
// }
module_init(w32_init);
module_exit(w32_exit);
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -