1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 23:27:42 +00:00

Kernel+Userland: Remove chroot functionality

We are not using this for anything and it's just been sitting there
gathering dust for well over a year, so let's stop carrying all this
complexity around for no good reason.
This commit is contained in:
Andreas Kling 2021-08-15 01:29:44 +02:00
parent 96d5d017b7
commit 1b739a72c2
19 changed files with 3 additions and 289 deletions

View file

@ -1,33 +0,0 @@
## Name
chroot, chroot\_with\_mount\_flags - change filesystem root
## Synopsis
```**c++
#include <unistd.h>
int chroot(const char* path);
int chroot_with_mount_flags(const char* path, int mount_flags);
```
## Description
`chroot()` changes the filesystem root of the current process to a new directory specified by `path`.
`chroot_with_mount_flags()` additionally applies the given `mount_flags` to the new root directory
of the current process as if it was a separate mount. All the same flags as for [`mount`(2)](mount.md)
are accepted, except `MS_BIND` doesn't make sense for chroots. Additionally, the value -1 is accepted,
and makes `chroot_with_mount_flags()` behave like regular `chroot()`.
## Errors
* `EPERM`: The current process does not have superuser privileges.
* `EFAULT`: `path` is not in readable memory.
All of the usual path resolution errors may also occur.
## See also
* [`chroot`(8)](../man8/chroot.md)
* [`mount`(2)](mount.md)

View file

@ -1,36 +0,0 @@
## Name
chroot - run a shell with a different filesystem root
## Synopsis
```**sh
# chroot <path> [program] [-o options]
```
## Description
This program uses the [`chroot`(2)](../man2/chroot.md) syscall to switch into a
different filesystem root and spawn a shell inside it.
It runs the given *program* (by default, `/bin/Shell`) inside the new root.
Mount options can be given in the same format as for [`mount`(8)](mount.md).
## Examples
```sh
# chroot /var/chroot
# pwd
/
```
```sh
# chroot -u 200:200 /var/chroot
$ id
uid=200(nona) gid=200(n/a)
```
## See also
* [`chroot`(2)](../man2/chroot.md)
* [`mount`(8)](mount.md)

View file

@ -55,7 +55,6 @@ enum class NeedsBigProcessLock {
S(chdir, NeedsBigProcessLock::Yes) \
S(chmod, NeedsBigProcessLock::Yes) \
S(chown, NeedsBigProcessLock::Yes) \
S(chroot, NeedsBigProcessLock::Yes) \
S(clock_gettime, NeedsBigProcessLock::No) \
S(clock_nanosleep, NeedsBigProcessLock::No) \
S(clock_settime, NeedsBigProcessLock::Yes) \

View file

@ -195,7 +195,6 @@ set(KERNEL_SOURCES
Syscalls/chdir.cpp
Syscalls/chmod.cpp
Syscalls/chown.cpp
Syscalls/chroot.cpp
Syscalls/clock.cpp
Syscalls/debug.cpp
Syscalls/disown.cpp

View file

@ -360,12 +360,6 @@ KResultOr<NonnullRefPtr<Inode>> ProcFSProcessDirectoryInode::lookup(StringView n
return maybe_inode.error();
return maybe_inode.release_value();
}
if (name == "root") {
auto maybe_inode = ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::RootLink, associated_pid());
if (maybe_inode.is_error())
return maybe_inode.error();
return maybe_inode.release_value();
}
return ENOENT;
}
@ -515,8 +509,6 @@ static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessS
return S_IFLNK | 0777;
if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink)
return S_IFLNK | 0777;
if (main_property == SegmentedProcFSIndex::MainProcessProperty::RootLink)
return S_IFLNK | 0777;
return S_IFREG | 0400;
}
@ -625,8 +617,6 @@ KResult ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, KBuffe
return process.procfs_get_perf_events(builder);
case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats:
return process.procfs_get_virtual_memory_stats(builder);
case SegmentedProcFSIndex::MainProcessProperty::RootLink:
return process.procfs_get_root_link(builder);
default:
VERIFY_NOT_REACHED();
}

View file

