Commit graph

834 commits

Author SHA1 Message Date
Andreas Kling
c32d65ae9f Kernel: Put some more syscalls in the "stdio" bucket
yield() and get_kernel_info_page() seem like decent fits for "stdio".
2020-01-12 10:31:21 +01:00
Andreas Kling
ca609ce5a3 Kernel: Put fcntl() debug spam behind DEBUG_IO 2020-01-12 10:01:22 +01:00
Andreas Kling
017b34e1ad Kernel: Add "video" pledge for accessing framebuffer devices
WindowServer becomes the only user.
2020-01-12 02:18:30 +01:00
Andreas Kling
f187374c1b Kernel: fork()ed children should inherit pledge promises :^)
Update various places that now need wider promises as they are not
reset by fork() anymore.
2020-01-11 23:28:41 +01:00
Andreas Kling
409a4f7756 ping: Use pledge() 2020-01-11 20:48:43 +01:00
Sergey Bugaev
0cb0f54783 Kernel: Implement bind mounts
You can now bind-mount files and directories. This essentially exposes an
existing part of the file system in another place, and can be used as an
alternative to symlinks or hardlinks.

Here's an example of doing this:

    # mkdir /tmp/foo
    # mount /home/anon/myfile.txt /tmp/foo -o bind
    # cat /tmp/foo
    This is anon's file.
2020-01-11 18:57:53 +01:00
Sergey Bugaev
61c1106d9f Kernel+LibC: Implement a few mount flags
We now support these mount flags:
* MS_NODEV: disallow opening any devices from this file system
* MS_NOEXEC: disallow executing any executables from this file system
* MS_NOSUID: ignore set-user-id bits on executables from this file system

The fourth flag, MS_BIND, is defined, but currently ignored.
2020-01-11 18:57:53 +01:00
Sergey Bugaev
2fcbb846fb Kernel+LibC: Add O_EXEC, move exec permission checking to VFS::open()
O_EXEC is mentioned by POSIX, so let's have it. Currently, it is only used
inside the kernel to ensure the process has the right permissions when opening
an executable.
2020-01-11 18:57:53 +01:00
Sergey Bugaev
4566c2d811 Kernel+LibC: Add support for mount flags
At the moment, the actual flags are ignored, but we correctly propagate them all
the way from the original mount() syscall to each custody that resides on the
mounted FS.
2020-01-11 18:57:53 +01:00
Andreas Kling
83f59419cd Kernel: Oops, recvfrom() is not quite ready for SMAP protections yet 2020-01-11 13:03:44 +01:00
Andreas Kling
24c736b0e7 Kernel: Use the Syscall string and buffer types more
While I was updating syscalls to stop passing null-terminated strings,
I added some helpful struct types:

    - StringArgument { const char*; size_t; }
    - ImmutableBuffer<Data, Size> { const Data*; Size; }
    - MutableBuffer<Data, Size> { Data*; Size; }

The Process class has some convenience functions for validating and
optionally extracting the contents from these structs:

    - get_syscall_path_argument(StringArgument)
    - validate_and_copy_string_from_user(StringArgument)
    - validate(ImmutableBuffer)
    - validate(MutableBuffer)

There's still so much code around this and I'm wondering if we should
generate most of it instead. Possible nice little project.
2020-01-11 12:47:47 +01:00
Andreas Kling
1434f30f92 Kernel: Remove SmapDisabler in bind() 2020-01-11 12:07:45 +01:00
Andreas Kling
2d7ae42f75 Kernel: Remove SmapDisabler in clock_nanosleep() 2020-01-11 11:51:03 +01:00
Andreas Kling
0ca6d6c8d2 Kernel: Remove validate_read_str() as nothing uses it anymore :^) 2020-01-11 10:57:50 +01:00
Andreas Kling
f5092b1c7e Kernel: Pass a parameter struct to mount()
This was the last remaining syscall that took a null-terminated string
and figured out how long it was by walking it in kernelspace *shudder*.
2020-01-11 10:56:02 +01:00
Andreas Kling
e380142853 Kernel: Pass a parameter struct to rename() 2020-01-11 10:36:54 +01:00
Andreas Kling
46830a0c32 Kernel: Pass a parameter struct to symlink() 2020-01-11 10:31:33 +01:00
Andreas Kling
c97bfbd609 Kernel: Pass a parameter struct to mknod() 2020-01-11 10:27:37 +01:00
Andreas Kling
6536a80aa9 Kernel: Pass a parameter struct to chown() 2020-01-11 10:17:44 +01:00
Andreas Kling
29b3d95004 Kernel: Expose a process's filesystem root as a /proc/PID/root symlink
In order to preserve the absolute path of the process root, we save the
custody used by chroot() before stripping it to become the new "/".
There's probably a better way to do this.
2020-01-10 23:48:44 +01:00
Andreas Kling
ddd0b19281 Kernel: Add a basic chroot() syscall :^)
The chroot() syscall now allows the superuser to isolate a process into
a specific subtree of the filesystem. This is not strictly permanent,
as it is also possible for a superuser to break *out* of a chroot, but
it is a useful mechanism for isolating unprivileged processes.

