diff --git a/repos/gems/run/ssh_exec_channel.run b/repos/gems/run/ssh_exec_channel.run index 305d467cff..a3caa34717 100644 --- a/repos/gems/run/ssh_exec_channel.run +++ b/repos/gems/run/ssh_exec_channel.run @@ -16,30 +16,32 @@ if {[have_spec linux]} { source ${genode_dir}/repos/base/run/platform_drv.inc append_platform_drv_build_components +lappend build_components test/exec_terminal + build $build_components create_boot_directory -import_from_depot [depot_user]/src/[base_src] -import_from_depot [depot_user]/src/bash -import_from_depot [depot_user]/src/coreutils-minimal -import_from_depot [depot_user]/src/exec_terminal -import_from_depot [depot_user]/src/init -import_from_depot [depot_user]/src/ipxe_nic_drv -import_from_depot [depot_user]/src/libc -import_from_depot [depot_user]/src/libcrypto -import_from_depot [depot_user]/src/libssh -import_from_depot [depot_user]/src/noux -import_from_depot [depot_user]/src/platform_drv -import_from_depot [depot_user]/src/posix -import_from_depot [depot_user]/src/ram_fs -import_from_depot [depot_user]/src/rtc_drv -import_from_depot [depot_user]/src/ssh_terminal -import_from_depot [depot_user]/src/vfs -import_from_depot [depot_user]/src/vfs_jitterentropy -import_from_depot [depot_user]/src/vfs_lxip -import_from_depot [depot_user]/src/vim-minimal -import_from_depot [depot_user]/src/zlib +import_from_depot [depot_user]/src/[base_src] \ + [depot_user]/src/bash \ + [depot_user]/src/coreutils-minimal \ + [depot_user]/src/exec_terminal \ + [depot_user]/src/init \ + [depot_user]/src/ipxe_nic_drv \ + [depot_user]/src/libc \ + [depot_user]/src/libcrypto \ + [depot_user]/src/libssh \ + [depot_user]/src/platform_drv \ + [depot_user]/src/posix \ + [depot_user]/src/ram_fs \ + [depot_user]/src/fs_rom \ + [depot_user]/src/rtc_drv \ + [depot_user]/src/ssh_terminal \ + [depot_user]/src/vfs \ + [depot_user]/src/vfs_jitterentropy \ + [depot_user]/src/vfs_lxip \ + [depot_user]/src/vim-minimal \ + [depot_user]/src/zlib # # Generate config @@ -103,7 +105,7 @@ set config { - + @@ -141,7 +143,7 @@ set config { - + @@ -170,37 +172,7 @@ set config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -238,6 +210,7 @@ if {![file exists bin/ed25519_key]} { # generic modules set boot_modules { ed25519_key + exec_terminal } # platform-specific modules @@ -275,38 +248,35 @@ if {[get_cmd_switch --autopilot]} { set port "22" } # wait for ssh_terminal to come up - run_genode_until "--- SSH terminal started ---" 15 $serial_id + run_genode_until "--- SSH terminal started ---.*\n" 15 $serial_id - for {set index 0} {$index < 10} {incr index} { + for {set index 0} {$index < 3} {incr index} { puts "test interactive channel" spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port set ssh_id $spawn_id - run_genode_until "--- noux started ---" 15 $serial_id + run_genode_until {/bin/bash] Hello from Genode!.*\n} 15 $serial_id send -i $ssh_id "ls\r" - run_genode_until "bin" 5 $ssh_id + run_genode_until "bin" 15 $ssh_id send -i $ssh_id "exit\r" - run_genode_until "child \"noux\" exited with exit value 0" 15 $serial_id + run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id puts "test exec channel echo" set echo_text "The quick brown fox jumps over the lazy dog" - spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port "echo $echo_text" + spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port echo "$echo_text" set ssh_id $spawn_id - run_genode_until "--- noux started ---" 15 $serial_id - run_genode_until $echo_text 5 $ssh_id - run_genode_until "child \"noux\" exited with exit value 0" 15 $serial_id + run_genode_until ".*$echo_text.*\n" 15 $ssh_id + run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id puts "test exec channel ls" spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port "ls" set ssh_id $spawn_id - run_genode_until "--- noux started ---" 15 $serial_id - run_genode_until "bin" 5 $ssh_id - run_genode_until "child \"noux\" exited with exit value 0" 15 $serial_id + run_genode_until "bin" 15 $ssh_id + run_genode_until "child \"init\" exited with exit value 0.*\n" 15 $serial_id puts "test exec channel with empty command will not hang" spawn sshpass -p xuon ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l noux $host -p $port " " set ssh_id $spawn_id - run_genode_until "--- noux started ---" 15 $serial_id - run_genode_until "child \"noux\" exited with exit value" 15 $serial_id + run_genode_until "child \"init\" exited with exit value.*\n" 15 $serial_id } puts "" diff --git a/repos/gems/src/test/exec_terminal/main.cc b/repos/gems/src/test/exec_terminal/main.cc index 8c64fca210..b3753d2dcf 100644 --- a/repos/gems/src/test/exec_terminal/main.cc +++ b/repos/gems/src/test/exec_terminal/main.cc @@ -1,6 +1,7 @@ /* - * \brief Component starting noux in a sub-init to execute a specific command + * \brief Component starting bash in a sub-init to execute a specific command * \author Sid Hussmann + * \author Norman Feske * \date 2019-05-11 */ @@ -12,19 +13,12 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* - * Copyright (C) 2019 gapfruit AG - */ - - /* Genode includes */ #include #include #include #include -/* local includes */ - namespace Exec_terminal { class Main; @@ -32,130 +26,273 @@ namespace Exec_terminal { using namespace Genode; } + class Exec_terminal::Main { private: Env& _env; - Attached_rom_dataspace _exec_terminal_config { _env, "exec_terminal.config" }; - Signal_handler
_exec_terminal_config_handler { _env.ep(), *this, &Main::_handle_exec_terminal_config }; - Expanding_reporter _init_config_reporter { _env, "config", "config" }; + Attached_rom_dataspace _config { _env, "exec_terminal.config" }; + Signal_handler
_config_handler { _env.ep(), *this, &Main::_handle_config }; + Expanding_reporter _init_config_reporter { _env, "config", "config" }; + unsigned int _version { 0 }; - unsigned int _version { 0 }; + void _handle_config(); - void _handle_exec_terminal_config(); + void _gen_init_config(Xml_generator &, Xml_node const &config) const; + + void _gen_sub_init_config(Xml_generator &, Xml_node const &config) const; + + static void _gen_service_node(Xml_generator &xml, char const *name) + { + xml.node("service",[&] () { xml.attribute("name", name); }); + } + + static void _gen_parent_provides(Xml_generator &xml) + { + xml.node("parent-provides",[&] () { + _gen_service_node(xml, "CPU"); + _gen_service_node(xml, "File_system"); + _gen_service_node(xml, "LOG"); + _gen_service_node(xml, "PD"); + _gen_service_node(xml, "RM"); + _gen_service_node(xml, "ROM"); + _gen_service_node(xml, "Report"); + _gen_service_node(xml, "Terminal"); + _gen_service_node(xml, "Timer"); + }); + } public: - Main(Env& env) : - _env{env} + Main(Env& env) : _env(env) { - _exec_terminal_config.sigh(_exec_terminal_config_handler); - _handle_exec_terminal_config(); + _config.sigh(_config_handler); + _handle_config(); } - - virtual ~Main() = default; }; -void Exec_terminal::Main::_handle_exec_terminal_config() +void Exec_terminal::Main::_handle_config() { - _exec_terminal_config.update(); + _config.update(); - const Xml_node cfg = _exec_terminal_config.xml(); + Xml_node const config = _config.xml(); - Genode::log(cfg); - if (!cfg.has_type("empty")) { - if (cfg.has_attribute("exit")) { - _init_config_reporter.generate([&] (Xml_generator& xml) { - xml.node("empty"); - }); - } else { + log(config); + if (config.has_type("empty")) + return; - _init_config_reporter.generate([&] (Xml_generator& xml) { - xml.node("parent-provides",[&] () { - xml.node("service",[&] () { xml.attribute("name", "CPU"); }); - xml.node("service",[&] () { xml.attribute("name", "File_system"); }); - xml.node("service",[&] () { xml.attribute("name", "LOG"); }); - xml.node("service",[&] () { xml.attribute("name", "PD"); }); - xml.node("service",[&] () { xml.attribute("name", "RM"); }); - xml.node("service",[&] () { xml.attribute("name", "ROM"); }); - xml.node("service",[&] () { xml.attribute("name", "Report"); }); - xml.node("service",[&] () { xml.attribute("name", "Terminal"); }); - xml.node("service",[&] () { xml.attribute("name", "Timer"); }); - }); + _version++; - xml.node("start",[&] () { - xml.attribute("name", "noux"); - xml.attribute("caps", "500"); - xml.attribute("version", ++_version); - xml.node("resource",[&] () { xml.attribute("name", "RAM"); xml.attribute("quantum", "64M"); }); - xml.node("config",[&] () { - xml.node("fstab",[&] () { - xml.node("tar",[&] () { xml.attribute("name", "bash.tar"); }); - xml.node("tar",[&] () { xml.attribute("name", "coreutils-minimal.tar"); }); - xml.node("tar",[&] () { xml.attribute("name", "vim-minimal.tar"); }); - xml.node("dir",[&] () { - xml.attribute("name", "rw"); - xml.node("fs",[&] () { xml.attribute("label", "rw"); }); - }); - xml.node("dir",[&] () { - xml.attribute("name", "tmp"); - xml.node("ram",[&] () { }); - }); - }); - xml.node("start",[&] () { - xml.attribute("name", "/bin/bash"); - xml.node("env",[&] () { - xml.attribute("name", "TERM"); - xml.attribute("value", "screen"); - }); - xml.node("env",[&] () { - xml.attribute("name", "HOME"); - xml.attribute("value", "/"); - }); - xml.node("env",[&] () { - xml.attribute("name", "IGNOREOF"); - xml.attribute("value", "3"); - }); - if (cfg.has_attribute("command")) { - Genode::String<128> cmd; - cfg.attribute_value("command", &cmd); - if (cmd.valid()) { - xml.node("arg",[&] () { - xml.attribute("value", "-c"); - }); - xml.node("arg",[&] () { - // FIXME appending " ; true" is done to force bash to fork. - // noux will fail otherwise. This invalidates any exit codes. - xml.attribute("value", Genode::String<136>(cmd, " ; true")); - }); - } - } else { - xml.node("env",[&] () { - xml.attribute("name", "PS1"); - xml.attribute("value", "noux@$PWD> "); - }); - } - }); - }); - xml.node("route",[&] () { - xml.node("service",[&] () { xml.attribute("name", "CPU"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "File_system"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "LOG"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "PD"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "RM"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "ROM"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "Terminal"); xml.node("parent",[&] () {}); }); - xml.node("service",[&] () { xml.attribute("name", "Timer"); xml.node("parent",[&] () {}); }); - }); - }); - }); - } - } + _init_config_reporter.generate([&] (Xml_generator &xml) { + + if (config.has_attribute("exit")) + xml.node("empty"); + else + _gen_init_config(xml, config); + }); } -void Component::construct(Genode::Env &env) { +void Exec_terminal::Main::_gen_init_config(Xml_generator &xml, Xml_node const &config) const +{ + _gen_parent_provides(xml); + + xml.node("start",[&] () { + xml.attribute("name", "init"); + xml.attribute("caps", 900); + xml.attribute("version", _version); + + xml.node("resource",[&] () { + xml.attribute("name", "RAM"); + xml.attribute("quantum", "70M"); }); + + xml.node("config", [&] () { + _gen_sub_init_config(xml, config); }); + + xml.node("route",[&] () { + xml.node("any-service",[&] () { + xml.node("parent",[&] () { }); }); }); + }); +} + + +void Exec_terminal::Main::_gen_sub_init_config(Xml_generator &xml, Xml_node const &config) const +{ + xml.attribute("verbose", "no"); + + _gen_parent_provides(xml); + + auto gen_parent_route = [&] (auto name) { + xml.node("service",[&] () { + xml.attribute("name", name); + xml.node("parent",[&] () {}); }); }; + + auto gen_ram = [&] (auto ram) { + xml.node("resource",[&] () { + xml.attribute("name", "RAM"); + xml.attribute("quantum", ram); }); }; + + auto gen_provides_service = [&] (auto name) { + xml.node("provides", [&] () { + xml.node("service", [&] () { + xml.attribute("name", name); }); }); }; + + xml.node("start",[&] () { + xml.attribute("name", "vfs"); + xml.attribute("caps", 120); + gen_ram("32M"); + gen_provides_service("File_system"); + xml.node("config",[&] () { + xml.node("vfs",[&] () { + xml.node("tar",[&] () { xml.attribute("name", "bash.tar"); }); + xml.node("tar",[&] () { xml.attribute("name", "coreutils-minimal.tar"); }); + xml.node("tar",[&] () { xml.attribute("name", "vim-minimal.tar"); }); + xml.node("dir",[&] () { + xml.attribute("name", "rw"); + xml.node("fs",[&] () { xml.attribute("label", "rw"); }); + }); + xml.node("dir", [&] () { + xml.attribute("name", "dev"); + xml.node("terminal", [&] () { }); + xml.node("inline", [&] () { + xml.attribute("name", "rtc"); + xml.append("2018-01-01 00:01"); + }); + }); + xml.node("dir",[&] () { + xml.attribute("name", "tmp"); + xml.node("ram",[&] () { }); + }); + xml.node("inline", [&] () { + xml.attribute("name", ".bash_profile"); + xml.append("echo Hello from Genode! > /dev/log"); + }); + }); + xml.node("default-policy", [&] () { + xml.attribute("root", "/"); + xml.attribute("writeable", "yes"); + }); + }); + xml.node("route",[&] () { + gen_parent_route("CPU"); + gen_parent_route("LOG"); + gen_parent_route("PD"); + gen_parent_route("ROM"); + gen_parent_route("File_system"); + gen_parent_route("Terminal"); + }); + }); + + auto gen_vfs_route = [&] () { + xml.node("service",[&] () { + xml.attribute("name", "File_system"); + xml.node("child",[&] () { xml.attribute("name", "vfs"); }); }); }; + + xml.node("start",[&] () { + xml.attribute("name", "vfs_rom"); + xml.attribute("caps", 100); + gen_ram("16M"); + gen_provides_service("ROM"); + xml.node("binary", [&] () { xml.attribute("name", "fs_rom"); }); + xml.node("config", [&] () { }); + xml.node("route", [&] () { + gen_parent_route("CPU"); + gen_parent_route("LOG"); + gen_parent_route("PD"); + gen_parent_route("ROM"); + gen_vfs_route(); + }); + }); + + xml.node("start",[&] () { + xml.attribute("name", "/bin/bash"); + xml.attribute("caps", 500); + gen_ram("16M"); + + /* exit sub init when leaving bash */ + xml.node("exit",[&] () { + xml.attribute("propagate", "yes"); }); + + xml.node("config",[&] () { + + xml.node("libc",[&] () { + xml.attribute("stdin", "/dev/terminal"); + xml.attribute("stdout", "/dev/terminal"); + xml.attribute("stderr", "/dev/terminal"); + xml.attribute("rtc", "/dev/rtc"); + }); + + xml.node("vfs",[&] () { + xml.node("fs",[&] () { xml.attribute("label", "rw"); }); + xml.node("dir", [&] () { + xml.attribute("name", "dev"); + xml.node("null", [&] () { }); + xml.node("log", [&] () { }); + }); + }); + + auto gen_env = [&] (auto key, auto value) { + xml.node("env",[&] () { + xml.attribute("key", key); + xml.attribute("value", value); }); }; + + auto gen_arg = [&] (auto value) { + xml.node("arg",[&] () { + xml.attribute("value", value); }); }; + + gen_env("TERM", "screen"); + gen_env("HOME", "/"); + gen_env("PATH", "/bin"); + gen_env("HISTFILE", ""); + gen_env("IGNOREOF", "3"); + + gen_arg("/bin/bash"); + + if (config.has_attribute("command")) { + + typedef String<128> Command; + Command const command = config.attribute_value("command", Command()); + + if (command.valid()) { + gen_arg("-c"); + + /* + * XXX appending " ; true" is done to force bash to fork. + * Bash fails to return the proper exit code otherwise. + */ + gen_arg(String<200>(command, " ; true")); + } + } else { + gen_env("PS1", "noux@$PWD> "); + gen_arg("--login"); + } + }); + xml.node("route",[&] () { + xml.node("service",[&] () { + xml.attribute("name", "ROM"); + xml.attribute("label_last", "/bin/bash"); + xml.node("child",[&] () { xml.attribute("name", "vfs_rom"); }); + }); + xml.node("service",[&] () { + xml.attribute("name", "ROM"); + xml.attribute("label_prefix", "/bin"); + xml.node("child",[&] () { xml.attribute("name", "vfs_rom"); }); + }); + gen_parent_route("CPU"); + gen_parent_route("LOG"); + gen_parent_route("PD"); + gen_parent_route("RM"); + gen_parent_route("ROM"); + gen_parent_route("Timer"); + gen_vfs_route(); + }); + }); +} + + +void Component::construct(Genode::Env &env) +{ static Exec_terminal::Main main(env); } diff --git a/tool/autopilot.list b/tool/autopilot.list index 96bc320585..03c1917e78 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -48,6 +48,7 @@ rtc rump_ext2 sd_card_bench seoul-auto +ssh_exec_channel smartcard smbios_decoder smp