module.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/FileSystem/FileDescription.h>
  7. #include <Kernel/FileSystem/VirtualFileSystem.h>
  8. #include <Kernel/KSyms.h>
  9. #include <Kernel/Module.h>
  10. #include <Kernel/Process.h>
  11. #include <LibELF/Image.h>
  12. namespace Kernel {
  13. extern HashMap<String, OwnPtr<Module>>* g_modules;
  14. KResultOr<FlatPtr> Process::sys$module_load(Userspace<const char*> user_path, size_t path_length)
  15. {
  16. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  17. if (!is_superuser())
  18. return EPERM;
  19. REQUIRE_NO_PROMISES;
  20. auto path = get_syscall_path_argument(user_path, path_length);
  21. if (path.is_error())
  22. return path.error();
  23. auto description_or_error = VirtualFileSystem::the().open(path.value()->view(), O_RDONLY, 0, current_directory());
  24. if (description_or_error.is_error())
  25. return description_or_error.error();
  26. auto& description = description_or_error.value();
  27. auto payload_or_error = description->read_entire_file();
  28. if (payload_or_error.is_error())
  29. return payload_or_error.error();
  30. auto& payload = *payload_or_error.value();
  31. auto storage = KBuffer::try_create_with_size(payload.size());
  32. if (!storage)
  33. return ENOMEM;
  34. memcpy(storage->data(), payload.data(), payload.size());
  35. auto elf_image = try_make<ELF::Image>(storage->data(), storage->size());
  36. if (!elf_image)
  37. return ENOMEM;
  38. if (!elf_image->parse())
  39. return ENOEXEC;
  40. HashMap<String, u8*> section_storage_by_name;
  41. auto module = try_make<Module>();
  42. if (!module)
  43. return ENOMEM;
  44. elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
  45. if (!section.size())
  46. return;
  47. auto section_storage = KBuffer::copy(section.raw_data(), section.size(), Memory::Region::Access::ReadWriteExecute);
  48. section_storage_by_name.set(section.name(), section_storage.data());
  49. module->sections.append(move(section_storage));
  50. });
  51. bool missing_symbols = false;
  52. elf_image->for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
  53. if (!section.size())
  54. return;
  55. auto* section_storage = section_storage_by_name.get(section.name()).value_or(nullptr);
  56. VERIFY(section_storage);
  57. auto relocations = section.relocations();
  58. VERIFY(relocations.has_value());
  59. relocations->for_each_relocation([&](const ELF::Image::Relocation& relocation) {
  60. auto& patch_ptr = *reinterpret_cast<ptrdiff_t*>(section_storage + relocation.offset());
  61. switch (relocation.type()) {
  62. case R_386_PC32: {
  63. // PC-relative relocation
  64. dbgln("PC-relative relocation: {}", relocation.symbol().name());
  65. auto symbol_address = address_for_kernel_symbol(relocation.symbol().name());
  66. if (symbol_address == 0)
  67. missing_symbols = true;
  68. dbgln(" Symbol address: {:p}", symbol_address);
  69. ptrdiff_t relative_offset = (FlatPtr)symbol_address - ((FlatPtr)&patch_ptr + 4);
  70. patch_ptr = relative_offset;
  71. break;
  72. }
  73. case R_386_32: // Absolute relocation
  74. dbgln("Absolute relocation: '{}' value={}, index={}", relocation.symbol().name(), relocation.symbol().value(), relocation.symbol_index());
  75. if (relocation.symbol().bind() == STB_LOCAL) {
  76. auto* section_storage_containing_symbol = section_storage_by_name.get(relocation.symbol().section().name()).value_or(nullptr);
  77. VERIFY(section_storage_containing_symbol);
  78. u32 symbol_address = (ptrdiff_t)(section_storage_containing_symbol + relocation.symbol().value());
  79. if (symbol_address == 0)
  80. missing_symbols = true;
  81. dbgln(" Symbol address: {:p}", symbol_address);
  82. patch_ptr += symbol_address;
  83. } else if (relocation.symbol().bind() == STB_GLOBAL) {
  84. u32 symbol_address = address_for_kernel_symbol(relocation.symbol().name());
  85. if (symbol_address == 0)
  86. missing_symbols = true;
  87. dbgln(" Symbol address: {:p}", symbol_address);
  88. patch_ptr += symbol_address;
  89. } else {
  90. VERIFY_NOT_REACHED();
  91. }
  92. break;
  93. }
  94. });
  95. });
  96. if (missing_symbols)
  97. return EINVAL;
  98. auto* text_base = section_storage_by_name.get(".text").value_or(nullptr);
  99. if (!text_base) {
  100. dbgln("No .text section found in module!");
  101. return EINVAL;
  102. }
  103. elf_image->for_each_symbol([&](const ELF::Image::Symbol& symbol) {
  104. dbgln(" - {} '{}' @ {:p}, size={}", symbol.type(), symbol.name(), symbol.value(), symbol.size());
  105. if (symbol.name() == "module_init") {
  106. module->module_init = (ModuleInitPtr)(text_base + symbol.value());
  107. } else if (symbol.name() == "module_fini") {
  108. module->module_fini = (ModuleFiniPtr)(text_base + symbol.value());
  109. } else if (symbol.name() == "module_name") {
  110. const u8* storage = section_storage_by_name.get(symbol.section().name()).value_or(nullptr);
  111. if (storage)
  112. module->name = String((const char*)(storage + symbol.value()));
  113. }
  114. });
  115. if (!module->module_init)
  116. return EINVAL;
  117. if (g_modules->contains(module->name)) {
  118. dbgln("a module with the name {} is already loaded; please unload it first", module->name);
  119. return EEXIST;
  120. }
  121. module->module_init();
  122. auto name = module->name;
  123. g_modules->set(name, move(module));
  124. return 0;
  125. }
  126. KResultOr<FlatPtr> Process::sys$module_unload(Userspace<const char*> user_name, size_t name_length)
  127. {
  128. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  129. if (!is_superuser())
  130. return EPERM;
  131. REQUIRE_NO_PROMISES;
  132. auto module_name_or_error = try_copy_kstring_from_user(user_name, name_length);
  133. if (module_name_or_error.is_error())
  134. return module_name_or_error.error();
  135. auto it = g_modules->find(module_name_or_error.value()->view());
  136. if (it == g_modules->end())
  137. return ENOENT;
  138. if (it->value->module_fini)
  139. it->value->module_fini();
  140. g_modules->remove(it);
  141. return 0;
  142. }
  143. }