瀏覽代碼

Kernel+Userland: Remove loadable kernel moduless

These interfaces are broken for about 9 months, maybe longer than that.
At this point, this is just a dead code nobody tests or tries to use, so
let's remove it instead of keeping a stale code just for the sake of
keeping it and hoping someone will fix it.

To better justify this, I read that OpenBSD removed loadable kernel
modules in 5.7 release (2014), mainly for the same reason we do -
nobody used it so they had no good reason to maintain it.
Still, OpenBSD had LKMs being effectively working, which is not the
current state in our project for a long time.
An arguably better approach to minimize the Kernel image size is to
allow dropping drivers and features while compiling a new image.
Liav A 3 年之前
父節點
當前提交
04ba31b8c5

+ 0 - 35
Base/usr/share/man/man2/module_load.md

@@ -1,35 +0,0 @@
-## Name
-
-module\_load - load a kernel module
-
-## Synopsis
-
-```**c++
-#include <serenity.h>
-
-int module_load(const char* path, size_t path_length);
-```
-
-## Description
-
-`module_load()` will load a kernel module from an ELF object file given its
-path in the filesystem.
-
-## Return value
-
-If the module is successfully loaded, `module_load()` returns 0. Otherwise, it
-returns -1 and sets `errno` to describe the error.
-
-## Errors
-
-* `EPERM`: The calling process does not have superuser permissions.
-* `EFAULT`: `path` pointed to memory that was not accessible for the caller.
-* `ENOEXEC`: The specified file could not be parsed as an ELF object.
-* `EINVAL`: One or more symbols referred to by the module could not be resolved, or the module had no `.text` section, or didn't export a `module_init` function.
-* `EEXIST`: A module with the same name was already loaded.
-
-## See also
-
-* [`module_unload`(2)](module_unload.md)
-* [`modload`(8)](../man8/modload.md)
-* [`kernel_modules`(7)](../man7/kernel_modules.md)

+ 0 - 32
Base/usr/share/man/man2/module_unload.md

@@ -1,32 +0,0 @@
-## Name
-
-module\_unload - unload a kernel module
-
-## Synopsis
-
-```**c++
-#include <serenity.h>
-
-int module_unload(const char* name, size_t name_length);
-```
-
-## Description
-
-`module_unload()` will unload a kernel module by name.
-
-## Return value
-
-If the module is successfully unloaded, `module_unload()` returns 0.
-Otherwise, it returns -1 and sets `errno` to describe the error.
-
-## Errors
-
-* `EPERM`: The calling process does not have superuser permissions.
-* `EFAULT`: `path` pointed to memory that was not accessible for the caller.
-* `ENOENT`: There was no module loaded with the specified name.
-
-## See also
-
-* [`module_load`(2)](module_load.md)
-* [`modunload`(8)](../man8/modunload.md)
-* [`kernel_modules`(7)](../man7/kernel_modules.md)

+ 0 - 65
Base/usr/share/man/man7/kernel_modules.md

@@ -1,65 +0,0 @@
-## Name
-
-Kernel Modules - runtime code loading for the kernel
-
-## Description
-
-Serenity's kernel supports loading modules at runtime. This functionality can
-be used to implement optional features (e.g. drivers), and speed up your
-development cycle.
-
-## Module format
-
-A kernel module is a regular ELF object file which must export several
-symbols. Any symbols it refers to will be resolved when it is loaded.
-
-### `module_name`
-
-This should be a string like `const char module_name[]` containing the name of
-the module. This is used to give the module a name in any informational
-contexts, but also to ensure that the module is not loaded twice by accident,
-and also used as a reference to unload the module later.
-
-### `module_init`
-
-This should be a function with the following signature: `void module_init()`.
-It will be called when the module is loaded.
-
-### `module_fini`
-
-This is optional, but if defined it should be a function with the following
-signature: `void module_fini()`. It will be called when the module is
-unloaded.
-
-## Example:
-
-```c++
-#include <Kernel/kstdio.h>
-#include <Kernel/Process.h>
-
-extern "C" const char module_name[] = "ExampleModule";
-
-extern "C" void module_init()
-{
-    kprintf("ExampleModule has booted!\n");
-
-    for (int i = 0; i < 3; ++i) {
-        kprintf("i is now %d\n", i);
-    }
-
-    kprintf("current pid: %d\n", current->process().sys$getpid());
-    kprintf("current process name: %s\n", current->process().name().characters());
-}
-
-extern "C" void module_fini()
-{
-    kprintf("ExampleModule is being removed!\n");
-}
-```
-
-## See also
-
-* [`modload`(8)](../man8/modload.md)
-* [`modunload`(8)](../man8/modunload.md)
-* [`module_load`(2)](../man2/module_load.md)
-* [`module_unload`(2)](../man2/module_unload.md)

