First of all I need to know addresses in System.map or /proc/kallsyms are virtual or physical?
then I want to read from addresses of kernel symbols, for example I want to read pid field of init_task symbol. I can find init_task address from System.map and also offset of pid. but I don't know how to read from an address in kernel.
I really appreciate any reference or link to say things in detail because I'm not familiar with kernel programming.
another question: when they say DKOM(dynamic kernel object manipulation) what does it mean? I searched but just find something about windows system!
and when they say you can access exported symbols in LKM? what operations do they mean? are specific functions to read or write from kernel symbols?
Just about any pointer address you can see is virtual. Its either user space process virtual space (namely your process), or the kernel virtual address space. It is only when the kernel needs to inform one hardware component how to access another that it will convert the pointer to is physical representation.
Its worth noting that event the physical address space is virtual in the sense that different hardware component are pragmatically assigned memory ranges and are expected to react when those are addressed. It is still very physical in the sense that those address values are the ones that are encoded on the BUS address and no software translation is needed.
As for reading/writing kernel pointers from userspace. Unless granted by a specific API and setup both by the user and the kernel (like shared memory), you can't. Its the most basic security protection etched into core of the operating system. (you can't even access the memory of another user for that matter).
Having said that, if you wish to intentionally decrease your kernel security, as root you may do just about anything, including loading a module that does just that...
here is another discussion on the same topic:
how-to-access-kernel-space-from-user-spacein-linux
First, addresses in System.map or /proc/kallsyms are virtual addresses.
Second, if you'd like traverse data structure in kernel, you could use Crash tool. It is based on gdb, easy to use. But you should recompile your kernel with debug information first. With crash tool, you can easily read every data structure of kernel in user space. And it supports multiply distributions, like Ubuntu, Fedora, and so on.
Another tool is Volatility, wrote by Python, you could take a snapshot of your system. Then read the memory snapshot with Volatility.
Related
This may be regarded as a naive question.
I'm used to bare-metal programming where I changed register values manually in order to write in the GPIO. Conversely, I read those same registers when needing information.
I've recently moved to embedded linux. I've remarked that now dealing with the GPIO cannot be done from code running in the user space.** I can imagine there it might be some security/sanity reason for this but I cannot see it. Why can't code from user space read/write in the GPIO? An example on a problem that could be caused by that would be great.
** I am aware of libraries/APIs that enable you to deal with the GPIO from user-space, and I am learning to use them. My question is pure out of curiosity.
On some platforms it can be, but it's usually avoided.
Typically Linux runs on hardware with an MMU providing both page-level memory protection, and remapping of a virtual address space to physical addresses.
To access a memory-mapped GPIO from userpace, you'd need to configure the MMU to map the register hardware address into the desired process's virtual address space, and you'd need to enable read and/or write access to that page.
The problem though is that the granularity is typically poor - a memory page may be something like 4 kilobytes, while a GPIO pin's behavior is governed by a few distinct bits in several different registers. So it's not possible to expose an individual pin to a given process.
Additionally, doing this from userspace would require knowing the precise hardware details of how GPIO works on a given platform, and that's information which usually better belongs in a driver.
There are a few cases where using the sysfs interface is too slow, for example trying to bit-bang some slower interfaces. But typically in those cases rather than trying to handle the GPIO directly from userspace, a kernel module is written which does the bit-banging from kernel space, and then userspace uses a syscall to pass entire mid- to high- level operation requests to the kernel.
I'm totally a newbie in embedded software. Currently, I'm working on a project that implements an image processing pipeline on an ARM Cortex-M4 based MCU(board model: STM32F446RE).
I would like to be able to configure the parameters of the pipeline on the fly without actually update the entire firmware since we're using LoRa which has low bandwidth.
I have googled for several hours and could not find any valid solution. So could you please point me in a direction? Thank you very much.
BTW, I don't know if this is relevant, but I'm using FreeRTOS kernel with CMSIS RTOS API v2.
If you are asking this question, I would hope that either:
The board is still under design or
You have a board that was designed by someone who has thought about these issues.
If #2, speak to whoever designed the board, and find out what resources were put in, to handle these issues.
If #1, presumably you have input into the design.
Necessary resources:
Non-volatile storage: flash, eeprom, etc.
One or more ways to write parameters to that non-volatile storage
Desirable resource: communication line for input/output while running (serial is often used).
Once you have these resources, you do the following:
Design the variables, data structures, etc. to hold the parameters
Design your non-volatile storage, taking into account:
a. The features/limitations of your media (for example, flash memory generally requires an erase before writing. Erase takes time and must be done by sector, not individual bytes.
b. Verification: your program should have a way to verify that the non-volatile storage has valid values, not garbage, not all 0xFFs, and either fail or use defaults or some such, if it is not valid
Then you can write a program using this.
You need to consider how you will write the values to the non-volatile memory
during development
in production
They are not likely to be the same.
During development, you want to be able to easily change values. You may have a way to burn your flash chip via a JTAG. You may have a communications port which either runs some kind of simple CLI, accepts commands via some protocol, asks questions and reads the answers via a terminal emulator, etc. The program can then write the values to the non-volatile memory.
In production, you will likely want to burn the 'correct' values once, when setting up the system, without too much operator involvement.
This is just a starting guideline...as mentioned in the comments, your question is very general.
I am trying to understand the way the filesystem and the kernel are related, and how they work together, specifically regarding the permissions.
(I know that, in fact, the filesystem is running in kernel space, but in this context I consider them as two separates entities.)
When Bob (UID=1001, GID=1001, groups="humans, minor") tries to read "file.txt" which is, let's say, "rwx r-- --x" with "owner = Alice" and "group owner = minor" -- which one, of the kernel and
the filesystem, permits access?
Does the filesystem have a function taking as parameters the entire list of Bob's groups, Bob's UID and other stuff sent by the kernel (which would allow the filesystem to determine whether Bob can or cannot read the targeted file)?
Furthermore, if this is the way it works -- how does the kernel know the data the filesystem needs for extended/special attributes? In the case of synology extended attributes (ext4/btrfs) for example.
Many thanks for any help / resources to read.
Good day to you!
In my opinion -- when the Kernel receives a request from a User (for example, to open a file), it then analyses the User's access rights. If they are correct -- the Kernel manages the hardware to provide the User with the requested data.
In a context of a computer system (consisting of a Kernel and a File-System; also including hardware to input, to store and to output the data), the File-System itself has no possibility of making decisions (like the Kernel do); it is just an informational structure, written in a manner defined by the rules of operating it (to which the Kernel must have an access, in order to interact correctly; these rules may be stored in the Kernel). So, the Kernel makes decisions on providing access (and if it is to fulfil the request, the Kernel operates the data). And the File-System is a set of both stored data on some hardware, and a software part (as the instructions to the Kernel: how to manipulate the hardware's physical layer and, maybe, how to decide on access-providing on a logical layer); but the decisive role, again, is up to the Kernel (which must accord to all the provided rules).
This variant is just a variant, and it may vary in various operating system realizations. I don't know, in which of them it is implemented (whether this is OS "Linux" or OS "Windows" approach, or maybe not).
And for example, if we describe a remote cloud-storage to which the User connects -- this storage (something in it that acts as a described Kernel; maybe, its Kernel) decides whether to grant the access or not; and the local Kernel acts as a User, to which the remote system is like a Kernel.
Also, I saw a similar (or relative) question here, on "Stack Overflow", too: What does opening a file actually do? -- maybe, there you will find some additional information.
I've learned that a process has the following structure in memory:
(Image from Operating System Concepts, page 82)
However, it is not clear to me what decides that a process looks like this. I guess processes could (and do?) look different if you have a look at non-standard OS / architectures.
Is this structure decided by the OS? By the compiler of the program? By the computer architecture? A combination of those?
Related and possible duplicate: Why do stacks typically grow downwards?.
On some ISAs (like x86), a downward-growing stack is baked in. (e.g. call decrements SP/ESP/RSP before pushing a return address, and exceptions / interrupts push a return context onto the stack so even if you wrote inefficient code that avoided the call instruction, you can't escape hardware usage of at least the kernel stack, although user-space stacks can do whatever you want.)
On others (like MIPS where there's no implicit stack usage), it's a software convention.
The rest of the layout follows from that: you want as much room as possible for downward stack growth and/or upward heap growth before they collide. (Or allowing you to set larger limits on their growth.)
Depending on the OS and executable file format, the linker may get to choose the layout, like whether text is above or below BSS and read-write data. The OS's program loader must respect where the linker asks for sections to be loaded (at least relative to each other, for executables that support ASLR of their static code/data/BSS). Normally such executables use PC-relative addressing to access static data, so ASLRing the text relative to the data or bss would require runtime fixups (and isn't done).
Or position-dependent executables have all their segments loaded at fixed (virtual) addresses, with only the stack address randomized.
The "heap" isn't normally a real thing, especially in systems with virtual memory so each process can have their own private virtual address space. Normally you have some space reserved for the stack, and everything outside that which isn't already mapped is fair game for malloc (actually its underlying mmap(MAP_ANONYMOUS) system calls) to choose when allocating new pages. But yes even modern glibc's malloc on modern Linux does still use brk() to move the "program break" upward for small allocations, increasing the size of "the heap" the way your diagram shows.
I think this is recommended by some committee and then tools like GCC conform to that recommendation. Binary format defines these segments and operating system and its tools facilitate the process of that format to run on system. lets say ELF is recommended by system V and then adopted by unix; and gcc produce the ELF binaries to be run on unix. so i feel story may start from binary format as it decides about memory mappings(code, data/heap/stack). binary format,among other hacks, defines memory mappings to be mapped for loading programs. As for example ELF defines segments (arrange code in text,data,stack to be loaded in memory), GCC generates that segments of ELF binary while loader loads these segments. operating system also has freedom in adjusting the values of these segments like stack size. These are debatable loud thoughts which I try to consolidate.
That figure represents a a specific implementation or an idealized one. A process does not necessarily have that structure. On many systems a process looks only somewhat similar to what is in the diagram.
I'm interested in operating systems topic and I have a dummy question. Standard PE executable files are linked to 0x400000. My question is how can operating system load multiply executables with same image base, when virtual memory just maps virtual addresses to physical. Is it storing PDE and PTE index of thread somewhere? Is there some addition to each address before execution starts? How does it work?
Each process gets its own virtual address space, and hence there's no conflict. All virtual address spaces that exist in any one time in the system get mapped into the physical address space. Virtual memory that can't or currently isn't mapped onto a particular physical memory is held in the swap file (swap partition, or alike) — this is called paging.
During thread switches, when the CPU is about to execute a thread from a different process than it was executing so far, the operating system's scheduler informs the CPU (sets the respective registers) about the new virtual address translation table to use. Thus the CPU thinks there's just one virtual address space at the given time, while the operating system can manage many more, one for each process.
Disclaimer: My answer may be a thought of as a bit superficial or imprecise as opposed to the reality. This for the sake of simplicity in respect to the nature of the OPs question. Also, these mechanisms are CPU-dependent and operating system-dependent.