Serenity Operating System
at master 85 lines 3.2 kB view raw
1/* 2 * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Userspace.h> 8#include <Kernel/API/Ioctl.h> 9#include <Kernel/Jail.h> 10#include <Kernel/Process.h> 11#include <Kernel/StdLib.h> 12 13namespace Kernel { 14 15constexpr size_t jail_name_max_size = 50; 16 17ErrorOr<FlatPtr> Process::sys$jail_create(Userspace<Syscall::SC_jail_create_params*> user_params) 18{ 19 VERIFY_NO_PROCESS_BIG_LOCK(this); 20 TRY(require_promise(Pledge::jail)); 21 22 auto params = TRY(copy_typed_from_user(user_params)); 23 auto jail_name = TRY(get_syscall_path_argument(params.name)); 24 if (jail_name->length() > jail_name_max_size) 25 return ENAMETOOLONG; 26 27 params.index = TRY(m_attached_jail.with([&](auto& my_jail) -> ErrorOr<u64> { 28 // Note: If we are already in a jail, don't let the process to be able to create other jails 29 // even if it will not be able to join them later on. The reason for this is to prevent as much as possible 30 // any info leak about the "outside world" jail metadata. 31 if (my_jail) 32 return Error::from_errno(EPERM); 33 auto jail = TRY(Jail::create(move(jail_name))); 34 return jail->index().value(); 35 })); 36 // Note: We do the copy_to_user outside of the m_attached_jail Spinlock locked scope because 37 // we rely on page faults to work properly. 38 TRY(copy_to_user(user_params, &params)); 39 return 0; 40} 41 42ErrorOr<FlatPtr> Process::sys$jail_attach(Userspace<Syscall::SC_jail_attach_params const*> user_params) 43{ 44 VERIFY_NO_PROCESS_BIG_LOCK(this); 45 TRY(require_promise(Pledge::jail)); 46 47 // NOTE: Because the user might run a binary that is using this syscall and 48 // that binary was marked as SUID, then the user might be unaware of the 49 // fact that while no new setuid binaries might be executed, he is already 50 // running within such binary so for the sake of completeness and preventing 51 // naive sense of being secure, we should block that. 52 TRY(with_protected_data([&](auto& protected_data) -> ErrorOr<void> { 53 if (protected_data.executable_is_setid) 54 return EPERM; 55 return {}; 56 })); 57 58 auto params = TRY(copy_typed_from_user(user_params)); 59 return m_attached_jail.with([&](auto& my_jail) -> ErrorOr<FlatPtr> { 60 // Note: If we are already in a jail, don't let the process escape it even if 61 // it knows there are other jails. 62 // Note: To ensure the process doesn't try to maliciously enumerate all jails 63 // in the system, just return EPERM before doing anything else. 64 if (my_jail) 65 return EPERM; 66 auto jail = Jail::find_by_index(static_cast<JailIndex>(params.index)); 67 if (!jail) 68 return EINVAL; 69 my_jail = *jail; 70 my_jail->attach_count().with([&](auto& attach_count) { 71 attach_count++; 72 }); 73 m_jail_process_list.with([&](auto& list_ptr) { 74 list_ptr = my_jail->process_list(); 75 if (list_ptr) { 76 list_ptr->attached_processes().with([&](auto& list) { 77 list.append(*this); 78 }); 79 } 80 }); 81 return 0; 82 }); 83} 84 85}