@ -934,9 +934,8 @@ KResultOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(S
GenericLexer path_lexer(path);
auto current_process = Process::current();
auto& current_root = current_process->root_directory();
NonnullRefPtr<Custody> custody = path[0] == '/' ? current_root : base;
NonnullRefPtr<Custody> custody = path[0] == '/' ? root_custody() : base;
bool extra_iteration = path[path.length() - 1] == '/';
while (!path_lexer.is_eof() || extra_iteration) {

View file

@ -609,8 +609,6 @@ void Process::finalize()
m_tty = nullptr;
m_executable = nullptr;
m_cwd = nullptr;
m_root_directory = nullptr;
m_root_directory_relative_to_global_root = nullptr;
m_arguments.clear();
m_environment.clear();
@ -775,25 +773,6 @@ void Process::FileDescriptionAndFlags::set(NonnullRefPtr<FileDescription>&& desc
m_flags = flags;
}
Custody& Process::root_directory()
{
if (!m_root_directory)
m_root_directory = VirtualFileSystem::the().root_custody();
return *m_root_directory;
}
Custody& Process::root_directory_relative_to_global_root()
{
if (!m_root_directory_relative_to_global_root)
m_root_directory_relative_to_global_root = root_directory();
return *m_root_directory_relative_to_global_root;
}
void Process::set_root_directory(const Custody& root)
{
m_root_directory = root;
}
void Process::set_tty(TTY* tty)
{
m_tty = tty;

View file

@ -57,7 +57,6 @@ Time kgettimeofday();
__ENUMERATE_PLEDGE_PROMISE(fattr) \
__ENUMERATE_PLEDGE_PROMISE(tty) \
__ENUMERATE_PLEDGE_PROMISE(chown) \
__ENUMERATE_PLEDGE_PROMISE(chroot) \
__ENUMERATE_PLEDGE_PROMISE(thread) \
__ENUMERATE_PLEDGE_PROMISE(video) \
__ENUMERATE_PLEDGE_PROMISE(accept) \
@ -392,7 +391,6 @@ public:
KResultOr<FlatPtr> sys$profiling_disable(pid_t);
KResultOr<FlatPtr> sys$profiling_free_buffer(pid_t);
KResultOr<FlatPtr> sys$futex(Userspace<const Syscall::SC_futex_params*>);
KResultOr<FlatPtr> sys$chroot(Userspace<const char*> path, size_t path_length, int mount_flags);
KResultOr<FlatPtr> sys$pledge(Userspace<const Syscall::SC_pledge_params*>);
KResultOr<FlatPtr> sys$unveil(Userspace<const Syscall::SC_unveil_params*>);
KResultOr<FlatPtr> sys$perf_event(int type, FlatPtr arg1, FlatPtr arg2);
@ -454,10 +452,6 @@ public:
Mutex& big_lock() { return m_big_lock; }
Mutex& ptrace_lock() { return m_ptrace_lock; }
Custody& root_directory();
Custody& root_directory_relative_to_global_root();
void set_root_directory(const Custody&);
bool has_promises() const { return m_protected_values.has_promises; }
bool has_promised(Pledge pledge) const { return m_protected_values.promises & (1u << (u32)pledge); }
@ -559,7 +553,6 @@ public:
KResult procfs_get_pledge_stats(KBufferBuilder& builder) const;
KResult procfs_get_virtual_memory_stats(KBufferBuilder& builder) const;
KResult procfs_get_binary_link(KBufferBuilder& builder) const;
KResult procfs_get_root_link(KBufferBuilder& builder) const;
KResult procfs_get_current_work_directory_link(KBufferBuilder& builder) const;
mode_t binary_link_required_mode() const;
KResultOr<size_t> procfs_get_thread_stack(ThreadID thread_id, KBufferBuilder& builder) const;
@ -760,8 +753,6 @@ private:
RefPtr<Custody> m_executable;
RefPtr<Custody> m_cwd;
RefPtr<Custody> m_root_directory;
RefPtr<Custody> m_root_directory_relative_to_global_root;
Vector<String> m_arguments;
Vector<String> m_environment;

View file

@ -31,7 +31,6 @@ enum class MainProcessProperty {
CurrentWorkDirectoryLink = 5,
PerformanceEvents = 6,
VirtualMemoryStats = 7,
RootLink = 8,
};
enum class ProcessSubDirectory {

View file

@ -65,7 +65,6 @@ KResult Process::ProcessProcFSTraits::traverse_as_directory(unsigned fsid, Funct
callback({ "cwd", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink) }, 0 });
callback({ "perf_events", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents) }, 0 });
callback({ "vm", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats) }, 0 });
callback({ "root", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::RootLink) }, 0 });
return KSuccess;
}