+ 0 - 25
Base/usr/share/man/man8/modload.md

@@ -1,25 +0,0 @@
-## Name
-
-modload - load a kernel module
-
-## Synopsis
-
-```**sh
-$ modload <path>
-```
-
-## Description
-
-Load a kernel module specified by *path*.
-
-## Examples
-
-```sh
-$ modload /mod/TestModule.o
-```
-
-## See also
-
-* [`modunload`(1)](modunload.md)
-* [`module_load`(2)](../man2/module_load.md)
-* [`kernel_modules`(7)](../man7/kernel_modules.md)

+ 0 - 25
Base/usr/share/man/man8/modunload.md

@@ -1,25 +0,0 @@
-## Name
-
-modunload - unload a kernel module
-
-## Synopsis
-
-```**sh
-$ modunload <name>
-```
-
-## Description
-
-Unload a kernel module specified by *name*.
-
-## Examples
-
-```sh
-$ modunload TestModule
-```
-
-## See also
-
-* [`modload`(8)](modload.md)
-* [`module_unload`(2)](../man2/module_unload.md)
-* [`kernel_modules`(7)](../man7/kernel_modules.md)

+ 0 - 2
Kernel/API/Syscall.h

@@ -121,8 +121,6 @@ enum class NeedsBigProcessLock {
     S(mkdir, NeedsBigProcessLock::Yes)                      \
     S(mknod, NeedsBigProcessLock::Yes)                      \
     S(mmap, NeedsBigProcessLock::Yes)                       \
-    S(module_load, NeedsBigProcessLock::Yes)                \
-    S(module_unload, NeedsBigProcessLock::Yes)              \
     S(mount, NeedsBigProcessLock::Yes)                      \
     S(mprotect, NeedsBigProcessLock::Yes)                   \
     S(mremap, NeedsBigProcessLock::Yes)                     \

+ 0 - 2
Kernel/CMakeLists.txt

@@ -219,7 +219,6 @@ set(KERNEL_SOURCES
     Syscalls/mkdir.cpp
     Syscalls/mknod.cpp
     Syscalls/mmap.cpp
-    Syscalls/module.cpp
     Syscalls/mount.cpp
     Syscalls/open.cpp
     Syscalls/perf_event.cpp
@@ -528,4 +527,3 @@ serenity_install_headers(Kernel)
 serenity_install_sources(Kernel)
 
 add_subdirectory(Prekernel)
-add_subdirectory(Modules)

+ 0 - 36
Kernel/GlobalProcessExposed.cpp

@@ -20,7 +20,6 @@
 #include <Kernel/Interrupts/GenericInterruptHandler.h>
 #include <Kernel/Interrupts/InterruptManagement.h>
 #include <Kernel/KBufferBuilder.h>
-#include <Kernel/Module.h>
 #include <Kernel/Net/LocalSocket.h>
 #include <Kernel/Net/NetworkAdapter.h>
 #include <Kernel/Net/NetworkingManagement.h>
@@ -682,33 +681,7 @@ private:
         return KSuccess;
     }
 };
