Memory segment permissions per user/group - any way to achieve this? - memory-management

We know there are rwxp/s permissions on memory segments of an elf executable.
Now, I have a user or a group, and I would like them to see .text segment (read access) of a certain executable but nothing else (no access to .bss or .data or .stack). Is there a way to achieve this?
Use case - a not trusted observer to whom I want to prove what the code is doing without disclosing any data the code operates upon.

Related

How does a PE file get mapped into memory?

So I have been reasearching the PE format for the last couple days, and I still have a couple of questions
Does the data section get mapped into the process' memory, or does the program read it from the disk?
If it does get mapped into its memory, how can the process aqquire the offset of the section? ( And other sections )
Is there any way the get the entry point of a process that has already been mapped into the memory, without touching the file on disk?
Does the data section get mapped into the process' memory
Yes. That's unlikely to survive for very long, the program is apt to write to that section. Which triggers a copy-on-write page copy that gets the page backed by the paging file instead of the PE file.
how can the process aqquire the offset of the section?
The linker already calculated the offsets of variables in the section. It might be relocated, common for DLLs that have an awkward base address that's already in use when the DLL gets loaded. In which case the relocation table in the PE file is used by the loader to patch the addresses in the code. The pages that contain such patched code get the same treatment as the data section, they are no longer backed by the PE file and cannot be shared between processes.
Is there any way the get the entry point of a process
The entire PE file gets mapped to memory, including its headers. So you can certainly read IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint from memory without reading the file. Do keep in mind that it is painful if you do this for another process since you don't have direct access to its virtual address space. You'd have to use ReadProcessMemory(), that's fairly little joy and unlikely to be faster than reading the file. The file is pretty likely to be present in the file system cache. The Address Space Layout Randomization feature is apt to give you a headache, designed to make it hard to do these kind of things.
Does the data section get mapped into the process' memory, or does the program read it from the disk?
It's mapped into process' memory.
If it does get mapped into its memory, how can the process aqquire the offset of the section? ( And other sections )
By means of a relocation table: every reference to a global object (data or function) from the executable code, that uses direct addressing, has an entry in this table so that the loader patches the code, fixing the original offset. Note that you can make a PE file without relocation section, in which case all data and code sections have a fixed offset, and the executable has a fixed entry point.
Is there any way the get the entry point of a process that has already been mapped into the memory, without touching the file on disk?
Not sure, but if by "not touching" you mean not even reading the file, then you may figure it out by walking up the stack.
Yes, all sections that are described in the PE header get mapped into memory. The IMAGE_SECTION_HEADER struct tells the loader how to map it (the section can for example be much bigger in memory than on disk).
I'm not quite sure if I understand what you are asking. Do you mean how does code from the code section know where to access data in the data section? If the module loads at the preferred load address then the addresses that are generated statically by the linker are correct, otherwise the loader fixes the addresses with relocation information.
Yes, the windows loader also loads the PE Header into memory at the base address of the module. There you can file all the info that was in the file PE header - also the Entry Point.
I can recommend this article for everything about the PE format, especially on relocations.
Does the data section get mapped into the process' memory, or does the
program read it from the disk?
Yes, everything before execution by the dynamic loader of operating systems either Windows or Linux must be mapped into memory.
If it does get mapped into its memory, how can the process acquire the
offset of the section? ( And other sections )
PE file has a well-defined structure which loader use that information and also parse that information to acquire the relative virtual address of sections around ImageBase. Also, if ASLR - Address randomization feature - was activated on the system, the loader has to use relocation information to resolve those offsets.
Is there any way the get the entry point of a process that has already
been mapped into the memory, without touching the file on disk?
NOPE, the loader of the operating system for calculation of OEP uses ImageBase + EntryPoint member values of the optional header structure and in some particular places when Address randomization is enabled, It uses relocation table to resolve all addresses. So we can't do anything without parsing of PE file on the disk.

windows memory segmentation & Ollydbg

a few questions about windows memory segmentation.
every process in windows got his own virtual memory. does it mean that each each process has it own task
(I mean own Task descriptor or Task gate) ?
I opened a simple exe with ollydbg and I saw that for each CALL intruction to a dll function is taking me to the jumping table. the jumping table had jumping instructions to the DLLs like this one :
JMP DWORD PTR DS:[402058]
my question is why its uses the data segment and not the CS selector for the base address?
if I open the memory map and find what stored at 402058 I find that it containes resorces.
if I understand correctly the addresses of the DLL function stored in the DS ?
I noticed that the memory map is organized by owner. shouldn't it be organized with segments like all the code be in CS data in DS etc ?
thank you
1.
A Process has it's own virtual address space.
I do not understand what you're referring to as "Task descriptor or Task gate", but the Windows operating system holds a descriptor for each process, called the Process Control Block, that contains information about the process (such as identification, access tokens, execution state, virtual memory mapping, etc).
A Task is a logical unit that can be used to manage a single process, or multiple processes.
Job -> Tasks
Task -> Processes
Process -> Threads
2.
In the case you mentioned, which is common for compilers, the program uses the .DATA section to store the jump table after loading the function addresses.
The reason why this happens in the first place is because the compiler cannot know the DLL base address at compile-time, therefore the address has to be fixed at load-time to point to the function. This is known as Relocation.
In order to maintain the jump table seperately from the code, compilers store it in the .DATA section. This way, we can also give it write permissions (usually the .DATA segment has write permissions) and modify it as necessary without sacrificing stability and security.
3.
Each module loaded in the process' virtual address space contains it's own sections - that's why you see a different set of .text, .data, .reloc etc for each module. The "Owner" column is the module name.
P.S. Please ask one question per post - that way it will be easily accesible by other users after you get answered, and each question will likely get more accurate answers.

