bzt wrote:In theory you're right it's false, but in practice it is true. That's what I meant by "not without a manually compiled kernel and dozens of dirty hacks that is". One of those dozen hacks is not using the default ld-linux.so interpreter or linking init statically for example as you mentioned.
Static linking is not a dirty hack. You do not actually want a real init daemon in your initramfs (initrd is the older mechanism), you only want a program there that can find the root file system, mount it, and change to it. That is all. The initramfs is only for finding the root FS. And due to all the mechanisms built into the kernel right now, it is even sufficient to build an initramfs consisting only of the modules needed for that. The kernel will try to find the root from the root= command line option, and will mount it, usually read-only (there are the ro and rw command line options to make sure).
Of course, you can take this game arbitrarily far: What if no root is found? Do you drop into a shell? Then that means we need a shell and all the stuff it needs. Do you want to check the root FS before continuing? What if that check fails? Etc. pp. Of course, "root-fs unavailable" is a fatal error, so just stopping the boot process with an explanatory message might also just work better.
bzt wrote:You mean under Linux, right? Because in my OS I use dynamically linked ELFs without interpreter so it is doable; and it is also true that the Linux kernel does not have a run-time linker, instead it delegates that task to the ELF interpreter.
Yes, I mean under Linux, the OP is asking for an OS based on Linux. You are of course free to do as you like in your own OS, but I will note that I do know how much code goes into a dynamic interpreter, and just how data-dependent it is, and I do not want this stuff to run in ring 0. I mean, you have to interpret the PT_DYNAMIC section, which contains pointers, pointers everywhere. And you have to parse strings, and you have to go into recursion, and there are just so many ways bad or evil data can corrupt state that running that stuff in ring 0 is flat out irresponsible. With the dynamic interpreter, all of the dynamic linking stuff is controlled from user-space, and can only corrupt user space. And for setuid executables, it should only ever touch admin-controlled data, so there is no way, evil data can be implanted to subvert the control flow of anything with a higher privilege level. And anything at your own level, well, you are welcome to hack yourself.
As for you, mmdmine:
mmdmine wrote:in my archlinux setup I have configured kernel to boot without initramfs and it works perfect.
My point, exactly.
mmdmine wrote:still you dont know what I mean. I dont want to create "yet another linux distrobute", and even I dont want to use a Unix shell and a Unix-like enviroment. my design has 3 layers, first a library that calls kernel, second my OS API, third my shell that runs on top of my API. if I try to write these in C, I will need a C Library then I could use musl or glibc or write my own library.
I think I'm getting you. Something completely different on top of Linux. Something like Android, perhaps? Anyway, musl still does try to present a POSIX compatible interface, and requires your Linux to be configured in some ways, to be compatible with POSIX. For example, if you want pseudo-terminals, you really need a devpts file system, mounted on /dev/pts. And a surprising amount of interfaces requires proc to be mounted on /proc. But those are small things.
Bear in mind that musl sets up a POSIX compatible programming environment. What you do for user interface really is up to you. Also, musl and glibc contain not only the C library (stuff like strchr(), memcmp(), and stuff), but also wrappers for all the system calls, and therefore are needed pretty much by every language. There is this weird thing going on with Go at the moment, where they basically reinvent the wheel and do all the system calls from the Go runtime directly, but for threading they fall back onto libpthread. That doesn't work, and as a result, the Go runtime ends up stepping on musl's libpthread, and I have no idea if that conflict is resolved yet. Another example of needing to go whole hog or not at all: It is possible to have userspace in Linux without libc, but it is hard, and you end up doing a lot of what libc did again. If you want to do syscalls yourself, great, but then do it for everything, don't switch back to libc wrappers in the middle.