The VFS now uses the current process's root_directory() as the root for
path resolution purposes. The root directory is stored as an uncached
Custody in the Process object.
2020-01-10 23:14:04 +01:00
Andreas Kling
485443bfca Kernel: Pass characters+length to link() 2020-01-10 21:26:47 +01:00
Andreas Kling
416c7ac2b5 Kernel: Rename Syscall::SyscallString => Syscall::StringArgument 2020-01-10 20:16:18 +01:00
Andreas Kling
0695ff8282 Kernel: Pass characters+length to readlink()
Note that I'm developing some helper types in the Syscall namespace as
I go here. Once I settle on some nice types, I will convert all the
other syscalls to use them as well.
2020-01-10 20:13:23 +01:00
Andreas Kling
8c5cd97b45 Kernel: Fix kernel null deref on process crash during join_thread()
The join_thread() syscall is not supposed to be interruptible by
signals, but it was. And since the process death mechanism piggybacked
on signal interrupts, it was possible to interrupt a pthread_join() by
killing the process that was doing it, leading to confusing due to some
assumptions being made by Thread::finalize() for threads that have a
pending joiner.

This patch fixes the issue by making "interrupted by death" a distinct
block result separate from "interrupted by signal". Then we handle that
state in join_thread() and tidy things up so that thread finalization
doesn't get confused by the pending joiner being gone.

Test: Tests/Kernel/null-deref-crash-during-pthread_join.cpp
2020-01-10 19:23:45 +01:00
Andreas Kling
de69f84868 Kernel: Remove SmapDisablers in fchmod() and fchown() 2020-01-10 14:20:14 +01:00
Andreas Kling
952bb95baa Kernel: Enable SMAP protection during the execve() syscall
The userspace execve() wrapper now measures all the strings and puts
them in a neat and tidy structure on the stack.

This way we know exactly how much to copy in the kernel, and we don't
have to use the SMAP-violating validate_read_str(). :^)
2020-01-10 12:20:36 +01:00
Andreas Kling
197e73ee31 Kernel+LibELF: Enable SMAP protection during non-syscall exec()
When loading a new executable, we now map the ELF image in kernel-only
memory and parse it there. Then we use copy_to_user() when initializing
writable regions with data from the executable.

Note that the exec() syscall still disables SMAP protection and will
require additional work. This patch only affects kernel-originated
process spawns.
2020-01-10 10:57:06 +01:00
Andreas Kling
ff16298b44 Kernel: Removed an unused global variable 2020-01-09 18:02:37 +01:00
Andreas Kling
17ef5bc0ac Kernel: Rename {ss,esp}_if_crossRing to userspace_{ss,esp}
These were always so awkwardly named.
2020-01-09 18:02:01 +01:00
Andreas Kling
4b4d369c5d Kernel: Take path+length in the unlink() and umount() syscalls 2020-01-09 16:23:41 +01:00
Andrew Kaster
e594724b01 Kernel: mmap(..., MAP_PRIVATE, fd, offset) is not supported
Make mmap return -ENOTSUP in this case to make sure users don't get
confused and think they're using a private mapping when it's actually
shared. It's currenlty not possible to open a file and mmap it
MAP_PRIVATE, and change the perms of the private mapping to ones that
don't match the permissions of the underlying file.
2020-01-09 09:29:36 +01:00
Andreas Kling
e1d4b19461 Kernel: open() and openat() should ignore non-permission bits in mode 2020-01-08 15:21:06 +01:00
Andreas Kling
532f240f24 Kernel: Remove unused syscall for setting the signal mask 2020-01-08 15:21:06 +01:00
Andreas Kling
200459d644 Kernel: Fix SMAP violation in join_thread() 2020-01-08 15:21:05 +01:00
Andreas Kling
50056d1d84 Kernel: mmap() should fail with ENODEV for directories 2020-01-08 12:47:37 +01:00
Andreas Kling
fe9680f0a4 Kernel: Validate PROT_READ and PROT_WRITE against underlying file
This patch fixes some issues with the mmap() and mprotect() syscalls,
neither of whom were checking the permission bits of the underlying
files when mapping an inode MAP_SHARED.

