diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/API/Syscall.h | 3 | ||||
-rw-r--r-- | Kernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Kernel/CoreDump.cpp | 5 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 7 | ||||
-rw-r--r-- | Kernel/Process.h | 6 | ||||
-rw-r--r-- | Kernel/Ptrace.cpp | 3 | ||||
-rw-r--r-- | Kernel/Syscalls/execve.cpp | 10 | ||||
-rw-r--r-- | Kernel/Syscalls/prctl.cpp | 46 | ||||
-rw-r--r-- | Kernel/Syscalls/setuid.cpp | 17 |
9 files changed, 91 insertions, 7 deletions
diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 0555851d7e..bf7de7da2c 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -195,7 +195,8 @@ namespace Kernel { S(set_process_name) \ S(disown) \ S(adjtime) \ - S(allocate_tls) + S(allocate_tls) \ + S(prctl) namespace Syscall { diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 0767371ce9..6e52b21545 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -136,6 +136,7 @@ set(KERNEL_SOURCES Syscalls/perf_event.cpp Syscalls/pipe.cpp Syscalls/pledge.cpp + Syscalls/prctl.cpp Syscalls/process.cpp Syscalls/profiling.cpp Syscalls/ptrace.cpp diff --git a/Kernel/CoreDump.cpp b/Kernel/CoreDump.cpp index 7a1d8cbe94..e203523156 100644 --- a/Kernel/CoreDump.cpp +++ b/Kernel/CoreDump.cpp @@ -42,6 +42,11 @@ namespace Kernel { OwnPtr<CoreDump> CoreDump::create(Process& process, const String& output_path) { + if (!process.is_dumpable()) { + dbgln("Refusing to generate CoreDump for non-dumpable process {}", process.pid().value()); + return nullptr; + } + auto fd = create_target_file(process, output_path); if (!fd) return nullptr; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index a7cd9cd241..f85d544b10 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -879,6 +879,7 @@ static OwnPtr<KBuffer> procfs$all(InodeIdentifier) process_object.add("amount_purgeable_volatile", process.amount_purgeable_volatile()); process_object.add("amount_purgeable_nonvolatile", process.amount_purgeable_nonvolatile()); process_object.add("icon_id", process.icon_id()); + process_object.add("dumpable", process.is_dumpable()); auto thread_array = process_object.add_array("threads"); process.for_each_thread([&](const Thread& thread) { auto thread_object = thread_array.add_object(); @@ -1137,22 +1138,20 @@ InodeMetadata ProcFSInode::metadata() const if (is_process_related_file(identifier())) { ProcessID pid = to_pid(identifier()); auto process = Process::from_pid(pid); - if (process) { + if (process && process->is_dumpable()) { metadata.uid = process->euid(); metadata.gid = process->egid(); } else { - // TODO: How to handle this? metadata.uid = 0; metadata.gid = 0; } } else if (is_thread_related_file(identifier())) { ThreadID tid = to_tid(identifier()); auto thread = Thread::from_tid(tid); - if (thread) { + if (thread && thread->process().is_dumpable()) { metadata.uid = thread->process().euid(); metadata.gid = thread->process().egid(); } else { - // TODO: How to handle this? metadata.uid = 0; metadata.gid = 0; } diff --git a/Kernel/Process.h b/Kernel/Process.h index 8f0f6ecf74..7054cb1753 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -192,6 +192,9 @@ public: gid_t sgid() const { return m_sgid; } ProcessID ppid() const { return m_ppid; } + bool is_dumpable() const { return m_dumpable; } + void set_dumpable(bool dumpable) { m_dumpable = dumpable; } + ThreadID exec_tid() const { return m_exec_tid; } mode_t umask() const { return m_umask; } @@ -371,6 +374,7 @@ public: long sys$sysconf(int name); int sys$disown(ProcessID); void* sys$allocate_tls(size_t); + int sys$prctl(int option, FlatPtr arg1, FlatPtr arg2); template<bool sockname, typename Params> int get_sock_or_peer_name(const Params&); @@ -627,6 +631,8 @@ private: ProcessID m_ppid { 0 }; mode_t m_umask { 022 }; + bool m_dumpable { true }; + Vector<gid_t> m_extra_gids; WeakPtr<Region> m_master_tls_region; diff --git a/Kernel/Ptrace.cpp b/Kernel/Ptrace.cpp index 6688d4f5fe..552c9656dd 100644 --- a/Kernel/Ptrace.cpp +++ b/Kernel/Ptrace.cpp @@ -59,6 +59,9 @@ KResultOr<u32> handle_syscall(const Kernel::Syscall::SC_ptrace_params& params, P || (peer->process().uid() != peer->process().euid())) // Disallow tracing setuid processes return KResult(-EACCES); + if (!peer->process().is_dumpable()) + return KResult(-EACCES); + auto& peer_process = peer->process(); if (params.request == PT_ATTACH) { if (peer_process.tracer()) { diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index e900d8e319..1e00bbf937 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -363,19 +363,25 @@ int Process::do_exec(NonnullRefPtr<FileDescription> main_program_description, Ve auto old_suid = m_suid; auto old_egid = m_egid; auto old_sgid = m_sgid; + auto was_dumpable = is_dumpable(); ArmedScopeGuard cred_restore_guard = [&] { m_euid = old_euid; m_suid = old_suid; m_egid = old_egid; m_sgid = old_sgid; + set_dumpable(was_dumpable); }; if (!(main_program_description->custody()->mount_flags() & MS_NOSUID)) { - if (main_program_metadata.is_setuid()) + if (main_program_metadata.is_setuid()) { + set_dumpable(false); m_euid = m_suid = main_program_metadata.uid; - if (main_program_metadata.is_setgid()) + } + if (main_program_metadata.is_setgid()) { + set_dumpable(false); m_egid = m_sgid = main_program_metadata.gid; + } } auto load_result_or_error = load(main_program_description, interpreter_description); diff --git a/Kernel/Syscalls/prctl.cpp b/Kernel/Syscalls/prctl.cpp new file mode 100644 index 0000000000..f5d06ea135 --- /dev/null +++ b/Kernel/Syscalls/prctl.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <Kernel/Process.h> +#include <LibC/sys/prctl_numbers.h> + +namespace Kernel { + +int Process::sys$prctl(int option, FlatPtr arg1, [[maybe_unused]] FlatPtr arg2) +{ + switch (option) { + case PR_GET_DUMPABLE: + return is_dumpable(); + case PR_SET_DUMPABLE: + set_dumpable(arg1); + return 0; + default: + return -EINVAL; + } + return 0; +} + +} diff --git a/Kernel/Syscalls/setuid.cpp b/Kernel/Syscalls/setuid.cpp index 8ea014039d..ee01f4e325 100644 --- a/Kernel/Syscalls/setuid.cpp +++ b/Kernel/Syscalls/setuid.cpp @@ -35,6 +35,8 @@ int Process::sys$seteuid(uid_t euid) if (euid != m_uid && euid != m_suid && !is_superuser()) return -EPERM; + if (m_euid != euid) + set_dumpable(false); m_euid = euid; return 0; } @@ -46,6 +48,9 @@ int Process::sys$setegid(gid_t egid) if (egid != m_gid && egid != m_sgid && !is_superuser()) return -EPERM; + if (m_egid != egid) + set_dumpable(false); + m_egid = egid; return 0; } @@ -57,6 +62,9 @@ int Process::sys$setuid(uid_t uid) if (uid != m_uid && uid != m_euid && !is_superuser()) return -EPERM; + if (m_euid != uid) + set_dumpable(false); + m_uid = uid; m_euid = uid; m_suid = uid; @@ -70,6 +78,9 @@ int Process::sys$setgid(gid_t gid) if (gid != m_gid && gid != m_egid && !is_superuser()) return -EPERM; + if (m_egid != gid) + set_dumpable(false); + m_gid = gid; m_egid = gid; m_sgid = gid; @@ -91,6 +102,9 @@ int Process::sys$setresuid(uid_t ruid, uid_t euid, uid_t suid) if ((!ok(ruid) || !ok(euid) || !ok(suid)) && !is_superuser()) return -EPERM; + if (m_euid != euid) + set_dumpable(false); + m_uid = ruid; m_euid = euid; m_suid = suid; @@ -112,6 +126,9 @@ int Process::sys$setresgid(gid_t rgid, gid_t egid, gid_t sgid) if ((!ok(rgid) || !ok(egid) || !ok(sgid)) && !is_superuser()) return -EPERM; + if (m_egid != egid) + set_dumpable(false); + m_gid = rgid; m_egid = egid; m_sgid = sgid; |