Userland: Add support for jails

This happens in two ways:
1. LibCore now has two new methods for creating Jails and attaching
   processes to a Jail.
2. We introduce 3 new utilities - lsjails, jail-create and jails-attach,
   which list jails, create jails and attach processes to a Jail,
   respectively.
This commit is contained in:
Liav A 2022-11-02 22:28:58 +02:00 committed by Andrew Kaster
parent 1d0066a5cc
commit 8d8b0d0a34
9 changed files with 174 additions and 0 deletions

View file

@ -0,0 +1,21 @@
## Name
jail-attach - attach a new process to existing jail
## Synopsis
```**sh
$ jail-attach <jail index> <command>
```
## Description
`jail-attach` attaches a new process by specifying a command, to an existing jail, with a
specified jail index.
## Examples
```sh
# Attach the command "ps -ef" to a jail with the index 0
$ jail-attach 0 ps -ef
```

View file

@ -0,0 +1,20 @@
## Name
jail-create - create a new jail
## Synopsis
```**sh
$ jail-create <name>
```
## Description
`jail-create` creates a new jail, with a specified name
## Examples
```sh
# Create jail with the name "test-jail"
$ jail-create test-jail
```

View file

@ -0,0 +1,22 @@
## Name
lsjails - list existing jails
## Synopsis
```**sh
# lsjails
```
## Description
This utility will list all existing jails at the moment of invoking this program.
Please note that if the current process is in jail, it will not see any jail.
## Examples
```sh
# lsjails
Index Name
2 test-jail
```

View file

@ -1000,6 +1000,20 @@ ErrorOr<void> exec_command(Vector<StringView>& command, bool preserve_env)
TRY(Core::System::exec(command.at(0), command, Core::System::SearchInPath::Yes, exec_environment));
return {};
}
ErrorOr<void> join_jail(u64 jail_index)
{
Syscall::SC_jail_attach_params params { jail_index };
int rc = syscall(SC_jail_attach, &params);
HANDLE_SYSCALL_RETURN_VALUE("jail_attach", rc, {});
}
ErrorOr<u64> create_jail(StringView jail_name)
{
Syscall::SC_jail_create_params params { 0, { jail_name.characters_without_null_termination(), jail_name.length() } };
int rc = syscall(SC_jail_create, &params);
HANDLE_SYSCALL_RETURN_VALUE("jail_create", rc, static_cast<u64>(params.index));
}
#endif
ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath search_in_path, Optional<Span<StringView>> environment)

View file

@ -172,6 +172,11 @@ ErrorOr<void> exec_command(Vector<StringView>& command, bool preserve_env);
ErrorOr<void> exec(StringView filename, Span<StringView> arguments, SearchInPath, Optional<Span<StringView>> environment = {});
#ifdef AK_OS_SERENITY
ErrorOr<void> join_jail(u64 jail_index);
ErrorOr<u64> create_jail(StringView jail_name);
#endif
ErrorOr<int> socket(int domain, int type, int protocol);
ErrorOr<void> bind(int sockfd, struct sockaddr const*, socklen_t);
ErrorOr<void> listen(int sockfd, int backlog);

View file

@ -90,6 +90,8 @@ target_link_libraries(grep PRIVATE LibRegex)
target_link_libraries(gunzip PRIVATE LibCompress)
target_link_libraries(gzip PRIVATE LibCompress)
target_link_libraries(headless-browser PRIVATE LibCrypto LibGemini LibGfx LibHTTP LibTLS LibWeb LibWebSocket)
target_link_libraries(jail-attach PRIVATE LibCore LibMain)
target_link_libraries(jail-create PRIVATE LibCore LibMain)
target_link_libraries(js PRIVATE LibCrypto LibJS LibLine LibLocale LibTextCodec)
link_with_locale_data(js)
target_link_libraries(keymap PRIVATE LibKeyboard)

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/ArgsParser.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <unistd.h>
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
unsigned jail_index = 0;
Vector<StringView> command;
Core::ArgsParser args_parser;
bool preserve_env = false;
args_parser.set_stop_on_first_non_option(true);
args_parser.add_option(preserve_env, "Preserve user environment when running command", "preserve-env", 'E');
args_parser.add_positional_argument(jail_index, "Jail Index", "jail index");
args_parser.add_positional_argument(command, "Command to execute", "command");
args_parser.parse(arguments);
TRY(Core::System::pledge("stdio rpath exec id jail tty"));
TRY(Core::System::join_jail(jail_index));
TRY(Core::System::exec_command(command, preserve_env));
return 0;
}

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/ArgsParser.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <unistd.h>
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView new_jail_name;
Core::ArgsParser args_parser;
args_parser.add_positional_argument(new_jail_name, "New jail name", "jail name");
args_parser.parse(arguments);
TRY(Core::System::pledge("stdio jail"));
if (!new_jail_name.is_null() && !new_jail_name.is_empty()) {
TRY(Core::System::create_jail(new_jail_name));
return 0;
}
return Error::from_string_view("Can't create a jail with empty name."sv);
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonArray.h>
#include <AK/JsonObject.h>
#include <LibCore/Stream.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
ErrorOr<int> serenity_main(Main::Arguments)
{
TRY(Core::System::pledge("stdio rpath"));
TRY(Core::System::unveil("/sys/kernel/jails", "r"));
TRY(Core::System::unveil(nullptr, nullptr));
auto jails_data = TRY(Core::Stream::File::open("/sys/kernel/jails"sv, Core::Stream::OpenMode::Read));
TRY(Core::System::pledge("stdio"));
outln("Index Name");
auto file_contents = TRY(jails_data->read_all());
auto json = TRY(JsonValue::from_string(file_contents));
json.as_array().for_each([](auto& value) {
auto& jail = value.as_object();
auto index = jail.get("index"sv).to_string();
auto name = jail.get("name"sv).to_string();
outln("{:4} {:10}", index, name);
});
return 0;
}