-class ProcFSModules final : public ProcFSGlobalInformation {
-public:
-    static NonnullRefPtr<ProcFSModules> must_create();
-
-    virtual mode_t required_mode() const override { return 0400; }
 
-private:
-    ProcFSModules();
-    virtual KResult try_generate(KBufferBuilder& builder) override
-    {
-        extern HashMap<String, OwnPtr<Module>>* g_modules;
-        JsonArraySerializer array { builder };
-        for (auto& it : *g_modules) {
-            auto obj = array.add_object();
-            obj.add("name", it.value->name);
-            obj.add("module_init", it.value->module_init);
-            obj.add("module_fini", it.value->module_fini);
-            u32 size = 0;
-            for (auto& section : it.value->sections) {
-                size += section.capacity();
-            }
-            obj.add("size", size);
-        }
-        array.finish();
-        return KSuccess;
-    }
-};
 class ProcFSProfile final : public ProcFSGlobalInformation {
 public:
     static NonnullRefPtr<ProcFSProfile> must_create();
@@ -791,10 +764,6 @@ UNMAP_AFTER_INIT NonnullRefPtr<ProcFSCommandLine> ProcFSCommandLine::must_create
 {
     return adopt_ref_if_nonnull(new (nothrow) ProcFSCommandLine).release_nonnull();
 }
-UNMAP_AFTER_INIT NonnullRefPtr<ProcFSModules> ProcFSModules::must_create()
-{
-    return adopt_ref_if_nonnull(new (nothrow) ProcFSModules).release_nonnull();
-}
 UNMAP_AFTER_INIT NonnullRefPtr<ProcFSProfile> ProcFSProfile::must_create()
 {
     return adopt_ref_if_nonnull(new (nothrow) ProcFSProfile).release_nonnull();
@@ -853,10 +822,6 @@ UNMAP_AFTER_INIT ProcFSCommandLine::ProcFSCommandLine()
     : ProcFSGlobalInformation("cmdline"sv)
 {
 }
-UNMAP_AFTER_INIT ProcFSModules::ProcFSModules()
-    : ProcFSGlobalInformation("modules"sv)
-{
-}
 UNMAP_AFTER_INIT ProcFSProfile::ProcFSProfile()
     : ProcFSGlobalInformation("profile"sv)
 {
@@ -896,7 +861,6 @@ UNMAP_AFTER_INIT NonnullRefPtr<ProcFSRootDirectory> ProcFSRootDirectory::must_cr
     directory->m_components.append(ProcFSDevices::must_create());
     directory->m_components.append(ProcFSUptime::must_create());
     directory->m_components.append(ProcFSCommandLine::must_create());
-    directory->m_components.append(ProcFSModules::must_create());
     directory->m_components.append(ProcFSProfile::must_create());
     directory->m_components.append(ProcFSKernelBase::must_create());
 

+ 0 - 26
Kernel/Module.h

@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-#include <AK/String.h>
-#include <AK/Vector.h>
-#include <Kernel/KBuffer.h>
-
-namespace Kernel {
-
-typedef void* (*ModuleInitPtr)();
-typedef void* (*ModuleFiniPtr)();
-
-struct Module {
-    String name;
-    NonnullOwnPtrVector<KBuffer> sections;
-
-    ModuleInitPtr module_init { nullptr };
-    ModuleFiniPtr module_fini { nullptr };
-};
-
-}

+ 0 - 8
Kernel/Modules/CMakeLists.txt

@@ -1,8 +0,0 @@
-set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
-
-function(serenity_kernel_module name sources)
-    add_library(${name} STATIC ${sources})
-    install(FILES $<TARGET_OBJECTS:${name}> DESTINATION mod)
-endfunction()
-
-serenity_kernel_module(TestModule TestModule.cpp)

+ 0 - 24
Kernel/Modules/TestModule.cpp

@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <AK/Format.h>
-#include <Kernel/Modules/module_syms.h>
-
-extern "C" const char module_name[] = "TestModule";
-
-extern "C" void module_init()
-{
-    dmesgln("TestModule has booted!");
-
-    for (int i = 0; i < 3; ++i) {
-        dmesgln("i is now {}", i);
-    }
-}
-
-extern "C" void module_fini()
-{
-    dmesgln("TestModule is being removed!");
-}

+ 0 - 11
Kernel/Modules/module_syms.h

@@ -1,11 +0,0 @@
-/*
- * Copyright (c) 2020, the SerenityOS developers.
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-extern "C" const char module_name[];
-extern "C" void module_init();
-extern "C" void module_fini();

+ 0 - 4
Kernel/Process.cpp

@@ -25,7 +25,6 @@
 #include <Kernel/Memory/AnonymousVMObject.h>
 #include <Kernel/Memory/PageDirectory.h>
 #include <Kernel/Memory/SharedInodeVMObject.h>
-#include <Kernel/Module.h>
 #include <Kernel/PerformanceEventBuffer.h>
 #include <Kernel/PerformanceManager.h>
 #include <Kernel/Process.h>
@@ -45,7 +44,6 @@ static void create_signal_trampoline();
 RecursiveSpinlock g_profiling_lock;
 static Atomic<pid_t> next_pid;
 static Singleton<SpinlockProtected<Process::List>> s_processes;
-READONLY_AFTER_INIT HashMap<String, OwnPtr<Module>>* g_modules;
 READONLY_AFTER_INIT Memory::Region* g_signal_trampoline_region;
 
 static Singleton<MutexProtected<String>> s_hostname;
@@ -72,8 +70,6 @@ ProcessID Process::allocate_pid()
 
 UNMAP_AFTER_INIT void Process::initialize()
 {
-    g_modules = new HashMap<String, OwnPtr<Module>>;
-
     next_pid.store(0, AK::MemoryOrder::memory_order_release);
 
     // Note: This is called before scheduling is initialized, and before APs are booted.

+ 0 - 2
Kernel/Process.h

@@ -393,8 +393,6 @@ public:
     KResultOr<FlatPtr> sys$getrandom(Userspace<void*>, size_t, unsigned int);
     KResultOr<FlatPtr> sys$getkeymap(Userspace<const Syscall::SC_getkeymap_params*>);
     KResultOr<FlatPtr> sys$setkeymap(Userspace<const Syscall::SC_setkeymap_params*>);
-    KResultOr<FlatPtr> sys$module_load(Userspace<const char*> path, size_t path_length);
-    KResultOr<FlatPtr> sys$module_unload(Userspace<const char*> name, size_t name_length);
     KResultOr<FlatPtr> sys$profiling_enable(pid_t, u64);
     KResultOr<FlatPtr> sys$profiling_disable(pid_t);
     KResultOr<FlatPtr> sys$profiling_free_buffer(pid_t);

+ 0 - 168
Kernel/Syscalls/module.cpp

@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <Kernel/FileSystem/OpenFileDescription.h>
-#include <Kernel/FileSystem/VirtualFileSystem.h>
-#include <Kernel/KSyms.h>
-#include <Kernel/Module.h>
-#include <Kernel/Process.h>
-#include <LibELF/Image.h>
-
-namespace Kernel {
-
-extern HashMap<String, OwnPtr<Module>>* g_modules;
-
-KResultOr<FlatPtr> Process::sys$module_load(Userspace<const char*> user_path, size_t path_length)
-{
-    VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
-    if (!is_superuser())
-        return EPERM;
-
-    REQUIRE_NO_PROMISES;
-
-    auto path = TRY(get_syscall_path_argument(user_path, path_length));
-    auto description = TRY(VirtualFileSystem::the().open(path->view(), O_RDONLY, 0, current_directory()));
-    auto payload = TRY(description->read_entire_file());
-
-    auto storage = TRY(KBuffer::try_create_with_bytes(payload->bytes()));
-
-    auto elf_image = try_make<ELF::Image>(storage->data(), storage->size());
-    if (!elf_image)
-        return ENOMEM;
-    if (!elf_image->parse())
-        return ENOEXEC;
-
-    HashMap<String, u8*> section_storage_by_name;
-
-    auto module = try_make<Module>();
-    if (!module)
-        return ENOMEM;
-
-    KResult section_loading_result = KSuccess;
-    elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
-        if (!section.size() || !section_loading_result.is_error())
-            return;
-        auto section_storage_or_error = KBuffer::try_create_with_bytes(ReadonlyBytes { section.raw_data(), section.size() }, Memory::Region::Access::ReadWriteExecute);
-        if (section_storage_or_error.is_error()) {
-            section_loading_result = section_storage_or_error.error();
-            return;
-        }
-        auto section_storage = section_storage_or_error.release_value();
-        section_storage_by_name.set(section.name(), section_storage->data());
-        module->sections.append(move(section_storage));
-    });
-    if (section_loading_result.is_error())
-        return section_loading_result;
-
-    bool missing_symbols = false;
-
-    elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
-        if (!section.size())
-            return;
-
-        auto* section_storage = section_storage_by_name.get(section.name()).value_or(nullptr);
-        VERIFY(section_storage);
-        auto relocations = section.relocations();
-        VERIFY(relocations.has_value());
-        relocations->for_each_relocation([&](const ELF::Image::Relocation& relocation) {
-            auto& patch_ptr = *reinterpret_cast<ptrdiff_t*>(section_storage + relocation.offset());
-            switch (relocation.type()) {
-            case R_386_PC32: {
-                // PC-relative relocation
-                dbgln("PC-relative relocation: {}", relocation.symbol().name());
-                auto symbol_address = address_for_kernel_symbol(relocation.symbol().name());
-                if (symbol_address == 0)
-                    missing_symbols = true;
-                dbgln("   Symbol address: {:p}", symbol_address);
-                ptrdiff_t relative_offset = (FlatPtr)symbol_address - ((FlatPtr)&patch_ptr + 4);
-                patch_ptr = relative_offset;
-                break;
-            }
-            case R_386_32: // Absolute relocation
-                dbgln("Absolute relocation: '{}' value={}, index={}", relocation.symbol().name(), relocation.symbol().value(), relocation.symbol_index());
-
-                if (relocation.symbol().bind() == STB_LOCAL) {
-                    auto* section_storage_containing_symbol = section_storage_by_name.get(relocation.symbol().section().name()).value_or(nullptr);
-                    VERIFY(section_storage_containing_symbol);
-                    u32 symbol_address = (ptrdiff_t)(section_storage_containing_symbol + relocation.symbol().value());
-                    if (symbol_address == 0)
-                        missing_symbols = true;
-                    dbgln("   Symbol address: {:p}", symbol_address);
-                    patch_ptr += symbol_address;
-                } else if (relocation.symbol().bind() == STB_GLOBAL) {
-                    u32 symbol_address = address_for_kernel_symbol(relocation.symbol().name());
-                    if (symbol_address == 0)
-                        missing_symbols = true;
-                    dbgln("   Symbol address: {:p}", symbol_address);
-                    patch_ptr += symbol_address;
-                } else {
-                    VERIFY_NOT_REACHED();
-                }
-                break;
-            }
-        });
-    });
-
-    if (missing_symbols)
-        return EINVAL;
-
-    auto* text_base = section_storage_by_name.get(".text").value_or(nullptr);
-    if (!text_base) {
-        dbgln("No .text section found in module!");
-        return EINVAL;
-    }
-
-    elf_image->for_each_symbol([&](const ELF::Image::Symbol& symbol) {
-        dbgln(" - {} '{}' @ {:p}, size={}", symbol.type(), symbol.name(), symbol.value(), symbol.size());
-        if (symbol.name() == "module_init") {
-            module->module_init = (ModuleInitPtr)(text_base + symbol.value());
-        } else if (symbol.name() == "module_fini") {
-            module->module_fini = (ModuleFiniPtr)(text_base + symbol.value());
-        } else if (symbol.name() == "module_name") {
-            const u8* storage = section_storage_by_name.get(symbol.section().name()).value_or(nullptr);
-            if (storage)
-                module->name = String((const char*)(storage + symbol.value()));
-        }
-    });
-
-    if (!module->module_init)
-        return EINVAL;
-
-    if (g_modules->contains(module->name)) {
-        dbgln("a module with the name {} is already loaded; please unload it first", module->name);
-        return EEXIST;
-    }
-
-    module->module_init();
-
-    auto name = module->name;
-    g_modules->set(name, move(module));
-
-    return 0;
-}
-
-KResultOr<FlatPtr> Process::sys$module_unload(Userspace<const char*> user_name, size_t name_length)
-{
-    VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
-    if (!is_superuser())
-        return EPERM;
-
-    REQUIRE_NO_PROMISES;
-
-    auto module_name = TRY(try_copy_kstring_from_user(user_name, name_length));
-
-    auto it = g_modules->find(module_name->view());
-    if (it == g_modules->end())
-        return ENOENT;
-
-    if (it->value->module_fini)
-        it->value->module_fini();
-
-    g_modules->remove(it);
-    return 0;
-}
-
-}

+ 0 - 12
Userland/Libraries/LibC/serenity.cpp

@@ -18,18 +18,6 @@ int disown(pid_t pid)
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
 
-int module_load(const char* path, size_t path_length)
-{
-    int rc = syscall(SC_module_load, path, path_length);
-    __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
-int module_unload(const char* name, size_t name_length)
-{
-    int rc = syscall(SC_module_unload, name, name_length);
-    __RETURN_WITH_ERRNO(rc, rc, -1);
-}
-
 int profiling_enable(pid_t pid, uint64_t event_mask)
 {
     int rc = syscall(SC_profiling_enable, pid, event_mask);

+ 0 - 3
Userland/Libraries/LibC/serenity.h

@@ -16,9 +16,6 @@ __BEGIN_DECLS
 
 int disown(pid_t);
 
-int module_load(const char* path, size_t path_length);
-int module_unload(const char* name, size_t name_length);
-
 int profiling_enable(pid_t, uint64_t);
 int profiling_disable(pid_t);
 int profiling_free_buffer(pid_t);

+ 0 - 25
Userland/Utilities/modload.cpp

@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <LibCore/ArgsParser.h>
-#include <serenity.h>
-#include <string.h>
-
-int main(int argc, char** argv)
-{
-    const char* path = nullptr;
-
-    Core::ArgsParser args_parser;
-    args_parser.add_positional_argument(path, "Path to the module to load", "path");
-    args_parser.parse(argc, argv);
-
-    int rc = module_load(path, strlen(path));
-    if (rc < 0) {
-        perror("module_load");
-        return 1;
-    }
-    return 0;
-}

+ 0 - 25
Userland/Utilities/modunload.cpp

@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <LibCore/ArgsParser.h>
-#include <serenity.h>
-#include <string.h>
-
-int main(int argc, char** argv)
-{
-    const char* name = nullptr;
-
-    Core::ArgsParser args_parser;
-    args_parser.add_positional_argument(name, "Name of the module to unload", "name");
-    args_parser.parse(argc, argv);
-
-    int rc = module_unload(name, strlen(name));
-    if (rc < 0) {
-        perror("module_unload");
-        return 1;
-    }
-    return 0;
-}