View file

@ -218,12 +218,6 @@ KResult Process::procfs_get_fds_stats(KBufferBuilder& builder) const
return KSuccess;
}
KResult Process::procfs_get_root_link(KBufferBuilder& builder) const
{
builder.append_bytes(const_cast<Process&>(*this).root_directory_relative_to_global_root().absolute_path().to_byte_buffer());
return KSuccess;
}
KResult Process::procfs_get_virtual_memory_stats(KBufferBuilder& builder) const
{
JsonArraySerializer array { builder };

View file

@ -1,38 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/StringView.h>
#include <Kernel/FileSystem/Custody.h>
#include <Kernel/FileSystem/VirtualFileSystem.h>
#include <Kernel/Process.h>
namespace Kernel {
KResultOr<FlatPtr> Process::sys$chroot(Userspace<const char*> user_path, size_t path_length, int mount_flags)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
if (!is_superuser())
return EPERM;
REQUIRE_PROMISE(chroot);
auto path = get_syscall_path_argument(user_path, path_length);
if (path.is_error())
return path.error();
auto directory_or_error = VirtualFileSystem::the().open_directory(path.value()->view(), current_directory());
if (directory_or_error.is_error())
return directory_or_error.error();
auto directory = directory_or_error.value();
m_root_directory_relative_to_global_root = directory;
int chroot_mount_flags = mount_flags == -1 ? directory->mount_flags() : mount_flags;
auto custody_or_error = Custody::try_create(nullptr, "", directory->inode(), chroot_mount_flags);
if (custody_or_error.is_error())
return custody_or_error.error();
set_root_directory(custody_or_error.release_value());
return 0;
}
}

View file

@ -21,8 +21,6 @@ KResultOr<FlatPtr> Process::sys$fork(RegisterState& regs)
auto child = Process::create(child_first_thread, m_name, uid(), gid(), pid(), m_is_kernel_process, m_cwd, m_executable, m_tty, this);
if (!child || !child_first_thread)
return ENOMEM;
child->m_root_directory = m_root_directory;
child->m_root_directory_relative_to_global_root = m_root_directory_relative_to_global_root;
child->m_veil_state = m_veil_state;
child->m_unveiled_paths = m_unveiled_paths.deep_copy();

View file

