init: session-label rewriting

This patch enhances init with the support for rewriting session labels
in the target node of a matching session route. For example, a Noux
instance may have the following session route for the "home" file
system:

<route>
  <service name="File_system" label="home">
    <child name="rump_fs"/>
  </service>
  ...
</route>

At the rump_fs file-system server, the label of the file-system session
will appear as "noux -> home". This information may be evaluated by
rump_fs's server-side policy. However, when renaming the noux instance,
we'd need to update this server-side policy.

With the new mechanism, the client's identity can be hidden from the
server. The label could instead represent the role of the client, or a
name of a physical resource. For example, the Noux route could be
changed to this:

<route>
  <service name="File_system" label="home">
    <child name="rump_fs" label="primary_user"/>
  </service>
  ...
</route>

When the rump_fs receives the session request, it is presented with the
label "primary_user". The fact that the client is "noux" is not taken
into account for the server-side policy selection.

Issue #2248
This commit is contained in:
Norman Feske 2017-02-15 16:42:49 +01:00 committed by Christian Helmuth
parent c0af463b81
commit 8cb0dc9c16
2 changed files with 36 additions and 25 deletions

View File

@ -156,7 +156,8 @@ namespace Init {
* \param child_name name of the originator of the session request
* \param service_name name of the requested service
*/
inline bool service_node_matches(Xml_node service_node, char const *args,
inline bool service_node_matches(Xml_node const service_node,
Session_label const &label,
Child_policy::Name const &child_name,
Service::Name const &service_name)
{
@ -184,15 +185,14 @@ namespace Init {
warning("service node contains both scoped and unscoped label attributes");
typedef String<Session_label::capacity()> Label;
Label const label = service_node.attribute_value(unscoped_attr, Label());
return label == label_from_args(args);
return label == service_node.attribute_value(unscoped_attr, Label());
}
if (!route_depends_on_child_provided_label)
return true;
char const * const scoped_label = skip_label_prefix(
child_name.string(), label_from_args(args).string());
child_name.string(), label.string());
if (!scoped_label)
return false;
@ -602,21 +602,19 @@ class Init::Child : Child_policy, Child_service::Wakeup
Id_space<Parent::Server> &server_id_space() override {
return _session_requester.id_space(); }
Service &resolve_session_request(Service::Name const &service_name,
Session_state::Args const &args) override
Route resolve_session_request(Service::Name const &service_name,
Session_label const &label) override
{
Session_label const label(label_from_args(args.string()));
Service *service = nullptr;
/* check for "config" ROM request */
if ((service = _config_policy.resolve_session_request(service_name.string(), args.string())))
return *service;
if ((service = _config_policy.resolve_session_request_with_label(service_name, label)))
return Route { *service, label };
/* check for "session_requests" ROM request */
if (service_name == Rom_session::service_name()
&& label.last_element() == Session_requester::rom_name())
return _session_requester.service();
return Route { _session_requester.service() };
try {
Xml_node route_node = _default_route_node;
@ -629,16 +627,29 @@ class Init::Child : Child_policy, Child_service::Wakeup
bool service_wildcard = service_node.has_type("any-service");
if (!service_node_matches(service_node, args.string(), name(), service_name))
if (!service_node_matches(service_node, label, name(), service_name))
continue;
Xml_node target = service_node.sub_node();
for (; ; target = target.next()) {
/*
* Determine session label to be provided to the server.
*
* By default, the client's identity (accompanied with
* the a client-provided label) is presented as session
* label to the server. However, the target node can
* explicitly override the client's identity by a
* custom label via the 'label' attribute.
*/
typedef String<Session_label::capacity()> Label;
Label const target_label =
target.attribute_value("label", Label(label.string()));
if (target.has_type("parent")) {
if ((service = find_service(_parent_services, service_name)))
return *service;
return Route { *service, target_label };
if (!service_wildcard) {
warning(name(), ": service lookup for "
@ -658,7 +669,7 @@ class Init::Child : Child_policy, Child_service::Wakeup
&& s.child_name() == server_name)
service = &s; });
if (service)
return *service;
return Route { *service, target_label };
if (!service_wildcard) {
warning(name(), ": lookup to child "
@ -675,7 +686,7 @@ class Init::Child : Child_policy, Child_service::Wakeup
}
if ((service = find_service(_child_services, service_name)))
return *service;
return Route { *service, target_label };
if (!service_wildcard) {
warning(name(), ": lookup for service "
@ -695,7 +706,7 @@ class Init::Child : Child_policy, Child_service::Wakeup
if (!service)
throw Parent::Service_denied();
return *service;
return Route { *service };
}
void filter_session_args(Service::Name const &service,

View File

@ -162,18 +162,18 @@ class Init::Child_policy_provide_rom_file
_session(*ep, ds_cap), _module_name(module_name)
{ }
Service *resolve_session_request_with_label(Service::Name const &name,
Session_label const &label)
{
return (name == "ROM" && label.last_element() == _module_name)
? &_service : nullptr;
}
Service *resolve_session_request(const char *service_name,
const char *args)
{
/* ignore session requests for non-ROM services */
if (strcmp(service_name, "ROM")) return 0;
/* drop out if request refers to another file name */
{
Session_label const label = label_from_args(args);
return label.last_element() == _module_name
? &_service : nullptr;
}
return resolve_session_request_with_label(service_name,
label_from_args(args));
}
};