From 959df5d46be13002bd07ebf9e00b923c21ba20c8 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 21 Nov 2012 15:20:21 +0100 Subject: [PATCH] Generalize handling of PD-session arguments On Linux, we want to attach additional attributes to processes, i.e., the chroot location, the designated UID, and GID. Instead of polluting the generic code with such Linux-specific platform details, I introduced the new 'Native_pd_args' type, which can be customized for each platform. The platform-dependent policy of init is factored out in the new 'pd_args' library. The new 'base-linux/run/lx_pd_args.run' script can be used to validate the propagation of those attributes into core. Note that this patch does not add the interpretation of the new UID and PID attributes by core. This will be subject of a follow-up patch. Related to #510. --- base-codezero/include/base/native_types.h | 2 + base-fiasco/include/base/native_types.h | 2 + base-foc/include/base/native_types.h | 2 + base-host/include/base/native_types.h | 2 + base-hw/include/base/native_types.h | 2 + base-linux/include/base/native_types.h | 30 ++++++ base-linux/include/pd_session/connection.h | 100 ++++++++++++++++++ base-linux/run/lx_pd_args.run | 59 +++++++++++ base-linux/src/base/process/process.cc | 4 +- .../src/core/include/pd_session_component.h | 2 + base-linux/src/core/pd_session_component.cc | 23 +++- base-mb/include/base/native_types.h | 6 +- base-nova/include/base/native_types.h | 1 + base-okl4/include/base/native_types.h | 2 + base-pistachio/include/base/native_types.h | 2 + base/include/base/child.h | 7 +- base/include/base/process.h | 7 +- base/include/pd_session/connection.h | 9 +- base/src/base/child/child.cc | 2 +- base/src/base/process/process.cc | 2 +- os/include/init/child.h | 35 ++---- os/include/init/child_policy.h | 46 ++------ os/include/loader_session/client.h | 5 +- os/include/loader_session/loader_session.h | 4 +- os/lib/mk/init_pd_args.mk | 3 + os/lib/mk/linux/init_pd_args.mk | 3 + os/src/init/linux/pd_args.cc | 99 +++++++++++++++++ os/src/init/pd_args.cc | 23 ++++ os/src/init/target.mk | 2 +- os/src/server/loader/child.h | 42 ++++---- os/src/server/loader/main.cc | 5 +- os/src/server/loader/target.mk | 6 +- os/src/test/chroot_loader/main.cc | 2 +- 33 files changed, 424 insertions(+), 117 deletions(-) create mode 100644 base-linux/include/pd_session/connection.h create mode 100644 base-linux/run/lx_pd_args.run create mode 100644 os/lib/mk/init_pd_args.mk create mode 100644 os/lib/mk/linux/init_pd_args.mk create mode 100644 os/src/init/linux/pd_args.cc create mode 100644 os/src/init/pd_args.cc diff --git a/base-codezero/include/base/native_types.h b/base-codezero/include/base/native_types.h index 7a5f428e13..33302d9a1e 100644 --- a/base-codezero/include/base/native_types.h +++ b/base-codezero/include/base/native_types.h @@ -130,6 +130,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } diff --git a/base-fiasco/include/base/native_types.h b/base-fiasco/include/base/native_types.h index 26cb3232c8..e487da0fdf 100644 --- a/base-fiasco/include/base/native_types.h +++ b/base-fiasco/include/base/native_types.h @@ -88,6 +88,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-foc/include/base/native_types.h b/base-foc/include/base/native_types.h index 6b711dacb2..3b341ff8ef 100644 --- a/base-foc/include/base/native_types.h +++ b/base-foc/include/base/native_types.h @@ -161,6 +161,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-host/include/base/native_types.h b/base-host/include/base/native_types.h index 490501b543..d4fd6d105b 100644 --- a/base-host/include/base/native_types.h +++ b/base-host/include/base/native_types.h @@ -46,6 +46,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index db30e3e3fc..5addf30596 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -151,6 +151,8 @@ namespace Genode */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-linux/include/base/native_types.h b/base-linux/include/base/native_types.h index 303552d36c..c371b2152b 100644 --- a/base-linux/include/base/native_types.h +++ b/base-linux/include/base/native_types.h @@ -14,6 +14,7 @@ #ifndef _INCLUDE__BASE__NATIVE_TYPES_H_ #define _INCLUDE__BASE__NATIVE_TYPES_H_ +#include #include #include @@ -149,6 +150,35 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + class Native_pd_args + { + public: + + enum { ROOT_PATH_MAX_LEN = 256 }; + + private: + + char _root[ROOT_PATH_MAX_LEN]; + + unsigned _uid; + unsigned _gid; + + public: + + Native_pd_args() : _uid(0), _gid(0) { _root[0] = 0; } + + Native_pd_args(char const *root, unsigned uid, unsigned gid) + : + _uid(uid), _gid(gid) + { + Genode::strncpy(_root, root, sizeof(_root)); + } + + char const *root() const { return _root; } + unsigned uid() const { return _uid; } + unsigned gid() const { return _gid; } + }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-linux/include/pd_session/connection.h b/base-linux/include/pd_session/connection.h new file mode 100644 index 0000000000..4028e7929a --- /dev/null +++ b/base-linux/include/pd_session/connection.h @@ -0,0 +1,100 @@ +/* + * \brief Connection to PD service + * \author Norman Feske + * \date 2012-11-21 + * + * In contrast to the generic version of 'pd_session/connection.h', the + * Linux-specific version supplies additional argument to core's PD service: + * + * :'root': is the path of a chroot environment of the process + * :'uid': is the user ID of the process + * :'gid': is the designated group ID of the process + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__PD_SESSION__CONNECTION_H_ +#define _INCLUDE__PD_SESSION__CONNECTION_H_ + +#include +#include + +namespace Genode { + + class Pd_connection : public Connection, public Pd_session_client + { + private: + + template + struct Arg + { + char string[STRING_MAX_LEN]; + + Arg() { string[0] = 0; } + }; + + /** + * Convert root path argument to session-construction parameter + */ + struct Root_arg : Arg + { + Root_arg(Native_pd_args const *args) + { + if (args && args->root() && args->root()[0]) + Genode::snprintf(string, sizeof(string), ", root=\"%s\"", + args->root()); + } + }; + + /** + * Convert UID argument to session-construction parameter + */ + struct Uid_arg : Arg<64> + { + Uid_arg(Native_pd_args const *args) + { + if (args && args->uid()) + Genode::snprintf(string, sizeof(string), ", uid=%u", + args->uid()); + } + }; + + /** + * Convert GID argument to session-construction parameter + */ + struct Gid_arg : Arg<64> + { + Gid_arg(Native_pd_args const *args) + { + if (args && args->gid()) + Genode::snprintf(string, sizeof(string), ", gid=%u", + args->gid()); + } + }; + + public: + + /** + * Constructor + * + * \param label session label + * \param pd_args Linux-specific PD-session arguments + */ + Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0) + : + Connection( + session("ram_quota=4K, label=\"%s\"%s%s%s", label, + Root_arg(pd_args).string, + Uid_arg(pd_args).string, + Gid_arg(pd_args).string)), + Pd_session_client(cap()) + { } + }; +} + +#endif /* _INCLUDE__PD_SESSION__CONNECTION_H_ */ diff --git a/base-linux/run/lx_pd_args.run b/base-linux/run/lx_pd_args.run new file mode 100644 index 0000000000..d8d3402358 --- /dev/null +++ b/base-linux/run/lx_pd_args.run @@ -0,0 +1,59 @@ +# +# \brief Test for supplying Linux-specific PD-session arguments to core +# \author Norman Feske +# \date 2012-11-21 +# + +build "core init test/printf" + +assert_spec linux + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init test-printf" + +# +# The chroot to '/tmp/somewhere' is expected to fail. We just want to validate +# that the PD-session arguments are properly propagated into core. Hence, we +# can take the error message as exit condition of the test run. +# +run_genode_until {chroot path does not point to valid directory} 10 + +# keep only the lines containing the relevant core output +grep_output {^ .*:} + +compare_output_to { +uid: 11 +root: /tmp/somewhere +uid: 11 +gid: 44 +} + diff --git a/base-linux/src/base/process/process.cc b/base-linux/src/base/process/process.cc index 73c611d5c0..8d1fe4c4bb 100644 --- a/base-linux/src/base/process/process.cc +++ b/base-linux/src/base/process/process.cc @@ -58,9 +58,9 @@ Process::Process(Dataspace_capability elf_data_ds_cap, Rm_session_capability rm_session_cap, Parent_capability parent_cap, char const *name, - char const *root) + Native_pd_args const *pd_args) : - _pd(name, root), + _pd(name, pd_args), _cpu_session_client(Cpu_session_capability()), _rm_session_client(Rm_session_capability()) { diff --git a/base-linux/src/core/include/pd_session_component.h b/base-linux/src/core/include/pd_session_component.h index 51929547bc..6386e69d7c 100644 --- a/base-linux/src/core/include/pd_session_component.h +++ b/base-linux/src/core/include/pd_session_component.h @@ -33,6 +33,8 @@ namespace Genode { unsigned long _pid; char _label[LABEL_MAX_LEN]; char _root[ROOT_PATH_MAX_LEN]; + unsigned _uid; + unsigned _gid; Parent_capability _parent; Rpc_entrypoint *_ds_ep; diff --git a/base-linux/src/core/pd_session_component.cc b/base-linux/src/core/pd_session_component.cc index 64f2339603..0ec0fc18a0 100644 --- a/base-linux/src/core/pd_session_component.cc +++ b/base-linux/src/core/pd_session_component.cc @@ -274,11 +274,32 @@ static const char *get_env(const char *key) Pd_session_component::Pd_session_component(Rpc_entrypoint *ep, const char *args) : - _pid(0), _ds_ep(ep) + _pid(0), _uid(0), _gid(0), _ds_ep(ep) { Arg_string::find_arg(args, "label").string(_label, sizeof(_label), ""); + + /* + * Read Linux-specific session arguments + */ Arg_string::find_arg(args, "root").string(_root, sizeof(_root), ""); + + _uid = Arg_string::find_arg(args, "uid").ulong_value(0); + _gid = Arg_string::find_arg(args, "gid").ulong_value(0); + + bool const is_chroot = (Genode::strcmp(_root, "") != 0); + + /* + * Print Linux-specific session arguments if specified + * + * This output used for the automated 'lx_pd_args' test. + */ + if (is_chroot || _uid || _gid) + printf("PD session for '%s'\n", _label); + + if (is_chroot) printf(" root: %s\n", _root); + if (_uid) printf(" uid: %u\n", _uid); + if (_gid) printf(" gid: %u\n", _gid); } diff --git a/base-mb/include/base/native_types.h b/base-mb/include/base/native_types.h index 31460a0633..65a71d6c9f 100755 --- a/base-mb/include/base/native_types.h +++ b/base-mb/include/base/native_types.h @@ -57,10 +57,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ - - - - diff --git a/base-nova/include/base/native_types.h b/base-nova/include/base/native_types.h index f940c403b2..0a7f05c4cd 100644 --- a/base-nova/include/base/native_types.h +++ b/base-nova/include/base/native_types.h @@ -230,6 +230,7 @@ namespace Genode { static addr_t context_virtual_size() { return 0x00100000UL; } }; + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-okl4/include/base/native_types.h b/base-okl4/include/base/native_types.h index 46995be8da..0d1435c76a 100644 --- a/base-okl4/include/base/native_types.h +++ b/base-okl4/include/base/native_types.h @@ -103,6 +103,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base-pistachio/include/base/native_types.h b/base-pistachio/include/base/native_types.h index cf004fbdcb..b0aaf2a3dc 100644 --- a/base-pistachio/include/base/native_types.h +++ b/base-pistachio/include/base/native_types.h @@ -89,6 +89,8 @@ namespace Genode { */ static addr_t context_virtual_size() { return 0x00100000UL; } }; + + struct Native_pd_args { }; } #endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */ diff --git a/base/include/base/child.h b/base/include/base/child.h index 3b5ada5229..c65cc995ea 100644 --- a/base/include/base/child.h +++ b/base/include/base/child.h @@ -95,9 +95,12 @@ namespace Genode { virtual Ram_session *ref_ram_session() { return env()->ram_session(); } /** - * Return root path of the child's PD session (only used on Linux) + * Return platform-specific PD-session arguments + * + * This function is used on Linux to supply additional PD-session + * argument to core, i.e., the chroot path, the UID, and the GID. */ - virtual char const *root() const { return ""; } + virtual Native_pd_args const *pd_args() const { return 0; } }; diff --git a/base/include/base/process.h b/base/include/base/process.h index baa2a9de1d..79f4f2ad0d 100644 --- a/base/include/base/process.h +++ b/base/include/base/process.h @@ -57,8 +57,9 @@ namespace Genode { * \param rm_session RM session for the new protection domain * \param parent parent of the new protection domain * \param name name of protection domain (can be used - * in debugging) - * \param root optional chroot path (only on Linux) + * for debugging) + * \param pd_args platform-specific arguments supplied to + * the PD session of the process * * The dataspace 'elf_data_ds' can be read-only. * @@ -71,7 +72,7 @@ namespace Genode { Rm_session_capability rm_session, Parent_capability parent, char const *name, - char const *root = ""); + Native_pd_args const *args = 0); /** * Destructor diff --git a/base/include/pd_session/connection.h b/base/include/pd_session/connection.h index c93e010813..ff46d6c7f6 100644 --- a/base/include/pd_session/connection.h +++ b/base/include/pd_session/connection.h @@ -25,15 +25,10 @@ namespace Genode { * Constructor * * \param label session label - * \param root chroot path (only on Linux) */ - Pd_connection(char const *label = "", char const *root = "") + Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0) : - Connection(session("ram_quota=4K, label=\"%s\"%s%s%s", - label, - (root && root[0]) ? ", root=\"" : "", - (root && root[0]) ? root : "", - (root && root[0]) ? "\"" : "")), + Connection(session("ram_quota=4K, label=\"%s\"", label)), Pd_session_client(cap()) { } }; diff --git a/base/src/base/child/child.cc b/base/src/base/child/child.cc index 85611f0ab2..bbec00256d 100644 --- a/base/src/base/child/child.cc +++ b/base/src/base/child/child.cc @@ -431,7 +431,7 @@ Child::Child(Dataspace_capability elf_ds, _parent_cap(_entrypoint->manage(this)), _policy(policy), _server(ram), - _process(elf_ds, ram, cpu, rm, _parent_cap, policy->name(), policy->root()) + _process(elf_ds, ram, cpu, rm, _parent_cap, policy->name(), policy->pd_args()) { } diff --git a/base/src/base/process/process.cc b/base/src/base/process/process.cc index c007108ac6..b0e4131282 100644 --- a/base/src/base/process/process.cc +++ b/base/src/base/process/process.cc @@ -175,7 +175,7 @@ Process::Process(Dataspace_capability elf_ds_cap, Rm_session_capability rm_session_cap, Parent_capability parent_cap, char const *name, - char const *pd_args) + Native_pd_args const *pd_args) : _pd(name, pd_args), _cpu_session_client(cpu_session_cap), diff --git a/os/include/init/child.h b/os/include/init/child.h index 552d9e388d..4e8a8f4aff 100644 --- a/os/include/init/child.h +++ b/os/include/init/child.h @@ -299,29 +299,12 @@ namespace Init { } _name; /** - * Path of the child's chroot environment (on Linux) + * Platform-specific PD-session arguments */ - struct Root + struct Pd_args : Genode::Native_pd_args { - /* - * XXX dimension ROOT_PATH_LEN depending on the platform - */ - enum { ROOT_PATH_LEN = 256 }; - char path[ROOT_PATH_LEN]; - - /** - * Constructor - */ - Root(Genode::Xml_node start_node) - { - path[0] = 0; - - try { - start_node.attribute("root").value(path, sizeof(path)); } - catch (Genode::Xml_node::Nonexistent_attribute) { } - } - - } _root; + Pd_args(Genode::Xml_node start_node); + } _pd_args; /** * Resources assigned to the child @@ -394,7 +377,7 @@ namespace Init { Init::Child_policy_provide_rom_file _config_policy; Init::Child_policy_provide_rom_file _binary_policy; Init::Child_policy_redirect_rom_file _configfile_policy; - Init::Child_policy_prepend_chroot_path _chroot_policy; + Init::Child_policy_pd_args _pd_args_policy; public: @@ -411,7 +394,7 @@ namespace Init { _default_route_node(default_route_node), _name_registry(name_registry), _name(start_node, name_registry), - _root(start_node), + _pd_args(start_node), _resources(start_node, _name.unique, prio_levels_log2), _entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false), _binary_rom(_name.file, _name.unique), @@ -426,7 +409,7 @@ namespace Init { _config_policy("config", _config.dataspace(), &_entrypoint), _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), _configfile_policy("config", _config.filename()), - _chroot_policy(_root.path) + _pd_args_policy(&_pd_args) { using namespace Genode; @@ -576,7 +559,7 @@ namespace Init { _labeling_policy. filter_session_args(service, args, args_len); _priority_policy. filter_session_args(service, args, args_len); _configfile_policy.filter_session_args(service, args, args_len); - _chroot_policy. filter_session_args(service, args, args_len); + _pd_args_policy. filter_session_args(service, args, args_len); } bool announce_service(const char *service_name, @@ -599,7 +582,7 @@ namespace Init { return true; } - char const *root() const { return _root.path; } + Genode::Native_pd_args const *pd_args() const { return &_pd_args; } }; } diff --git a/os/include/init/child_policy.h b/os/include/init/child_policy.h index 8bcbb53cf9..febf1ec527 100644 --- a/os/include/init/child_policy.h +++ b/os/include/init/child_policy.h @@ -64,53 +64,25 @@ namespace Init { /** - * Policy for prepending the chroot path of the child + * Policy for handling platform-specific PD-session arguments * - * This policy is effective only on the Linux base platform. - * - * By applying this policy, the chroot path of the child gets supplied - * to PD session requests. + * This policy is used onthe Linux base platform for prepending the chroot + * path of the child. By applying this policy, the chroot path of the child + * gets supplied to PD session requests. */ - class Child_policy_prepend_chroot_path + class Child_policy_pd_args { private: - char const *_root_prefix; + Genode::Native_pd_args const *_pd_args; public: - Child_policy_prepend_chroot_path(const char *root_prefix) - : _root_prefix(root_prefix) { } + Child_policy_pd_args(Genode::Native_pd_args const *pd_args) + : _pd_args(pd_args) { } - /** - * Filter arguments of session request - * - * This function prepends the '_root' to the 'root' session - * argument of PD sessions initiated through the child (not the - * child's PD session). - */ void filter_session_args(const char *session, char *args, - Genode::size_t args_len) - { - using namespace Genode; - - /* - * Specify 'Genode' namespace to remove possible ambiguity of - * 'strcmp' when including the header along with libc headers. - */ - if (Genode::strcmp(session, "PD") != 0) - return; - - char path[Parent::Session_args::MAX_SIZE]; - Arg_string::find_arg(args, "root").string(path, sizeof(path), ""); - - char value[Parent::Session_args::MAX_SIZE]; - Genode::snprintf(value, sizeof(value), - "\"%s%s\"", - _root_prefix, path); - - Arg_string::set_arg(args, args_len, "root", value); - } + Genode::size_t args_len); }; diff --git a/os/include/loader_session/client.h b/os/include/loader_session/client.h index 519c20dab0..98918bba68 100644 --- a/os/include/loader_session/client.h +++ b/os/include/loader_session/client.h @@ -41,8 +41,9 @@ namespace Loader { void view_ready_sigh(Signal_context_capability sigh) { call(sigh); } - void start(Name const &binary, Name const &label = "", Path const &root = "") { - call(binary, label, root); } + void start(Name const &binary, Name const &label = "", + Native_pd_args const &pd_args = Native_pd_args()) { + call(binary, label, pd_args); } Nitpicker::View_capability view() { return call(); } diff --git a/os/include/loader_session/loader_session.h b/os/include/loader_session/loader_session.h index d1537879c9..344ba0ec62 100644 --- a/os/include/loader_session/loader_session.h +++ b/os/include/loader_session/loader_session.h @@ -123,7 +123,7 @@ namespace Loader { * not obtained as ROM module */ virtual void start(Name const &binary, Name const &label = "", - Path const &root = "") = 0; + Native_pd_args const &pd_args = Native_pd_args()) = 0; /** * Return first nitpicker view created by the loaded subsystem @@ -154,7 +154,7 @@ namespace Loader { GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability); GENODE_RPC_THROW(Rpc_start, void, start, GENODE_TYPE_LIST(Rom_module_does_not_exist), - Name const &, Name const &, Path const &); + Name const &, Name const &, Native_pd_args const &); GENODE_RPC_THROW(Rpc_view, Nitpicker::View_capability, view, GENODE_TYPE_LIST(View_does_not_exist)); GENODE_RPC(Rpc_view_geometry, View_geometry, view_geometry); diff --git a/os/lib/mk/init_pd_args.mk b/os/lib/mk/init_pd_args.mk new file mode 100644 index 0000000000..ef8d0b4e99 --- /dev/null +++ b/os/lib/mk/init_pd_args.mk @@ -0,0 +1,3 @@ +SRC_CC = pd_args.cc + +vpath pd_args.cc $(REP_DIR)/src/init diff --git a/os/lib/mk/linux/init_pd_args.mk b/os/lib/mk/linux/init_pd_args.mk new file mode 100644 index 0000000000..ed03ff22ad --- /dev/null +++ b/os/lib/mk/linux/init_pd_args.mk @@ -0,0 +1,3 @@ +SRC_CC = pd_args.cc + +vpath pd_args.cc $(REP_DIR)/src/init/linux diff --git a/os/src/init/linux/pd_args.cc b/os/src/init/linux/pd_args.cc new file mode 100644 index 0000000000..72fa0b2933 --- /dev/null +++ b/os/src/init/linux/pd_args.cc @@ -0,0 +1,99 @@ +/* + * \brief Extract 'Native_pd_args' from '' node of the init config + * \author Norman Feske + * \date 2012-11.21 + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* init includes */ +#include + + +/** + * Read chroot path from XML node + */ +struct Root +{ + char path[Genode::Native_pd_args::ROOT_PATH_MAX_LEN]; + + Root(Genode::Xml_node node) + { + path[0] = 0; + try { node.attribute("root").value(path, sizeof(path)); } + catch (Genode::Xml_node::Nonexistent_attribute) { } + } +}; + + +/** + * Read unsigned ID from XML node + */ +static unsigned id_value(char const *attr, Genode::Xml_node node) +{ + unsigned value = 0; + try { node.attribute(attr).value(&value); } + catch (Genode::Xml_node::Nonexistent_attribute) { } + return value; +} + + +Init::Child::Pd_args::Pd_args(Genode::Xml_node start_node) +: + Genode::Native_pd_args(Root(start_node).path, + id_value("uid", start_node), + id_value("gid", start_node)) +{ } + + +void Init::Child_policy_pd_args::filter_session_args(char const *session, + char *args, + Genode::size_t args_len) +{ + /* + * Specify 'Genode' namespace to remove possible ambiguity of + * 'strcmp' when including the header along with libc headers. + */ + if (Genode::strcmp(session, "PD") != 0) + return; + + /* + * Apply platform-specific PD-session arguments only if specified. + */ + if (!_pd_args) + return; + + using namespace Genode; + + /* + * Prepend the '_root' to the 'root' session argument of PD sessions + * initiated through the child (not the child's PD session). + */ + if (_pd_args->root() && _pd_args->root()[0]) { + + char path[Parent::Session_args::MAX_SIZE]; + Arg_string::find_arg(args, "root").string(path, sizeof(path), ""); + + char value[Parent::Session_args::MAX_SIZE]; + Genode::snprintf(value, sizeof(value), + "\"%s%s\"", + _pd_args->root(), path); + + Arg_string::set_arg(args, args_len, "root", value); + } + + /* + * Add user ID and group ID to session arguments + */ + if (_pd_args->uid()) + Arg_string::set_arg(args, args_len, "uid", _pd_args->uid()); + + if (_pd_args->gid()) + Arg_string::set_arg(args, args_len, "gid", _pd_args->gid()); +} + diff --git a/os/src/init/pd_args.cc b/os/src/init/pd_args.cc new file mode 100644 index 0000000000..148c2ccee6 --- /dev/null +++ b/os/src/init/pd_args.cc @@ -0,0 +1,23 @@ +/* + * \brief Extract 'Native_pd_args' from '' node of the init config + * \author Norman Feske + * \date 2012-11.21 + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* init includes */ +#include + + +Init::Child::Pd_args::Pd_args(Genode::Xml_node start_node) { } + + +void Init::Child_policy_pd_args::filter_session_args(char const *, + char *, Genode::size_t) +{ } diff --git a/os/src/init/target.mk b/os/src/init/target.mk index f9ba59e110..aabae562c4 100644 --- a/os/src/init/target.mk +++ b/os/src/init/target.mk @@ -1,3 +1,3 @@ TARGET = init SRC_CC = main.cc -LIBS = env cxx server child +LIBS = env cxx server child init_pd_args diff --git a/os/src/server/loader/child.h b/os/src/server/loader/child.h index 382738bcf4..0aa18f06c7 100644 --- a/os/src/server/loader/child.h +++ b/os/src/server/loader/child.h @@ -36,10 +36,7 @@ namespace Loader { Label(char const *l) { strncpy(string, l, sizeof(string)); } } _label; - struct Path { - char string[Session::Path::MAX_SIZE]; - Path(char const *l) { strncpy(string, l, sizeof(string)); } - } _root; + Native_pd_args _pd_args; Rpc_entrypoint &_ep; @@ -75,9 +72,9 @@ namespace Loader { Rom_session_client _binary_rom_session; - Init::Child_policy_provide_rom_file _binary_policy; - Init::Child_policy_enforce_labeling _labeling_policy; - Init::Child_policy_prepend_chroot_path _chroot_policy; + Init::Child_policy_provide_rom_file _binary_policy; + Init::Child_policy_enforce_labeling _labeling_policy; + Init::Child_policy_pd_args _pd_args_policy; int _max_width, _max_height; @@ -97,19 +94,20 @@ namespace Loader { public: - Child(char const *binary_name, - char const *label, - char const *root, - Rpc_entrypoint &ep, - Ram_session_client &ram_session_client, - size_t ram_quota, - Service_registry &parent_services, - Service &local_rom_service, - Service &local_nitpicker_service, - int max_width, int max_height) + Child(char const *binary_name, + char const *label, + Native_pd_args const &pd_args, + Rpc_entrypoint &ep, + Ram_session_client &ram_session_client, + size_t ram_quota, + Service_registry &parent_services, + Service &local_rom_service, + Service &local_nitpicker_service, + int max_width, + int max_height) : _label(label), - _root(root), + _pd_args(pd_args), _ep(ep), _resources(_label.string, ram_session_client, ram_quota), _parent_services(parent_services), @@ -118,7 +116,7 @@ namespace Loader { _binary_rom_session(_rom_session(binary_name)), _binary_policy("binary", _binary_rom_session.dataspace(), &_ep), _labeling_policy(_label.string), - _chroot_policy(_root.string), + _pd_args_policy(&_pd_args), _max_width(max_width), _max_height(max_height), _child(_binary_rom_session.dataspace(), _resources.ram.cap(), _resources.cpu.cap(), @@ -135,13 +133,13 @@ namespace Loader { ** Child-policy interface ** ****************************/ - const char *name() const { return _label.string; } - char const *root() const { return _root.string; } + char const *name() const { return _label.string; } + Native_pd_args const *pd_args() const { return &_pd_args; } void filter_session_args(char const *service, char *args, size_t args_len) { _labeling_policy.filter_session_args(service, args, args_len); - _chroot_policy. filter_session_args(service, args, args_len); + _pd_args_policy. filter_session_args(service, args, args_len); if (!strcmp(service, "Nitpicker")) { diff --git a/os/src/server/loader/main.cc b/os/src/server/loader/main.cc index 6496565e7d..0cdf94c97f 100644 --- a/os/src/server/loader/main.cc +++ b/os/src/server/loader/main.cc @@ -244,7 +244,8 @@ namespace Loader { _nitpicker_service.view_ready_sigh = sigh; } - void start(Name const &binary_name, Name const &label, Path const &root) + void start(Name const &binary_name, Name const &label, + Genode::Native_pd_args const &pd_args) { if (_child) { PWRN("cannot start subsystem twice"); @@ -258,7 +259,7 @@ namespace Loader { try { _child = new (&_md_alloc) Child(binary_name.string(), label.string(), - root.string(), _ep, _ram_session_client, + pd_args, _ep, _ram_session_client, ram_quota, _parent_services, _rom_service, _nitpicker_service, _width, _height); } diff --git a/os/src/server/loader/target.mk b/os/src/server/loader/target.mk index e66f2ad042..754675d237 100644 --- a/os/src/server/loader/target.mk +++ b/os/src/server/loader/target.mk @@ -1,4 +1,4 @@ -TARGET = loader -LIBS = cxx env thread server child signal -SRC_CC = main.cc +TARGET = loader +LIBS = cxx env thread server child signal init_pd_args +SRC_CC = main.cc INC_DIR += $(PRG_DIR) diff --git a/os/src/test/chroot_loader/main.cc b/os/src/test/chroot_loader/main.cc index c604e19ba9..5015cbee20 100644 --- a/os/src/test/chroot_loader/main.cc +++ b/os/src/test/chroot_loader/main.cc @@ -135,7 +135,7 @@ class Chroot_subsystem /* start execution of new subsystem */ _loader.start(binary_name, Loader::Session::Name(_label), - Loader::Session::Path(chroot_path)); + Native_pd_args(chroot_path, 0, 0)); } };