📄 virtual.c
字号:
/* * virtual.c * * Copyright (C) 2006 Insigme Co., Ltd * * Authors: * - Liwei Zhou * * 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. *//* * virtual.c: virtual memory handling * Reference to ReactOS code */#include "virtual.h"#include "attach.h"#include "../thread.h"#include "../process.h"#include "../section.h"#include "../object.h"#include "../w32syscall.h"#include <asm/page.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/slab.h>#include <asm/uaccess.h>#include <linux/personality.h>#ifdef CONFIG_UNIFIED_KERNELpgprot_t protection_map[16] = { __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111};/* * NtQueryVirtualMemory * Get the information of the virtual memory */NTSTATUS STDCALLNtQueryVirtualMemory (IN HANDLE ProcessHandle, IN PVOID Address, IN CINT VirtualMemoryInformationClass, OUT PVOID VirtualMemoryInformation, IN ULONG Length, OUT PULONG UnsafeResultLength){ NTSTATUS status; ULONG result_len, gap_size, base_addr; struct win32_object *obj; struct ethread *thread, *first_thread; struct eprocess *process; struct mm_struct *mm; struct vm_area_struct *vma; MEMORY_BASIC_INFORMATION Info; ktrace("NtQueryVirtualMemory\n"); thread = thread_find(); if (!thread) return -EINVAL; if (ProcessHandle==NtCurrentProcess() || !ProcessHandle) process = thread->threads_process; else { etget(thread); obj = GetObject(thread, ProcessHandle, &process_objclass); etput(thread); if (IS_ERR(obj)) return PTR_ERR(obj); process = obj->o_private; } first_thread = get_first_thread(process); mm = first_thread->et_task->mm; vma = find_vma(mm, (ULONG)Address); base_addr = (ULONG)Address & PAGE_MASK; switch (VirtualMemoryInformationClass) { case MemoryBasicInformation: if (Length !=sizeof(MEMORY_BASIC_INFORMATION)) return -EFAULT; if (!vma || vma->vm_start > (ULONG)Address) { gap_size = vma ? vma->vm_start - base_addr : mm->start_stack- base_addr; Info.Type = 0; Info.State = MEM_FREE; Info.Protect = PAGE_NOACCESS; Info.AllocationProtect = 0; Info.BaseAddress = (PVOID)base_addr; Info.AllocationBase = NULL; Info.RegionSize = gap_size; status = STATUS_SUCCESS; result_len = sizeof(MEMORY_BASIC_INFORMATION); } else { ULONG offset = pgd_index((ULONG)Address); /* Setup state */ if (((pgd_t *)(mm->pgd + offset))->pgd) Info.State = MEM_COMMIT; else Info.State = MEM_RESERVE; /* Setup allocation protect */ if (vma->vm_flags & VM_READ) { if (vma->vm_flags & VM_EXEC) Info.AllocationProtect = PAGE_EXECUTE_READ; else Info.AllocationProtect = PAGE_READ; } else if (vma->vm_flags & VM_WRITE) { if (vma->vm_flags & VM_EXEC) Info.AllocationProtect = PAGE_EXECUTE_READWRITE; else Info.AllocationProtect = PAGE_READWRITE; } else if (vma->vm_flags & VM_EXEC) { if (vma->vm_flags & VM_SHARED) Info.AllocationProtect = PAGE_EXECUTE_WRITECOPY; else Info.AllocationProtect = PAGE_EXECUTE; } else if (vma->vm_flags & VM_SHARED) Info.AllocationProtect = PAGE_WRITECOPY; else Info.AllocationProtect = 0; Info.Type = 0; Info.Protect = Info.AllocationProtect; Info.BaseAddress = (PVOID)base_addr; Info.AllocationBase = (PVOID)vma->vm_start; Info.RegionSize = vma->vm_end - vma->vm_start; status = STATUS_SUCCESS; result_len = sizeof(MEMORY_BASIC_INFORMATION); } break; default: ktrace("Unimplemented information class\n"); return -EFAULT; } if ((ULONG)VirtualMemoryInformation < TASK_SIZE) { if (copy_to_user(VirtualMemoryInformation, &Info, sizeof(MEMORY_BASIC_INFORMATION))) return -EFAULT; } else *(PMEMORY_BASIC_INFORMATION)VirtualMemoryInformation = Info; if (UnsafeResultLength) { if ((ULONG)UnsafeResultLength < TASK_SIZE) { if (copy_to_user(UnsafeResultLength, &result_len, sizeof(ULONG))) return -EFAULT; } else *UnsafeResultLength = result_len; } return status;} /* end NtQueryVirtualMemory *//* * MmCreateMemoryArea * Create a memory area */NTSTATUS STDCALLMmCreateMemoryArea(struct eprocess *Process, PMADDRESS_SPACE AddressSpace, ULONG Type, PVOID *BaseAddress, ULONG_PTR Length, ULONG Attributes, PMEMORY_AREA *Result, BOOLEAN FixedAddress, BOOLEAN TopDown, PHYSICAL_ADDRESS bound_addr_multi){ struct mm_struct *mm; struct task_struct *task; struct ethread *thread, *first_thread; struct vm_area_struct *vma; ULONG flags, prot; ULONG addr_page, size_page, address; NTSTATUS status = STATUS_SUCCESS; ktrace("MmCreateMemoryArea\n"); thread = thread_find(); if (!thread) return -EINVAL; if (Process == get_eprocess(thread)) task = current; else { first_thread = get_first_thread(Process); task = first_thread->et_task; } mm = task->mm; addr_page = (ULONG)(*BaseAddress) & PAGE_MASK; size_page = PAGE_ALIGN((ULONG)(*BaseAddress) + Length) - ((ULONG)addr_page); if (addr_page) { if (mm->start_stack && mm->end_data) if (mm->start_stack < addr_page + size_page || mm->end_data > addr_page) return -EFAULT; vma = find_vma(mm, addr_page); if (vma && vma->vm_start < addr_page + size_page) return -EFAULT; } switch (Attributes) { case PAGE_READ: prot = PROT_READ; flags = MAP_PRIVATE; break; case PAGE_READWRITE: prot = PROT_READ | PROT_WRITE; flags= MAP_PRIVATE; break; case PAGE_WRITECOPY: prot = 0; flags = MAP_SHARED; break; case PAGE_EXECUTE: prot = PROT_EXEC; flags = MAP_PRIVATE; break; case PAGE_EXECUTE_READ: prot = PROT_EXEC | PROT_READ; flags = MAP_PRIVATE; break; case PAGE_EXECUTE_READWRITE: prot = PROT_EXEC | PROT_READ | PROT_WRITE; flags = MAP_PRIVATE; break; case PAGE_EXECUTE_WRITECOPY: prot = PROT_EXEC; flags = MAP_SHARED; break; default: prot = 0; flags = 0; break; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(&mm->mmap_sem); address = win32_do_mmap_pgoff(task, TopDown, NULL, addr_page, size_page, prot, flags, 0); up_write(&mm->mmap_sem); *BaseAddress = (PVOID)address; return status;} /* end MmCreateMemoryArea *//* * NtAllocateVirtualMemory * Allocate a block of virtual memory in the process address space */NTSTATUS STDCALLNtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID* UBaseAddress, IN ULONG ZeroBits, IN OUT PULONG URegionSize, IN ULONG AllocationType, IN ULONG Protect){ struct ethread *thread, *first_thread; struct eprocess *process; struct win32_object *obj; struct mm_struct *mm; struct vm_area_struct *vma; PVOID address, addr_page; ULONG size, size_page; NTSTATUS status; PHYSICAL_ADDRESS bound_addr_multi; ktrace("NtAllocateVirtualMemory(%p,%p,%d,%p,%d,%d)\n", ProcessHandle, UBaseAddress, ZeroBits, URegionSize, AllocationType, Protect); bound_addr_multi.QuadPart = 0; /* Check the validity of the parameters */ if ((Protect & PAGE_FLAGS_VALID_FROM_USER_MODE) != Protect) return -EFAULT; if ((AllocationType & (MEM_COMMIT | MEM_RESERVE)) == 0) return -EFAULT; if ((ULONG)UBaseAddress < TASK_SIZE) { if (copy_from_user(&address, UBaseAddress, sizeof(PVOID))) return -EFAULT; } else address = *UBaseAddress; if ((ULONG)URegionSize < TASK_SIZE) { if (copy_from_user(&size,URegionSize,sizeof(ULONG))) return -EFAULT; } else size = *URegionSize; thread = thread_find(); if (!thread) return -EINVAL; if (ProcessHandle == NtCurrentProcess() || !ProcessHandle) process = thread->threads_process; else { etget(thread); obj = GetObject(thread, ProcessHandle, &process_objclass); etput(thread); if (IS_ERR(obj)) return PTR_ERR(obj); process = obj->o_private; } first_thread = get_first_thread(process);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -