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.
This commit is contained in:
Norman Feske
2012-11-21 15:20:21 +01:00
parent 59eb8bf3a8
commit 959df5d46b
33 changed files with 424 additions and 117 deletions

View File

@@ -14,6 +14,7 @@
#ifndef _INCLUDE__BASE__NATIVE_TYPES_H_
#define _INCLUDE__BASE__NATIVE_TYPES_H_
#include <util/string.h>
#include <base/native_capability.h>
#include <base/stdint.h>
@@ -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_ */

View File

@@ -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 <pd_session/client.h>
#include <base/connection.h>
namespace Genode {
class Pd_connection : public Connection<Pd_session>, public Pd_session_client
{
private:
template <Genode::size_t STRING_MAX_LEN>
struct Arg
{
char string[STRING_MAX_LEN];
Arg() { string[0] = 0; }
};
/**
* Convert root path argument to session-construction parameter
*/
struct Root_arg : Arg<Native_pd_args::ROOT_PATH_MAX_LEN>
{
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<Pd_session>(
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_ */

View File

@@ -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 {
<config>
<parent-provides>
<service name="LOG"/>
<service name="RAM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="ROM"/>
</parent-provides>
<default-route>
<any-service> <parent/> </any-service>
</default-route>
<start name="init" uid="11">
<resource name="RAM" quantum="10M"/>
<config>
<parent-provides>
<service name="LOG"/>
</parent-provides>
<start name="test-printf" root="/tmp/somewhere" uid="33" gid="44">
<resource name="RAM" quantum="10M"/>
</start>
</config>
</start>
</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
}

View File

@@ -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())
{

View File

@@ -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;

View File

@@ -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),
"<unlabeled>");
/*
* 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);
}