This made it possible to subvert execution of any running program
by simply memory-mapping its executable and replacing some of the code.

Test: Kernel/mmap-write-into-running-programs-executable-file.cpp
2020-01-07 19:32:32 +01:00
Andreas Kling
5387a19268 Kernel: Make Process::file_description() vend a RefPtr<FileDescription>
This encourages callers to strongly reference file descriptions while
working with them.

This fixes a use-after-free issue where one thread would close() an
open fd while another thread was blocked on it becoming readable.

Test: Kernel/uaf-close-while-blocked-in-read.cpp
2020-01-07 15:53:42 +01:00
Andreas Kling
6a4b376021 Kernel: Validate ftruncate(fd, length) syscall inputs
- EINVAL if 'length' is negative
- EBADF if 'fd' is not open for writing
2020-01-07 14:48:43 +01:00
Andreas Kling
78a63930cc Kernel+LibELF: Validate PT_LOAD and PT_TLS offsets before memcpy()'ing
Before this, you could make the kernel copy memory from anywhere by
setting up an ELF executable with a program header specifying file
offsets outside the file.

Since ELFImage didn't even know how large it was, we had no clue that
we were copying things from outside the ELF.

Fix this by adding a size field to ELFImage and validating program
header ranges before memcpy()'ing to them.

The ELF code is definitely going to need more validation and checking.
2020-01-06 21:04:57 +01:00
Andreas Kling
8088fa0556 Kernel: Process::send_signal() should prefer main thread
The main/first thread in a process always has the same TID as the PID.
2020-01-06 14:37:26 +01:00
Andreas Kling
a803312eb4 Kernel: Send SIGCHLD to the thread with same PID as my PPID
Instead of delivering SIGCHLD to "any thread" in the process with PPID,
send it to the thread with the same TID as my PPID.
2020-01-06 14:35:42 +01:00
Andreas Kling
cd42ccd686 Kernel: The waitpid() syscall was not storing to "wstatus" in all cases 2020-01-06 14:34:04 +01:00
Andreas Kling
47cc3e68c6 Kernel: Remove bogus kernel image access validation checks
This code had been misinterpreting the Multiboot ELF section headers
since the beginning. Furthermore QEMU wasn't even passing us any
headers at all, so this wasn't checking anything.
2020-01-06 13:27:14 +01:00
Andreas Kling
53bda09d15 Kernel: Make utime() take path+length, remove SmapDisabler 2020-01-06 12:23:30 +01:00
Andreas Kling
1226fec19e Kernel: Remove SmapDisablers in stat() and lstat() 2020-01-06 12:13:48 +01:00
Andreas Kling
a47f0c93de Kernel: Pass name+length to mmap() and remove SmapDisabler 2020-01-06 12:04:55 +01:00
Andreas Kling
33025a8049 Kernel: Pass name+length to set_mmap_name() and remove SmapDisabler 2020-01-06 11:56:59 +01:00
Andreas Kling
6af8392cf8 Kernel: Remove SmapDisabler in futex() 2020-01-06 11:44:15 +01:00
Andreas Kling
a30fb5c5c1 Kernel: SMAP fixes for module_load() and module_unload()
Remove SmapDisabler in module_load() + use get_syscall_path_argument().
Also fix a SMAP violation in module_unload().
2020-01-06 11:36:16 +01:00