summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-12-25 18:27:42 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-25 19:35:55 +0100
commit82f86e35d6e0aa521df632fdba43fe7a37a5db4c (patch)
tree7f96f91c8467598a8419498576a7da9c06baeaa4
parent3c9bd911b8b90e8034c9b61633a6985e752eb417 (diff)
downloadserenity-82f86e35d6e0aa521df632fdba43fe7a37a5db4c.zip
Kernel+LibC: Introduce a "dumpable" flag for processes
This new flag controls two things: - Whether the kernel will generate core dumps for the process - Whether the EUID:EGID should own the process's files in /proc Processes are automatically made non-dumpable when their EUID or EGID is changed, either via syscalls that specifically modify those ID's, or via sys$execve(), when a set-uid or set-gid program is executed. A process can change its own dumpable flag at any time by calling the new sys$prctl(PR_SET_DUMPABLE) syscall. Fixes #4504.
-rw-r--r--Kernel/API/Syscall.h3
-rw-r--r--Kernel/CMakeLists.txt1
-rw-r--r--Kernel/CoreDump.cpp5
-rw-r--r--Kernel/FileSystem/ProcFS.cpp7
-rw-r--r--Kernel/Process.h6
-rw-r--r--Kernel/Ptrace.cpp3
-rw-r--r--Kernel/Syscalls/execve.cpp10
-rw-r--r--Kernel/Syscalls/prctl.cpp46
-rw-r--r--Kernel/Syscalls/setuid.cpp17
-rw-r--r--Libraries/LibC/CMakeLists.txt1
-rw-r--r--Libraries/LibC/sys/prctl.cpp40
-rw-r--r--Libraries/LibC/sys/prctl.h37
-rw-r--r--Libraries/LibC/sys/prctl_numbers.h30
13 files changed, 199 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;
diff --git a/Libraries/LibC/CMakeLists.txt b/Libraries/LibC/CMakeLists.txt
index 0105d44ff5..3366957d5d 100644
--- a/Libraries/LibC/CMakeLists.txt
+++ b/Libraries/LibC/CMakeLists.txt
@@ -31,6 +31,7 @@ set(LIBC_SOURCES
string.cpp
strings.cpp
syslog.cpp
+ sys/prctl.cpp
sys/ptrace.cpp
sys/select.cpp
sys/socket.cpp
diff --git a/Libraries/LibC/sys/prctl.cpp b/Libraries/LibC/sys/prctl.cpp
new file mode 100644
index 0000000000..d7aa35486b
--- /dev/null
+++ b/Libraries/LibC/sys/prctl.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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/API/Syscall.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+
+extern "C" {
+
+int prctl(int option, uintptr_t arg1, uintptr_t arg2)
+{
+ int rc = syscall(SC_prctl, option, arg1, arg2);
+ __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+}
diff --git a/Libraries/LibC/sys/prctl.h b/Libraries/LibC/sys/prctl.h
new file mode 100644
index 0000000000..ea6b8ed47d
--- /dev/null
+++ b/Libraries/LibC/sys/prctl.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/prctl_numbers.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+int prctl(int option, uintptr_t arg1, uintptr_t arg2);
+
+__END_DECLS
diff --git a/Libraries/LibC/sys/prctl_numbers.h b/Libraries/LibC/sys/prctl_numbers.h
new file mode 100644
index 0000000000..36ecc75bb6
--- /dev/null
+++ b/Libraries/LibC/sys/prctl_numbers.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#define PR_SET_DUMPABLE 1
+#define PR_GET_DUMPABLE 2