Change user space memory protection flags from kernel module

I am writing a kernel module that has access to a particular process's memory. I have done an anonymous mapping on some of the user space memory with do_mmap():
#define MAP_FLAGS (MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS)
prot = PROT_WRITE;
retval = do_mmap(NULL, vaddr, vsize, prot, MAP_FLAGS, 0);
vaddr and vsize are set earlier, and the call succeeds. After I write to that memory block from the kernel module (via copy_to_user), I want to remove the PROT_WRITE permission on it (like I would with mprotect in normal user space). I can't seem to find a function that will allow this.
I attempted unmapping the region and remapping it with the correct protections, but that zeroes out the memory block, erasing all the data I just wrote; setting MAP_UNINITIALIZED might fix that, but, from the man pages:
MAP_UNINITIALIZED (since Linux 2.6.33)
Don't clear anonymous pages. This flag is intended to improve performance on embedded
devices. This flag is only honored if the kernel was configured with the
CONFIG_MMAP_ALLOW_UNINITIALIZED option. Because of the security implications, that option
is normally enabled only on embedded devices (i.e., devices where one has complete
control of the contents of user memory).
so, while that might do what I want, it wouldn't be very portable. Is there a standard way to accomplish what I've suggested?
After some more research, I found a function called get_user_pages() (best documentation I've found is here) that returns a list of pages from userspace at a given address that can be mapped to kernel space with kmap() and written to that way (in my case, using kernel_read()). This can be used as a replacement for copy_to_user() because it allows forcing write permissions on the pages retrieved. The only drawback is that you have to write page by page, instead of all in one go, but it does solve the problem I described in my question.
In userspace there is a system call mprotect that can modify the protection flags on existing mapping. You probably need to follow from the implementation of that system call, or maybe simply call it directly from your code. See mm/protect.c.

VirtualQueryEx how do i parse the results (how do i know if the page is readable or not by ReadProcessMemory?)

I am trying to learn how to access other process's memory. I'm using ReadProcessMemory but it fails, supposedly because i'm reading from an unaccessible memory. I think I should use VirtualQueryEx first to find out if the memory I'm trying to read is readable, but I don't know how to parse the results of VirtualQueryEx.
VirtualQueryEx returns a structure described here http://msdn.microsoft.com/en-us/library/windows/desktop/aa366775%28v=vs.85%29.aspx
Is there any good simple way to know whether the values in the MEMORY_BASIC_INFORMATION structure tell that the page is readable by ReadProcessMemory or not?
This structure has several parameters that, from what I understand, define whether or not memory is accessible:
DWORD AllocationProtect;
DWORD State;
DWORD Protect;
DWORD Type;
Its not even clear on what combination of parameters actually allows reading the memory (for example, should I read Protection flag from AllocationProtect or Protect, does State other than Commit mean that memory is unreadable, etc) and making a huge if (this is that and that is that or this is that....) doesn't seem like a clean solution.
There's got to be a better way, but I don't seem to be able to find it...
Actually the clue is in the documentation you linked:
AllocationProtect
The memory protection option when the region was initially allocated. This member can be one
of the memory protection constants or 0 if the caller does not have access.
VirtualProtect or VirtualProtectEx could have been used meanwhile to change the protection (per-page, while the initial protection was for the whole allocated range). So you'd have to check the Protect member of the structure against the Memory Protection Constants in the MSDN documentation that state that read is allowed. Checking for a single bit doesn't seem to be enough.

Unexpected behavior of write operations when creating a custom section in EEPROM using GCC

Here is my question,
I work on an application embeded in a board we manufactured ourselves for a space project.
The board uses a LEON2 Processor which is a derivate of SPARC v8 and we also use RTEMS as OS.
In this application we have to save default value for various tables for the FS in the EEPROM, so the user can modify them how he wants without having to do it everytime.
To achieve this I simply created a new section (.eeprom_data) and I placed it at address 0x6007cc40 which is in the EEPROM. It was done by using a specs file and a custom linker script which located the section at the correct address and told the compiler to put certain variables in this same section.
It seems to be working fine in this regard.
Here is an extract of objdump for the section and one particular var:
6 .eeprom_data 000033c0 6007cc40 6007cc40 00038a80 2**3
CONTENTS, ALLOC, LOAD, DATA
6007fbda g O .eeprom_data 00000002 Downlink_Priority_Vc1_default_value
The only problem is that it seems not to be fully working. My application runs correctly with no problem but doing a simple test like this only partially work:
Eeprom_ChipEnable(TRUE);
managed_faulty_sectors_default_crc = 0x789A;
tmp = managed_faulty_sectors_default_crc;
Eeprom_ChipEnable(FALSE);
The write operation which should write 0x789A in EEPROM does absolutely nothing
The read operation however works perfectly and returns correctly the data that is stored in the memory.
I don't really know how to solve this problem so I hope someone can give me a hand.
Thanks, Léo.
Thanks for your answers.
For some reason, when the HW engineer designed our board they did not allow the addressing of single 16 bits address only 32 bits address..
Are you sure the data cache (if any) is flushed before you disable the EEPROM?
And, are the EEPROM variables properly declared volatile?
Do you compile with optimization flags ?
I'd guess the compiler to optimize away the write unless managed_faulty_sectors_default_crc is declared volatile .
Also how is managed_faulty_sectors_default_crc mapped to the .eeprom_data section - does objdump give any clue as to wether they're mapped correctly ?

Resources