Image this way to invade Linux: 1. malloc a space. 2. write binary code to this region. 3. jump to this code.
I want to forbid this way to run code. Only run code in .text section. What should I do to the Linux kernel? Thank you!
The PaX security patch to linux address this concern by ensuring that no memory in RAM is both writeable and executable. This ensures that one can not allocate memory into RAM, write code to it, and then execute it (which seems exactly what you are trying to prevent).
https://en.wikipedia.org/wiki/PaX#Executable_space_protections
Note that you may have to compile a custom kernel to install this patch. Alternatively, try seeing if your distribution offers a linux kernel with the patch installed. (Search for linux-grsec or linux-pax).
Related
I have a project in mind and for that I require the kernel to boot up and bring me to a console window so that I can start working. [later I'll automate the process].
How do I accomplish it?
Well, I have downloaded the latest stable kernel source from kernel.org and I have tried editing the init/main.c file. But I have no idea what in the world was going on in that file [noob ^n].
Hence, I post this question for an answer.
I require the kernel to boot up and bring me to a console window so that I can start working.
The kernel doesn't do much by itself. In fact, it's unlikely you want to alter "main" in the kernel.
If you want to "run" the kernel, you'll also need a root filesystem and some user-space programs. If you want a minimal userland, you can use "busybox". Even better, buildroot will help you create a minimal userland + kernel.
You can even combine your root filesystem plus the kernel into a single binary. At runtime, it will uncompress userland into a ramdisk and run entirely from RAM. See initramfs. This is super-helpful for embedded systems. A minimal kernel+root filesystem can be around 1MB.
Go through below link
http://balau82.wordpress.com/2010/03/27/busybox-for-arm-on-qemu/
Just black screen after running Qemu
I am trying to compile the kernel from downloaded source. I made the kernel image using sources from kernel.org.
I have successfully loaded it into grub, but when I try to run the loaded module it gives error message: "invalid magic number". I am not getting what I need to fix to get the things done.
Steps that I've followed:
make xconfig,
make bzImage
make modules
make modules_install
I also changed the name of image from bzImage (in /boot folder), then created initrd image from:
# dracut /boot/initramfs-3.1.6-1.fc16.x86_64.img 3.1.6-1.fc16.x86_64 (command copied from net)
Every time you compile a kernel, you must re-compile also the kernel module that you need to use within that kernel. For example, you cannot load a module compiled for kernel 2.6.39 on kernel 3.7. You must recompile it for kernel 3.7.
More details --> better answer
Actually I doubt this has anything to do with kernel modules. As it seems the kernel itself is being refered to as a module. It is possible the kernel got built incorrectly or is being loaded incorrectly possibly from the grub commandline.
http://forums.gentoo.org/viewtopic-t-932358-start-0.html try that.
It is possible that some file in the kernel build didn't get cleaned up properly an so has incorrect data in it since any changes you made in a previous attempt at building it.
Also do note that the x86 images will end up at arch/x86_64/boot/bzImage or arch/x86/boot/bzImage inside the kernel source make sure you actually have copied the kernel itself and not some other incorrect file.
If that fails try grub 1.x as its simpler to use than grub 2.x just note that alot of things are different and you should read tutorials for the correct version of grub. Often grub 1.x will be in a grub-legacy or similar package depending on the distro.
Edit: If you are building your kernel for your hardware only... do not use an initramfs its overkill. There are places you would want to do this is if your system is incapable of loading a kernel large enough for essential drivers (sparc for instance is very limited in kernel image size). another being booting over network possibly but by and large it isn't needed. If you must use an initramfs get your kernel build working without it first.
Also personally I build my kernel with essential drivers included (disk and filesystem basically) and build it with.
make mrproper (save/backup your .config first) ;
make menuconfig ;
make -j8 ;
make modules_install ;
cp arch/x86_64/boot/bzImage /boot/linux-3.7.1 ;
(modify grub to boot the new kernel) and im done and ready to reboot.
Any chance you could attach a screenshot of the failure?
I am not getting your question 100% clearly. Anyway, you downloaded some kernel tree from kernel.org and successfully booted with new Image.
Then you are trying to load a LKM i.e kernel module using insmod or modprobe.
so you are getting "Invalid magic number".
Solution
Need to re-compile the kernel module in new kernel, then try to insert.
I wanted to build my own custom kernel with a different syscall table. (same syscalls but in different position/numbers)
I was working on kernel 3.2.29.
Changing the kernel was quite easy:
1) changing the syscall position in arch/x86/kernel/syscall_table_32.S
2) changing the syscall macro number in arch/x86/include/asm/unistd_32.h
3) compiling and installing the new kernel
I switched the syscalls around: sys_open took the place and number of sys_read, and vice versa.
I figured that if I compile glibc with the modified kernel headers, I could have a running system, but unfortunately, it wasn't enough and my system won't boot.
Am I missing something? What else do I need to do in order to have a running system?
The steps I have taken are:
1) building and installing the kernel as described in my question
2) extracting the new kernel headers using make headers_install INSTALL_HDR_PATH=[path]
3) building glibc with the parameter --with-headers=[path/include]
4) I used a live cd to access the file system externally in order to install the new glibc, using the make install install_root=[the original file system] (so the system won't break during the install)
I hope that the new glibc was built properly, but I am not sure.
After that, when booting the system, the boot stops in the (initrafms) shell screen:
I guess I need to rebuild the initrd, but how do I compile it according to the new syscall table?
You will have to rebuild everything. Even if all your binaries are dynamically linked, it is possible that the old syscalls were inlined into the binary because many of the C functions are just return syscall(__NR_somecall,...).
You could do this manually, but it could be difficult to keep the toolchains straight unless you use a cross compilable toolchain like buildroot, aboriginal or similar. Pick whichever best suits you (I prefer Rob Landley's aboriginal - http://landley.net/aboriginal/ )
Then to make your initrd just expand the old one using {z,bz,xz}cat oldinit.rd |cpio -id; rm oldinit.rd. Replace the old kernel modules, libs and binaries with the new and cpio and compress it back (cpio needs the -H newc option) ... or now you can rebuild your kernel and point the initramfs to that directory, but wouldn't recommend that if your initrd may need changed frequently such as if for instance you were testing out a whole new syscall structure and having to debug a lot.
Scrambling the system call numbers is really going to hurt. You'll at least need to rebuild all of the statically linked binaries on your system and your initrd (if you use one).
You haven't said at what point the boot fails, but even if the kernel comes up it is likely that the critical programs contained in the initrd compressed ramdisk would fail because they have the original syscall numbers hard-coded. You will need to rebuild and repackage those as well.
You might consider first replacing init with a static hello-world type of program to verify that your kernel can support a userspace at all; then look into the details of making all the complexity of a modern linux userspace match.
you had to learn to reading the messsage of pansic dump and show us what kenrel panic. Without this information, people can hardly help you or provide you useful suggestion.
I am using gdb attached to a serial port of a virtual machine to debug linux kernel.
I am wondering, if there is any patches/plugins which can make the gdb understand some of linux kernel's data structure and make it "thread aware"?
By that I mean under gdb I can see how many kernel threads are there, their status, and for each thread, their stack information.
libvmi
https://github.com/libvmi/libvmi
This project does "LibVMI: Simplified Virtual Machine Introspection" which sounds really close.
This project in particular https://github.com/Wenzel/pyvmidbg uses libvmi and features a demo video of debugging a Windows userland application form inside it, without memory conflicts.
As of May 2019, there are two limitations however as of May 2019, both of which could be overcome with some work: https://github.com/Wenzel/pyvmidbg/issues/24
Linux memory parsing is not yet complete
requires Xen
The developer of that project also answered further at: https://stackoverflow.com/a/56369454/895245
Implementing it with those libraries would be in my opinion the best way to achieve this goal today.
Linaro lkd-python
First, this Linaro page claims to have a working setup: https://wiki.linaro.org/LandingTeams/ST/GDB that allows you to do usual thread operations such as thread, bt, etc., but it relies on a GDB fork. I will test it out later. In 2016, https://youtu.be/pqn5hIrz3A8 says that the implementation was in C, not as Python scripts unfortunately, which would be better and avoid forking. The sketch for lkd-python can be found at: https://git.linaro.org/people/lee.jones/kieran.bingham/binutils-gdb.git/log/?h=lkd-python
Linux kernel in-tree GDB scripts + my brain
I then tried to see what I could do with the kernel in-tree Python scripts at v4.17 + some manual intervention as a prototype, but didn't quite get there yet.
I have tested using this highly automated QEMU + Buildroot setup.
First follow the procedure I described at: How to debug the Linux kernel with GDB and QEMU? to get GDB working.
Then, as described at: How to debug Linux kernel modules with QEMU? run GDB with:
gdb -ex add-auto-load-safe-path /full/path/to/linux/kernel
This loads the in-tree GDB Python scripts from scripts/gdb.
One of those scripts provides:
lx-ps
which lists all threads with format:
0xffff88000ed08000 1 init
0xffff88000ed08ac0 2 kthreadd
The first field is the address of the task_struct struct, so we can see the entire struct with:
p (struct task_struct)*0xffff88000ed08000
which should in theory allow us to get any information we want about the process.
Now I wanted to find the PC. For ARM, I've seen: Find program counter of process in kernel and I tried:
task_pt_regs((struct thread_info *)((struct task_struct)*0xffffffc00e8f8000))->uregs[ARM_pc]
but task_pt_regs is a #define and GDB cannot see defines without -ggdb3: How do I print a #defined constant in GDB? which are apparently not set?
I don't think GDB understands kernel data structures, that would make them version dependent. GDB uses ptrace for gathering information on any running process.
That's all I know :(
pyvmidbg developer here.
I will add some clarifications:
yes the goal of the project is indeed to have a cross-platform, guest-aware GDB stub.
Most of the implementation is already done for Windows, where we are aware of processes and their threads context.
It's possible to intercept a specific process (cmd.exe in the demo) and singlestep its execution (this is limited to 1 process with 1 thread for now), as well as attaching to a new process's entrypoint.
Regarding Linux, I looked at the internals and the resources that I could find, but I'm lacking the whole picture to figure out how I can:
- intercept a task when it's being scheduled (core/sched.c:switch_to() ?)
- read the task state (Windows's KTRAP_FRAME equivalent for Linux ?)
I asked a question on SO, but nobody answered :/
Linux context switch internals: how does a process goes back to userland after the switch?
If you can help with this, I can guide you through the implementation :)
Regarding the hypervisor support, only Xen is fully supported in the Libvmi interface at the moment.
I added a section in the README to describe where we are in terms of VMI APIs with other hypervisors.
Thanks !
Is there any way i can mark a page execute only with no read permissions ? (i.e able to execute instructions on that page without having read permissions of that page which is executable.)
My final goal is to make a page that i can execute but no other process should be able to make any data access to that page ..
This is one of the things that is kernel and hardware-dependent, as mentioned in the mprotect() manual page:
Whether PROT_EXEC has any effect different from PROT_READ is architecture and kernel version dependent.
On recent Linux/x86 kernels, those flags are definitely discrete if your CPU supports the NX-bit. On the other x86 CPUs, it depends on whether your kernel has support for Exec-Shield or another similar NX-bit emulation.