@ -92,7 +92,7 @@ KResultOr<FlatPtr> Process::sys$unveil(Userspace<const Syscall::SC_unveil_params
// If this case is encountered, the parent node of the path is returned and the custody of that inode is used instead.
RefPtr<Custody> parent_custody; // Parent inode in case of ENOENT
OwnPtr<KString> new_unveiled_path;
auto custody_or_error = VirtualFileSystem::the().resolve_path_without_veil(path.view(), root_directory(), &parent_custody);
auto custody_or_error = VirtualFileSystem::the().resolve_path_without_veil(path.view(), VirtualFileSystem::the().root_custody(), &parent_custody);
if (!custody_or_error.is_error()) {
new_unveiled_path = custody_or_error.value()->try_create_absolute_path();
if (!new_unveiled_path)

View file

@ -325,8 +325,6 @@ void init_stage2(void*)
PANIC("VirtualFileSystem::mount_root failed");
}
Process::current()->set_root_directory(VirtualFileSystem::the().root_custody());
// Switch out of early boot mode.
g_in_early_boot = false;

View file

@ -763,21 +763,6 @@ int set_process_name(const char* name, size_t name_length)
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int chroot(const char* path)
{
return chroot_with_mount_flags(path, -1);
}
int chroot_with_mount_flags(const char* path, int mount_flags)
{
if (!path) {
errno = EFAULT;
return -1;
}
int rc = syscall(SC_chroot, path, strlen(path), mount_flags);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int pledge(const char* promises, const char* execpromises)
{
Syscall::SC_pledge_params params {

View file

@ -46,8 +46,6 @@ int execvp(const char* filename, char* const argv[]);
int execl(const char* filename, const char* arg, ...);
int execle(const char* filename, const char* arg, ...);
int execlp(const char* filename, const char* arg, ...);
int chroot(const char* path);
int chroot_with_mount_flags(const char* path, int mount_flags);
void sync();
__attribute__((noreturn)) void _exit(int status);
pid_t getsid(pid_t);

View file

@ -1,7 +1,7 @@
file(GLOB CMD_SOURCES CONFIGURE_DEPENDS "*.cpp")
list(APPEND SPECIAL_TARGETS test install)
list(APPEND REQUIRED_TARGETS
arp base64 basename cat chmod chown chroot clear comm cp cut date dd df dirname dmesg du echo env expr false fgrep
arp base64 basename cat chmod chown clear comm cp cut date dd df dirname dmesg du echo env expr false fgrep
file find grep groups head host hostname id ifconfig kill killall ln ls mkdir mount mv nproc
pgrep pidof ping pmap ps readlink realpath reboot rm rmdir seq shutdown sleep sort stat stty su tail test
touch tr true umount uname uniq uptime w wc which whoami xargs yes less

View file

@ -1,107 +0,0 @@
/*
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/StringView.h>
#include <LibCore/ArgsParser.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int flags = -1;
uid_t chroot_user = 0;
gid_t chroot_group = 0;
const char* path = nullptr;
const char* program = "/bin/Shell";
const char* userspec = "0:0";
Core::ArgsParser args_parser;
args_parser.set_general_help(
"Run a program in a chroot sandbox. During execution, the program "
"sees the given path as '/', and cannot access files outside of it.");
args_parser.add_positional_argument(path, "New root directory", "path");
args_parser.add_positional_argument(program, "Program to run", "program", Core::ArgsParser::Required::No);
Core::ArgsParser::Option userspec_option {
true,
"The uid:gid to use",
"userspec",
'u',
"userpec",
[&userspec](const char* s) {
Vector<StringView> parts = StringView(s).split_view(':', true);
if (parts.size() != 2)
return false;
userspec = s;
return true;
}
};
args_parser.add_option(move(userspec_option));
Core::ArgsParser::Option mount_options {
true,
"Mount options",
"options",
'o',
"options",
[&flags](const char* s) {
flags = 0;
Vector<StringView> parts = StringView(s).split_view(',');
for (auto& part : parts) {
if (part == "defaults")
continue;
else if (part == "nodev")
flags |= MS_NODEV;
else if (part == "noexec")
flags |= MS_NOEXEC;
else if (part == "nosuid")
flags |= MS_NOSUID;
else if (part == "ro")
flags |= MS_RDONLY;
else if (part == "remount")
flags |= MS_REMOUNT;
else if (part == "bind")
warnln("Ignoring -o bind, as it doesn't make sense for chroot");
else
return false;
}
return true;
}
};
args_parser.add_option(move(mount_options));
args_parser.parse(argc, argv);
if (chroot_with_mount_flags(path, flags) < 0) {
perror("chroot");
return 1;
}
if (chdir("/") < 0) {
perror("chdir(/)");
return 1;
}
// Failed parsing will silently fail open (uid=0; gid=0);
// 0:0 is also the default when no --userspec argument is provided.
auto parts = String(userspec).split(':', true);
chroot_user = (uid_t)strtol(parts[0].characters(), nullptr, 10);
chroot_group = (uid_t)strtol(parts[1].characters(), nullptr, 10);
if (setresgid(chroot_group, chroot_group, chroot_group)) {
perror("setgid");
return 1;
}
if (setresuid(chroot_user, chroot_user, chroot_user)) {
perror("setuid");
return 1;
}
execl(program, program, nullptr);
perror("execl");
return 1;
}