apsun / lolios Goto Github PK
View Code? Open in Web Editor NEWLightweight & operational Linux-inspired OS.
Lightweight & operational Linux-inspired OS.
Until we find a way to properly implement tab alignment, we should probably just ignore it.
This would let us get rid of the statically allocated kernel stacks (and hence remove the hard capped process limit).
clang seems to insist on linking in the system libubsan even when we're compiling with -nostdlib.
Current workaround is to link the final executable with ld
instead of cc
when not using LTO, but that complicates our Makefile since the flags are different.
Haven't thought of a good way to do this while maintaining backwards compatibility with the original filesystem spec. Ideally we can reuse some bits like we did for the inode refcount, but if not... haven't thought that far yet.
Building with clang and optimizations disabled causes infinite recursion. Apparently clang synthesizes a call to memset... inside of memset. -fno-builtin does not help (IIRC all it does is disable the builtin aliases for e.g. memcpy -> __builtin_memcpy, not prevent the builtins from being used).
Potential solutions, off the top of my head:
Because I was lazy, pages obtained via sbrk are given out in increments of 4MB so that we didn't have to maintain page tables. However this is fairly inefficient (and I foresee issues with ELF r/w/x support since the linker script seems to assume a page size of 4KB) so we should do this properly.
Seems to only be exhibited when compiling with clang with optimizations enabled.
Terminal 1: nc -l 127.0.0.1 1111
Terminal 2: nc 127.0.0.1 1111 < random
Socket manages to send some data, then aborts the connection. Adding TCP_DEBUG_PRINT=1
interestingly makes it work fine, so this could be something related to TCP windows or ne2k capacity.
Arguments for doing this:
#define isizeof(x) ((int)sizeof(x))
macro instead?char
instead of int
and some non-standard function signatures already)memcpy
/memmove
/memset
take size_t
and synthesize calls accordingly, so on the off chance we ever want to support 64-bit, we'll get mismatched argument types (although I guess since x64 uses fastcall, it probably won't explode immediately?)malloc()
and friends are odd-ones-out (since myalloc was originally an external project)-Wconversion
would be pretty cool, and using int
makes it a lot harderI don't want to change the return type of syscalls (for uniformity/OCD reasons); this effectively means that all syscalls are still limited to reading 2GB at a time. Which is fine; we need to limit the range to half of size_t
anyways since the return value needs to encode an error bit.
Currently socketcalls always return -EAGAIN
even if the file descriptor is not set to nonblocking mode which is kinda out of place. Potential solution paths:
a) use BLOCKING_WAIT
at the socketcall level (socket.c). The socket struct can have a single sleep queue. Pros: less complexity at the protocol level, no need to propagate nonblocking flag to protocol layer. Cons: not as flexible.
b) use BLOCKING_WAIT
at the protocol level (tcp.c/udp.c). Pros: fully customizable by syscall/whatever. Cons: need to figure out how to propagate the nonblocking flag.
This is very dangerous. Since we don't restore ebx/esi/edi as the caller of process_run
expects, we could corrupt the registers in the kernel if the way GCC arranges our variables changes. We should explicitly surround the call to process_run
with clobbers.
A lot of code in the kernel uses the following pattern:
if (fn() < 0) {
return -1;
}
This discards the error code and replaces it with a generic -1
. If we ever want to start returning proper error codes like EINVAL
, ENOMEM
, etc, we need to replace this with:
if ((ret = fn()) < 0) {
return ret;
}
Both for the DNS resolver and the main loop.
When typing on the last line of the terminal or on the second/third terminal screens, the cursor disappears. It comes back if you type some characters and then delete them with backspace.
Currently we only detect deltas, not full states. This causes 2 annoying bugs:
ON
when the machine boots, the states will be flipped (i.e. ON
-> OFF
, OFF
-> ON
).We can probably fix this by polling the complete modifier state every time one of them changes.
https://github.com/qemu/qemu/blob/80f1709aa0eb4de09b4240563463f991a5b9d855/hw/rtc/mc146818rtc.c#L253 seems to no longer work as s->irq
is NULL
for some reason. I suspect one of the recent-ish changes in https://github.com/qemu/qemu/commits/master/hw/i386/pc.c which touch RTC initialization is to blame.
As a result of this, no interrupts are generated by the RTC device and all reads hang.
Repro: /build.sh -rOg run
, hit any key, instant BSOD in terminal_tty_read
. Backtrace:
Exception: Page-fault exception (14)
Registers:
eax: 0xfffffffd ebx: 0xfffffffd ecx: 0x00000001 edx: 0x00000466
esi: 0x0043e020 edi: 0x00000000 ebp: 0x0041bf54 esp: 0x00000004
cr0: 0x80000011 cr2: 0x0000000c cr3: 0x00415000 cr4: 0x00000010
eip: 0x0040df60 eflags: 0x00000046 error: 0x00000000
cs: 0x0010 ds: 0x0018 es: 0x0018 fs: 0x0018 gs: 0x0018 ss: 0x819c
Backtrace:
at 0x0040df60 (0x00800050, 0x08400008, 0x00000400, 0x00407b33, 0x00000008)
at 0x0040144f (0x00000000, 0x08400008, 0x00000400, 0x08049c0a, 0x0804e56c)
at 0x00402f5e (0x00000000, 0x00000000, 0x083ffeb8, 0x00400164, 0x0041bfc0)
at 0x00402fb9 (0x0041bfc0, 0x083ffeb8, 0x0804e56c, 0x08049c0a, 0x00000400)
at 0x00400164 (0x00000000, 0x00000000, 0x083ffef8, 0x0804ad97, 0x00000000)
at 0x0804a19d (0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000)
at 0x0804ad97 (0x083fff3f, 0x00000081, 0x0804e56c, 0x00000000, 0x00000000)
at 0x0804ae43 (0x083fff3f, 0x00000081, 0x00000000, 0x00000000, 0x00000000)
I suspect an optimization in a new version of GCC is breaking something in the scheduler code. Strangely this only happens in -Og; levels 0, 1, 2, 3 don't exhibit this behavior. clang doesn't do this either.
$ gcc --version
gcc (GCC) 12.2.1 20230201
The two are logically independent, IDT should be strictly for the interrupt handler ASM <-> C function linkage. This also causes bugs like passing INT_IRQ8
to the register_irq_handler
when we should have used IRQ_RTC
instead.
However, the IRQ code should probably not go into i8259.c
, since that would introduce a circular dependency between i8259.c
and idt.c
.
This may or may not be a problem, but what happens if we have 2 processes who call rtc_read at the same time (one process is pre-empted while waiting for the next tick, and the other also calls read)? If the flag is set to 0 between stopping process 1 and starting process 2, the first process will miss a tick.
This probably isn't a huge issue, but it would be nice to virtualize the RTC for multple processes which should fix this problem. Each process has its own interrupt_occurred flag, and on tick all of them will be reset to 0. Also each file descriptor should have its own virtual RTC frequency.
/usr/bin/ld: /tmp/ccjI03lp.ltrans1.ltrans.o: in function `terminal_mouse_read.lto_priv.0':
<artificial>:(.text+0x2a53): undefined reference to `scheduler_yield_impl'
I already marked scheduler_yield_impl
as __attribute__((used))
, not sure how to fix this one.
Our DNS response parser is trash. We should fix it to limit reads into the response body range only. Currently this is vulnerable to RCE (though I suppose since we only support QEMU, this probably isn't that big of an issue).
It would be great to get rid of the elfconvert black box binary, one way would be to load real x86 ELF binaries. The post-elfconvert binaries seem to be valid ELF, as they can be executed natively on Linux (cat
for instance), so we can transparently replace the old implementation.
elf.h: https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
Unfortunately the x86 ABI specifies that addresses 4MB~3GB are available for usage. There are two solutions:
a. move the kernel to virtual address 3GB
b. write a custom linker script to avoid the 4-8MB page
Currently there are no plans to support a dynamic linker. All binaries should be statically linked.
We should update the vidmap page to point to the "backing" page if the executing process is not currently displayed.
This depends on issue #9, so finish that first.
Currently, modifying a header in userspace/ doesn't rebuild programs that depend on it. In kernel/ we have Makefile.dep, but the mechanism used to generate it assumes a flat directory tree which is not the case in userspace/.
Some exceptions push an additional error code onto the stack, which must be popped by our interrupt handler before returning from interrupt, or else we corrupt the stack.
isa-vga looks for vgabios.bin
which doesn't come with the seabios
package on Arch (it's called vgabios-isavga.bin
instead). VGA (pci-vga) on the other hand looks for vgabios-stdvga.bin
which works.
Current workaround is:
sudo ln -sf /usr/share/qemu/vgabios-isavga.bin /usr/share/qemu/vgabios.bin
But obviously I'd prefer not to maintain that hack.
Switching to pci-vga is currently blocked on (obviously) PCI support, since using isa-vga is what makes hard-coding the framebuffer address work. The PCI variant requires reading the address from the BAR.
Security issue, though it probably doesn't matter. Just zero everything before jumping into userspace code.
Consider:
local -> remote "SEQ=0, LEN=1500" (received)
remote -> local "ACK=1500, WND=0" (received - inbox is now empty, new writes are rejected)
remote -> local "ACK=1500, WND=1500" (lost)
Since we don't attempt to send anything when the window is full, we will deadlock. According to the TCP RFC, we should try to send probing packets even when the window is full to periodically check if the window has reopened.
To prevent visible lag, we can take a "foreground terminal has higher priority" approach to scheduling. Basically, give the foreground process extra time when choosing which process to schedule.
Repro steps:
TCP_DEBUG_DROP
TCP_FIN_TIMEOUT_MS
to a smaller value (e.g. 6000) to make it go fastertestsocket
This seems to always corrupt 8 bytes within an object in a pattern similar to list_t
(self-referential pointer). I'm strongly suspecting a use-after-free, since the other fields within the object are not smashed. Timer seems like the prime culprit at the moment since it gets used during packet loss, and it touches list_t
.
If the length of the input buffer is too small, we should either return -1 or at least make sure the string is NUL-terminated, since the test programs assume that if the call succeeded, the buffer is valid.
If the cursor's logical x == 0, we decrement the input buffer count but don't delete the character on screen. This causes the characters on screen to become out of sync with what's actually in the buffer.
Instead of using array buffers, we should create new 4KB pages, one for each terminal.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.