📄 section.c
字号:
/* * section.c * * Copyright (C) 2006 Insigme Co., Ltd * * Authors: * - Chenzhan Hu * * 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. */ /* * section.c: section syscall functions * Reference to Kernel-win32 code */#include <linux/module.h>#include "section.h"#include "objwait.h"#include "thread.h"#include <asm/uaccess.h>#include <linux/file.h>#include <linux/mman.h>#include <linux/win32_process.h>#ifdef CONFIG_UNIFIED_KERNELstatic int SectionConstructor(struct win32_object *, void *);static int SectionReconstructor(struct win32_object *, void *);static void SectionDestructor(struct win32_object *);static int SectionPoll(struct wait_table_entry *, struct ethread *);extern int data_section_map(struct win32_section *, unsigned long *, unsigned long, unsigned long, unsigned long);struct win32_object_class section_objclass = { oc_type: "SECTN", constructor: SectionConstructor, reconstructor: NULL, destructor: SectionDestructor, poll: SectionPoll,};static unsigned long prot2linux[] = { /* _PAGE_NOACCESS */ PROT_NONE, /* _PAGE_READONLY */ PROT_READ, /* _PAGE_READWRITE */ PROT_READ | PROT_WRITE, /* _PAGE_WRITECOPY */ PROT_READ, /* _PAGE_EXECUTE */ PROT_EXEC, /* _PAGE_EXECUTE_READ */ PROT_EXEC | PROT_READ, /* _PAGE_EXECUTE_READWRITE */ PROT_EXEC | PROT_READ | PROT_WRITE, /* _PAGE_EXECUTE_WRITECOPY */ PROT_EXEC | PROT_READ};/* * initialise the section object classes */void SectionClassInit(void){ InitObjectClass(§ion_objclass);} /* end SectionClassInit() *//* * open a section object, maybe creating if non-existent */NTSTATUSSTDCALLNtCreateSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL ){ HANDLE hSection; char *oname; struct win32_object *obj, *fobj = NULL; struct ethread *thread; struct section_args args; OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING obj_name; LARGE_INTEGER max_size; if (!(thread = thread_find())) return -EINVAL; if (ObjectAttributes) { if ((unsigned long)ObjectAttributes < TASK_SIZE) { /* FIXME */ if (copy_from_user(&obj_attr, ObjectAttributes, sizeof(obj_attr))) return -EFAULT; if(obj_attr.ObjectName){ if (copy_from_user(&obj_name, obj_attr.ObjectName, sizeof(obj_name))) return -EFAULT; obj_attr.ObjectName = &obj_name; args.ObjectAttributes = &obj_attr; oname = (char *)(obj_name.Buffer); } else { obj_attr.ObjectName = NULL; args.ObjectAttributes = &obj_attr; oname = NULL; } } else { args.ObjectAttributes = ObjectAttributes; oname = (char *)(ObjectAttributes->ObjectName->Buffer); } } else { args.ObjectAttributes = NULL; oname = NULL; } if (MaximumSize) { if ((unsigned long)MaximumSize < TASK_SIZE) { /* FIXME */ if (copy_from_user(&max_size, MaximumSize, sizeof(max_size))) return -EFAULT; args.MaximumSize = &max_size; } else args.MaximumSize = MaximumSize; } else args.MaximumSize = NULL; /* gain access to the file */ if (FileHandle) { etget(thread); fobj = GetObject(thread, FileHandle, &file_objclass); etput(thread); if (IS_ERR(fobj)) return PTR_ERR(fobj); } /* create a section_args struct */ args.DesiredAccess = DesiredAccess; args.SectionPageProtection = SectionPageProtection; args.AllocationAttributes = AllocationAttributes; args.FileHandle = FileHandle; args.FileObject = fobj; /* create a section object */ etget(thread); obj = CreateObject(thread, §ion_objclass, oname, &args, &hSection); etput(thread); if (IS_ERR(obj)) { if (fobj) objput(fobj); return (NTSTATUS)PTR_ERR(obj); } ktrace("*** NtCreateSection(%p) = %p\n",obj,hSection); objput(obj); if (fobj) objput(fobj); if ((unsigned long)SectionHandle < TASK_SIZE && copy_to_user(SectionHandle, &hSection, sizeof(hSection))) return -EFAULT; else return STATUS_SUCCESS;} /* end NtCreateSection() *//* * map a view of the section to the process's address space */NTSTATUSSTDCALLNtMapViewOfSection( IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN ULONG CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect ){ NTSTATUS status = -EINVAL; size_t size = 0; unsigned long addr = 0; unsigned long flags = 0; struct win32_object *sec_obj, *proc_obj = NULL; struct ethread *thread; struct eprocess *process; LARGE_INTEGER sec_off = {.QuadPart = 0}; if (!(thread = thread_find())) return -EINVAL; if (BaseAddress) { if (copy_from_user(&addr, BaseAddress, sizeof(PVOID))) return -EFAULT; } if (addr) { /* fixed address map, align to 64k */ flags = MAP_FIXED; addr = (addr + BASE_ADDRESS_ALIGN - 1) & ~(BASE_ADDRESS_ALIGN - 1); } /* map offset, aligned to PAGE_SIZE */ if (SectionOffset) { if (copy_from_user(&sec_off, SectionOffset, sizeof(sec_off))) return -EFAULT; /* TODO: not support 64bit offset */ if (sec_off.u.HighPart) return -EINVAL; } sec_off.u.LowPart &= PAGE_MASK; if (ViewSize) { if (copy_from_user(&size, ViewSize, sizeof(size))) return -EFAULT; } /* access the section object */ etget(thread); sec_obj = GetObject(thread, SectionHandle, §ion_objclass); if (IS_ERR(sec_obj)) { etput(thread); return PTR_ERR(sec_obj); } if (!ProcessHandle || ProcessHandle == NtCurrentProcess()) { process = thread->threads_process; etput(thread); } else { proc_obj = GetObject(thread, ProcessHandle, &process_objclass); etput(thread); if (IS_ERR(proc_obj)) { objput(sec_obj); return PTR_ERR(proc_obj); } process = proc_obj->o_private; } status = MmMapViewOfSection( (PVOID)sec_obj, process, BaseAddress ? (void *)&addr : NULL, ZeroBits, CommitSize, SectionOffset ? (PLARGE_INTEGER)&sec_off : NULL, ViewSize ? (PSIZE_T)&size : NULL, InheritDisposition, AllocationType, Protect ); /* return the address if sucess */ if (!status) if(copy_to_user(BaseAddress, &addr, sizeof(PVOID))) status = -EFAULT; if (proc_obj) objput(proc_obj); objput(sec_obj); ktrace("*** NtMapViewOfSection(%p) = %d\n", sec_obj, status); return status;} /* end NtMapViewOfSection() *//* * unmap a mapped view of the file * - the view must start _exactly_ on the address */NTSTATUSSTDCALLNtUnmapViewOfSection( IN HANDLE ProcessHandle, IN PVOID BaseAddress ){ /* only unmap DATA SECTION */ struct vm_area_struct *vma; struct mm_struct *mm; unsigned long len, addr; NTSTATUS ret = -EINVAL; /* TODO: how to unmap PE IMAGE */ ktrace("*** NtUnmapViewOfSection %p\n", BaseAddress); mm = current->mm; addr = (unsigned long)BaseAddress; vma = find_vma(mm, addr); if (vma) { struct win32_section *ws; if ((ws = (struct win32_section *)vma->vm_private_data) && ws->ws_munmap) return ws->ws_munmap(ws); len = vma->vm_end - vma->vm_start; /* grab the process's memory mapping semaphore */ down_write(&mm->mmap_sem); /* do the munmap operation */ ret = do_munmap(mm, addr, len); /* release the process's memory mapping semaphore */ up_write(&mm->mmap_sem); } return ret;} /* NtUnmapViewOfSection() *//* * NtQuerySection */NTSTATUS STDCALLNtQuerySection(IN HANDLE SectionHandle, IN SECTION_INFORMATION_CLASS SectionInformationClass, OUT PVOID SectionInformation, IN ULONG SectionInformationLength, OUT PULONG ResultLength OPTIONAL){ struct win32_section *ws; struct win32_object *sec_obj; struct ethread *thread; long len; PSECTION_IMAGE_INFORMATION sii; PSECTION_BASIC_INFORMATION sbi; ktrace("NtQuerySection\n"); if(!(thread = thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } sec_obj = GetObject(thread, SectionHandle, §ion_objclass); if (IS_ERR(sec_obj)) { kdebug("can't find created eprocess\n"); return -EINVAL; } ws = sec_obj->o_private; switch (SectionInformationClass) { case SectionBasicInformation: if(!(sbi = kmalloc(sizeof(SECTION_BASIC_INFORMATION), GFP_KERNEL))) { kdebug("***error malloc, No memory\n"); return -ENOMEM; } sbi->Attributes = ws->ws_alloctype; if (ws->ws_alloctype & _SEC_IMAGE) { sbi->BaseAddress = 0; sbi->Size.QuadPart = 0; } else { sbi->BaseAddress = (void *)ws->ws_sections->wis_rva; sbi->Size.QuadPart = ws->ws_sections->wis_size; } if (ResultLength != NULL) { len = sizeof(SECTION_BASIC_INFORMATION); if(copy_to_user(ResultLength, &len, sizeof(long))) { kdebug("wrong copy to user\n"); kfree(sbi); return -EFAULT; } } if (copy_to_user(SectionInformation, sbi, sizeof(*sbi))) { kdebug("wrong copy to user\n"); kfree(sbi); return -EFAULT; } break; case SectionImageInformation: if(!(sii = kmalloc(sizeof(SECTION_IMAGE_INFORMATION), GFP_KERNEL))) { kdebug("***error malloc, No memory\n"); return -ENOMEM; } if(ws->ws_alloctype & _SEC_IMAGE) { sii->EntryPoint = ws->ws_entrypoint; sii->StackReserve = ws->ws_stackresv; sii->StackCommit = ws->ws_stackcommit; sii->Subsystem= ws->ws_subsystem; sii->MinorSubsystemVersion = ws->ws_minorver; sii->MajorSubsystemVersion = ws->ws_majorver; sii->Characteristics = ws->ws_imagecharacter; sii->ImageNumber = ws->ws_machine; sii->Executable = ws->ws_executable; } if (ResultLength != NULL) { len = sizeof(SECTION_IMAGE_INFORMATION); if(copy_to_user(ResultLength, &len, sizeof(long))){ kdebug("wrong copy to user\n"); kfree(sii); return -EFAULT; } } if (copy_to_user(SectionInformation, sii, sizeof(*sii))) { kdebug("wrong copy to user\n"); kfree(sii); return -EFAULT; } break; default: break; } objput(sec_obj); return STATUS_SUCCESS;} /* end NtQuerySection *//* * construct a section access object (allocate its private data) * - called by CreateObject if the section does not already exists * - called with data pointing to section_args arguments * - hFile replaced with file struct win32_object pointer (or NULL) */static int SectionConstructor(struct win32_object *obj, void *data){ int tmp, err; struct win32_section *ws; struct section_args *args = (struct section_args *)data; ktrace("SectionConstructor(%p)\n", obj); /* construct the section information record */ ws = (struct win32_section *)kmalloc(sizeof(struct win32_section), GFP_KERNEL); if (!ws) return -ENOMEM; memset(ws, 0, sizeof(*ws)); obj->o_private = ws; ws->ws_obj = obj; /* attach the file */ ws->ws_fileobj = args->FileObject; if (ws->ws_fileobj) { ws->ws_wfile = ws->ws_fileobj->o_private; objget(ws->ws_fileobj); } /* TODO: 64bit size is not support */ err = -EINVAL; if (args->MaximumSize && args->MaximumSize->u.HighPart) goto failed; ws->ws_len = args->MaximumSize ? args->MaximumSize->u.LowPart : 0; /* TODO: PE IMAGE section is not support */ ws->ws_alloctype = args->AllocationAttributes; if (args->AllocationAttributes & _SEC_IMAGE) { if (!args->FileObject || image_section_setup(ws) < 0) goto failed; } else { /* translate the protection flags to syscall mmap() prot */ tmp = ffs(args->SectionPageProtection & 0x000000ff); if (tmp == 0 || tmp == 1) goto failed; ws->ws_protect = prot2linux[tmp - 1]; /* anonymous map, map len is need */ if (!args->FileObject && !ws->ws_len) goto failed; if (args->SectionPageProtection & _PAGE_WRITECOPY || args->SectionPageProtection & _PAGE_EXECUTE_WRITECOPY) /* copy on write */ ws->ws_flags |= MAP_PRIVATE; else /* shared map */ ws->ws_flags |= MAP_SHARED; /* get the file size, when paramter len is 0 */ if (!ws->ws_len && ws->ws_wfile) ws->ws_len = ws->ws_wfile->wf_file->f_dentry->d_inode->i_size; ws->ws_pagelen = PAGE_ALIGN(ws->ws_pagelen); if ((err = data_section_setup(ws)) < 0) goto failed; } return 0;failed: if (ws->ws_fileobj) objput(ws->ws_fileobj); kfree(ws); return err;} /* end SectionConstructor() *//* * reconstruct a section (allocate its private data) * - called by CreateObject if the section already exists * - for section, no operation is needed */static int SectionReconstructor(struct win32_object *obj, void *data){ return 0;} /* end SectionReconstructor() *//* * destroy a section (discard its private data) */static void SectionDestructor(struct win32_object *obj){ struct win32_section *ws = obj->o_private; ktrace("SectionDestructor(%p)\n",obj); /* discard the association with the file object */ if (ws->ws_fileobj) objput(ws->ws_fileobj); if (ws->ws_sections) kfree(ws->ws_sections); kfree(obj->o_private);} /* end SectionDestructor() *//* * never used for section */static int SectionPoll(struct wait_table_entry *wte, struct ethread *filp){ return POLL_NOTSIG;} /* end SectionPoll() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -