mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 03:55:04 +00:00
parent
76db3b9c06
commit
9a3185f8ed
@ -73,8 +73,6 @@ namespace Genode {
|
||||
|
||||
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
|
||||
typedef Fiasco::l4_threadid_t Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
@ -193,8 +193,6 @@ namespace Genode {
|
||||
|
||||
|
||||
typedef int Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
@ -40,8 +40,6 @@ namespace Genode
|
||||
*/
|
||||
struct Native_region;
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
||||
/**
|
||||
* Get the the minimal supported page-size log 2
|
||||
*/
|
||||
|
@ -33,7 +33,7 @@ struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
|
||||
*
|
||||
* \param label session label
|
||||
*/
|
||||
Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0)
|
||||
Pd_connection(char const *label = "")
|
||||
: Connection<Pd_session>(session("ram_quota=%u, label=\"%s\"",
|
||||
RAM_QUOTA, label)),
|
||||
Pd_session_client(cap()) { }
|
||||
|
@ -114,35 +114,6 @@ namespace Genode {
|
||||
};
|
||||
|
||||
enum { PARENT_SOCKET_HANDLE = 100 };
|
||||
|
||||
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_ */
|
||||
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* \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-2013 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:
|
||||
|
||||
enum { RAM_QUOTA = 4*1024 };
|
||||
|
||||
/**
|
||||
* 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=36K, 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_ */
|
@ -1,59 +0,0 @@
|
||||
#
|
||||
# \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
|
||||
}
|
||||
|
@ -123,41 +123,6 @@ inline int lx_pollpid()
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
** Chroot handling **
|
||||
*********************/
|
||||
|
||||
inline int lx_chroot(char const *path)
|
||||
{
|
||||
return lx_syscall(SYS_chroot, path);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_chdir(char const *path)
|
||||
{
|
||||
return lx_syscall(SYS_chdir, path);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_getcwd(char *dst, size_t dst_len)
|
||||
{
|
||||
return lx_syscall(SYS_getcwd, dst, dst_len);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_bindmount(char const *source, char const *target)
|
||||
{
|
||||
enum { MS_BIND = 4096 };
|
||||
return lx_syscall(SYS_mount, source, target, 0, MS_BIND, 0);
|
||||
}
|
||||
|
||||
|
||||
inline int lx_umount(char const *target)
|
||||
{
|
||||
return lx_syscall(SYS_umount2, target, 0);
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
** Communication over Unix-domain sockets **
|
||||
********************************************/
|
||||
|
@ -26,166 +26,6 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/***********************************
|
||||
** Utilities for chroot handling **
|
||||
***********************************/
|
||||
|
||||
enum { MAX_PATH_LEN = 256 };
|
||||
|
||||
|
||||
/**
|
||||
* Return true if specified path is an existing directory
|
||||
*/
|
||||
static bool is_directory(char const *path)
|
||||
{
|
||||
struct stat64 s;
|
||||
if (lx_stat(path, &s) != 0)
|
||||
return false;
|
||||
|
||||
if (!(s.st_mode & S_IFDIR))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool is_path_delimiter(char c) { return c == '/'; }
|
||||
|
||||
|
||||
static bool has_trailing_path_delimiter(char const *path)
|
||||
{
|
||||
char last_char = 0;
|
||||
for (; *path; path++)
|
||||
last_char = *path;
|
||||
|
||||
return is_path_delimiter(last_char);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return number of path elements of given path
|
||||
*/
|
||||
static Genode::size_t num_path_elements(char const *path)
|
||||
{
|
||||
Genode::size_t count = 0;
|
||||
|
||||
/*
|
||||
* If path starts with non-slash, the first characters belongs to a path
|
||||
* element.
|
||||
*/
|
||||
if (*path && !is_path_delimiter(*path))
|
||||
count = 1;
|
||||
|
||||
/* count slashes */
|
||||
for (; *path; path++)
|
||||
if (is_path_delimiter(*path))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static bool leading_path_elements(char const *path, unsigned num,
|
||||
char *dst, Genode::size_t dst_len)
|
||||
{
|
||||
/* counter of path delimiters */
|
||||
unsigned count = 0;
|
||||
unsigned i = 0;
|
||||
|
||||
if (is_path_delimiter(path[0]))
|
||||
num++;
|
||||
|
||||
for (; path[i] && (count < num) && (i < dst_len); i++)
|
||||
{
|
||||
if (is_path_delimiter(path[i]))
|
||||
count++;
|
||||
|
||||
if (count == num)
|
||||
break;
|
||||
|
||||
dst[i] = path[i];
|
||||
}
|
||||
|
||||
if (i + 1 < dst_len) {
|
||||
dst[i] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* string is cut, append null termination anyway */
|
||||
dst[dst_len - 1] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void mirror_path_to_chroot(char const *chroot_path, char const *path)
|
||||
{
|
||||
char target_path[MAX_PATH_LEN];
|
||||
Genode::snprintf(target_path, sizeof(target_path), "%s%s",
|
||||
chroot_path, path);
|
||||
|
||||
/*
|
||||
* Create directory hierarchy pointing to the target path except for the
|
||||
* last element. The last element will be bind-mounted to refer to the
|
||||
* original 'path'.
|
||||
*/
|
||||
for (unsigned i = 1; i <= num_path_elements(target_path); i++)
|
||||
{
|
||||
char buf[MAX_PATH_LEN];
|
||||
leading_path_elements(target_path, i, buf, sizeof(buf));
|
||||
|
||||
/* skip existing directories */
|
||||
if (is_directory(buf))
|
||||
continue;
|
||||
|
||||
/* create new directory */
|
||||
lx_mkdir(buf, 0777);
|
||||
}
|
||||
|
||||
lx_umount(target_path);
|
||||
|
||||
int ret = 0;
|
||||
if ((ret = lx_bindmount(path, target_path)))
|
||||
PERR("bind mount failed (errno=%d)", ret);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup content of chroot environment as prerequisite to 'execve' new
|
||||
* processes within the environment. I.e., the current working directory
|
||||
* containing the ROM modules must be mounted at the same location within the
|
||||
* chroot environment.
|
||||
*/
|
||||
static bool setup_chroot_environment(char const *chroot_path)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
static char cwd_path[MAX_PATH_LEN];
|
||||
|
||||
lx_getcwd(cwd_path, sizeof(cwd_path));
|
||||
|
||||
/*
|
||||
* Validate chroot path
|
||||
*/
|
||||
if (!is_directory(chroot_path)) {
|
||||
PERR("chroot path does not point to valid directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (has_trailing_path_delimiter(chroot_path)) {
|
||||
PERR("chroot path has trailing slash");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardlink directories needed for running Genode within the chroot
|
||||
* environment.
|
||||
*/
|
||||
mirror_path_to_chroot(chroot_path, cwd_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
** Utilities **
|
||||
***************/
|
||||
@ -196,23 +36,16 @@ static bool setup_chroot_environment(char const *chroot_path)
|
||||
struct Execve_args
|
||||
{
|
||||
char const *filename;
|
||||
char const *root;
|
||||
char * const *argv;
|
||||
char * const *envp;
|
||||
unsigned int const uid;
|
||||
unsigned int const gid;
|
||||
int const parent_sd;
|
||||
|
||||
Execve_args(char const *filename,
|
||||
char const *root,
|
||||
char * const *argv,
|
||||
char * const *envp,
|
||||
unsigned int uid,
|
||||
unsigned int gid,
|
||||
int parent_sd)
|
||||
:
|
||||
filename(filename), root(root), argv(argv), envp(envp),
|
||||
uid(uid), gid(gid), parent_sd(parent_sd)
|
||||
filename(filename), argv(argv), envp(envp), parent_sd(parent_sd)
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -224,57 +57,6 @@ static int _exec_child(Execve_args *arg)
|
||||
{
|
||||
lx_dup2(arg->parent_sd, PARENT_SOCKET_HANDLE);
|
||||
|
||||
/* change to chroot environment */
|
||||
if (arg->root && arg->root[0]) {
|
||||
char cwd[1024];
|
||||
|
||||
PDBG("arg->root='%s'", arg->root);
|
||||
|
||||
if (setup_chroot_environment(arg->root) == false) {
|
||||
PERR("Could not setup chroot environment");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!lx_getcwd(cwd, sizeof(cwd))) {
|
||||
PERR("Failed to getcwd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("changing root of %s (PID %d) to %s",
|
||||
arg->filename, lx_getpid(), arg->root);
|
||||
|
||||
int ret = lx_chroot(arg->root);
|
||||
if (ret < 0) {
|
||||
PERR("Syscall chroot failed (errno %d)", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lx_chdir(cwd);
|
||||
if (ret < 0) {
|
||||
PERR("chdir to new chroot failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set UID and GID
|
||||
*
|
||||
* We must set the GID prior setting the UID because setting the GID won't
|
||||
* be possible anymore once we set the UID to non-root.
|
||||
*/
|
||||
if (arg->gid) {
|
||||
int const ret = lx_setgid(arg->gid);
|
||||
if (ret)
|
||||
PWRN("Could not set PID %d (%s) to GID %u (error %d)",
|
||||
lx_getpid(), arg->filename, arg->gid, ret);
|
||||
}
|
||||
if (arg->uid) {
|
||||
int const ret = lx_setuid(arg->uid);
|
||||
if (ret)
|
||||
PWRN("Could not set PID %d (%s) to UID %u (error %d)",
|
||||
lx_getpid(), arg->filename, arg->uid, ret);
|
||||
}
|
||||
|
||||
return lx_execve(arg->filename, arg->argv, arg->envp);
|
||||
}
|
||||
|
||||
@ -381,7 +163,7 @@ void Native_pd_component::_start(Dataspace_component &ds)
|
||||
* Argument frame as passed to 'clone'. Because, we can only pass a single
|
||||
* pointer, all arguments are embedded within the 'execve_args' struct.
|
||||
*/
|
||||
Execve_args arg(filename, _root, argv_buf, env, _uid, _gid,
|
||||
Execve_args arg(filename, argv_buf, env,
|
||||
_pd_session._parent.dst().socket);
|
||||
|
||||
_pid = lx_create_process((int (*)(void *))_exec_child,
|
||||
@ -398,37 +180,6 @@ Native_pd_component::Native_pd_component(Pd_session_component &pd_session,
|
||||
_pd_session(pd_session)
|
||||
{
|
||||
_pd_session._thread_ep.manage(this);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* If a UID is specified but no GID, we use the UID as GID. This way, a
|
||||
* configuration error where the UID is defined but the GID is left
|
||||
* undefined won't result in the execution of the new process with the
|
||||
* root user's GID.
|
||||
*/
|
||||
if (_gid == 0)
|
||||
_gid = _uid;
|
||||
|
||||
/*
|
||||
* 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", _pd_session._label.string);
|
||||
|
||||
if (is_chroot) printf(" root: %s\n", _root);
|
||||
if (_uid) printf(" uid: %u\n", _uid);
|
||||
if (_gid) printf(" gid: %u\n", _gid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -237,8 +237,6 @@ namespace Genode {
|
||||
};
|
||||
|
||||
typedef int Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
@ -89,8 +89,6 @@ namespace Genode {
|
||||
|
||||
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
|
||||
typedef Okl4::L4_ThreadId_t Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
@ -73,8 +73,6 @@ namespace Genode {
|
||||
typedef Native_capability_tpl<Cap_dst_policy> Native_capability;
|
||||
|
||||
typedef Pistachio::L4_ThreadId_t Native_connection_state;
|
||||
|
||||
struct Native_pd_args { };
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__NATIVE_TYPES_H_ */
|
||||
|
@ -126,8 +126,6 @@ namespace Genode {
|
||||
};
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
||||
typedef int Native_connection_state;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
|
||||
*
|
||||
* \param label session label
|
||||
*/
|
||||
Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0)
|
||||
Pd_connection(char const *label = "")
|
||||
: Connection<Pd_session>(session("ram_quota=%u, label=\"%s\"",
|
||||
RAM_QUOTA, label)),
|
||||
Pd_session_client(cap())
|
||||
|
@ -111,14 +111,6 @@ struct Genode::Child_policy
|
||||
virtual Ram_session *ref_ram_session() { return env()->ram_session(); }
|
||||
virtual Ram_session_capability ref_ram_cap() const { return env()->ram_session_cap(); }
|
||||
|
||||
/**
|
||||
* Return platform-specific PD-session arguments
|
||||
*
|
||||
* This method is used on Linux to supply additional PD-session
|
||||
* argument to core, i.e., the chroot path, the UID, and the GID.
|
||||
*/
|
||||
virtual Native_pd_args const *pd_args() const { return 0; }
|
||||
|
||||
/**
|
||||
* Respond to the release of resources by the child
|
||||
*
|
||||
|
@ -29,7 +29,7 @@ struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
|
||||
*
|
||||
* \param label session label
|
||||
*/
|
||||
Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0)
|
||||
Pd_connection(char const *label = "")
|
||||
: Connection<Pd_session>(session("ram_quota=%u, label=\"%s\"",
|
||||
RAM_QUOTA, label)),
|
||||
Pd_session_client(cap())
|
||||
|
@ -320,29 +320,6 @@ optional sub node '<exit>' with the attribute 'propagate' set to "yes".
|
||||
The exit value specified by the exiting child is forwarded to init's parent.
|
||||
|
||||
|
||||
Executing children in chroot environments on Linux
|
||||
==================================================
|
||||
|
||||
On the Linux base platform, each process started by init can be assigned to
|
||||
a chroot environment by specifying the new root location as 'root' attribute
|
||||
to the corresponding '<start>' node. Root environments can be nested. The
|
||||
root path of a nested init instance will be appended to the root path of
|
||||
the outer instance.
|
||||
|
||||
When using the chroot mechanism, core will mirror the current working
|
||||
directory within the chroot environment via the a bind mount operation. This
|
||||
step is needed to enable execve to obtain the ELF binary of the new process.
|
||||
|
||||
In order to use the chroot mechanism when starting Genode's core as a non-root
|
||||
user process, the core executable must be equipped with the 'CAP_SYS_ADMIN' and
|
||||
'CAP_SYS_CHROOT' capabilities. 'CAP_SYS_ADMIN' is needed for bind mounting.
|
||||
'CAP_SYS_CHROOT' is needed to perform the 'chroot' syscall:
|
||||
|
||||
! sudo setcap cap_sys_admin,cap_sys_chroot=ep core
|
||||
|
||||
For an example of using chroot, please refer to the 'os/run/chroot.run' script.
|
||||
|
||||
|
||||
Using the configuration concept
|
||||
###############################
|
||||
|
||||
|
@ -414,14 +414,6 @@ class Init::Child : Genode::Child_policy
|
||||
}
|
||||
} _name;
|
||||
|
||||
/**
|
||||
* Platform-specific PD-session arguments
|
||||
*/
|
||||
struct Pd_args : Genode::Native_pd_args
|
||||
{
|
||||
Pd_args(Genode::Xml_node start_node);
|
||||
} _pd_args;
|
||||
|
||||
struct Read_quota
|
||||
{
|
||||
Read_quota(Genode::Xml_node start_node,
|
||||
@ -482,15 +474,14 @@ class Init::Child : Genode::Child_policy
|
||||
|
||||
Resources(Genode::Xml_node start_node, const char *label,
|
||||
long prio_levels,
|
||||
Genode::Affinity::Space const &affinity_space,
|
||||
Genode::Native_pd_args const * pd_args)
|
||||
Genode::Affinity::Space const &affinity_space)
|
||||
:
|
||||
Read_quota(start_node, ram_quota, cpu_quota_pc, constrain_phys),
|
||||
prio_levels_log2(Genode::log2(prio_levels)),
|
||||
priority(read_priority(start_node, prio_levels)),
|
||||
affinity(affinity_space,
|
||||
read_affinity_location(affinity_space, start_node)),
|
||||
pd(label, pd_args),
|
||||
pd(label),
|
||||
ram(label),
|
||||
cpu(label,
|
||||
priority*(Genode::Cpu_session::PRIORITY_LIMIT >> prio_levels_log2),
|
||||
@ -549,7 +540,6 @@ class Init::Child : Genode::Child_policy
|
||||
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_pd_args _pd_args_policy;
|
||||
Init::Child_policy_ram_phys _ram_session_policy;
|
||||
|
||||
public:
|
||||
@ -568,9 +558,8 @@ class Init::Child : Genode::Child_policy
|
||||
_default_route_node(default_route_node),
|
||||
_name_registry(name_registry),
|
||||
_name(start_node, name_registry),
|
||||
_pd_args(start_node),
|
||||
_resources(start_node, _name.unique, prio_levels,
|
||||
affinity_space, &_pd_args),
|
||||
affinity_space),
|
||||
_entrypoint(cap_session, ENTRYPOINT_STACK_SIZE, _name.unique, false, _resources.affinity.location()),
|
||||
_binary_rom(_name.file, _name.file),
|
||||
_binary_rom_ds(_binary_rom.dataspace()),
|
||||
@ -585,7 +574,6 @@ class Init::Child : Genode::Child_policy
|
||||
_config_policy("config", _config.dataspace(), &_entrypoint),
|
||||
_binary_policy("binary", _binary_rom_ds, &_entrypoint),
|
||||
_configfile_policy("config", _config.filename()),
|
||||
_pd_args_policy(&_pd_args),
|
||||
_ram_session_policy(_resources.constrain_phys)
|
||||
{
|
||||
using namespace Genode;
|
||||
@ -743,7 +731,6 @@ class Init::Child : Genode::Child_policy
|
||||
_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);
|
||||
_pd_args_policy. filter_session_args(service, args, args_len);
|
||||
_ram_session_policy.filter_session_args(service, args, args_len);
|
||||
}
|
||||
|
||||
@ -838,8 +825,6 @@ class Init::Child : Genode::Child_policy
|
||||
*/
|
||||
Child_policy::exit(exit_value);
|
||||
}
|
||||
|
||||
Genode::Native_pd_args const *pd_args() const { return &_pd_args; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -25,7 +25,6 @@ namespace Init {
|
||||
|
||||
class Child_policy_ram_phys;
|
||||
class Child_policy_enforce_labeling;
|
||||
class Child_policy_pd_args;
|
||||
class Child_policy_handle_cpu_priorities;
|
||||
class Child_policy_provide_rom_file;
|
||||
class Child_policy_redirect_rom_file;
|
||||
@ -109,29 +108,6 @@ class Init::Child_policy_enforce_labeling
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Policy for handling platform-specific PD-session arguments
|
||||
*
|
||||
* 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 Init::Child_policy_pd_args
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Native_pd_args const *_pd_args;
|
||||
|
||||
public:
|
||||
|
||||
Child_policy_pd_args(Genode::Native_pd_args const *pd_args)
|
||||
: _pd_args(pd_args) { }
|
||||
|
||||
void filter_session_args(const char *session, char *args,
|
||||
Genode::size_t args_len);
|
||||
};
|
||||
|
||||
|
||||
class Init::Child_policy_handle_cpu_priorities
|
||||
{
|
||||
/* priority parameters */
|
||||
|
@ -49,9 +49,8 @@ struct Loader::Session_client : Genode::Rpc_client<Session>
|
||||
void fault_sigh(Signal_context_capability sigh) override {
|
||||
call<Rpc_fault_sigh>(sigh); }
|
||||
|
||||
void start(Name const &binary, Name const &label = "",
|
||||
Native_pd_args const &pd_args = Native_pd_args()) override {
|
||||
call<Rpc_start>(binary, label, pd_args); }
|
||||
void start(Name const &binary, Name const &label = "") override {
|
||||
call<Rpc_start>(binary, label); }
|
||||
|
||||
void view_geometry(Rect rect, Point offset) override {
|
||||
call<Rpc_view_geometry>(rect, offset); }
|
||||
|
@ -31,7 +31,6 @@ namespace Loader {
|
||||
|
||||
using Genode::Dataspace_capability;
|
||||
using Genode::Signal_context_capability;
|
||||
using Genode::Native_pd_args;
|
||||
using Genode::Meta::Type_tuple;
|
||||
|
||||
struct Session;
|
||||
@ -144,8 +143,7 @@ struct Loader::Session : Genode::Session
|
||||
* \throw Rom_module_does_not_exist if the specified binary could
|
||||
* not obtained as ROM module
|
||||
*/
|
||||
virtual void start(Name const &binary, Name const &label = "",
|
||||
Native_pd_args const &pd_args = Native_pd_args()) = 0;
|
||||
virtual void start(Name const &binary, Name const &label = "") = 0;
|
||||
|
||||
/**
|
||||
* Set view geometry and buffer offset
|
||||
@ -174,7 +172,7 @@ struct Loader::Session : Genode::Session
|
||||
GENODE_RPC(Rpc_fault_sigh, void, fault_sigh, Signal_context_capability);
|
||||
GENODE_RPC_THROW(Rpc_start, void, start,
|
||||
GENODE_TYPE_LIST(Rom_module_does_not_exist),
|
||||
Name const &, Name const &, Native_pd_args const &);
|
||||
Name const &, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_view_geometry, void, view_geometry,
|
||||
GENODE_TYPE_LIST(View_does_not_exist),
|
||||
Rect, Point);
|
||||
|
@ -1,3 +0,0 @@
|
||||
SRC_CC = pd_args.cc
|
||||
|
||||
vpath pd_args.cc $(REP_DIR)/src/init
|
@ -1,3 +0,0 @@
|
||||
SRC_CC = pd_args.cc
|
||||
|
||||
vpath pd_args.cc $(REP_DIR)/src/init/spec/linux
|
@ -1,111 +0,0 @@
|
||||
#
|
||||
# \brief Test for using chroot on Linux
|
||||
# \author Norman Feske
|
||||
# \date 2012-04-18
|
||||
#
|
||||
#
|
||||
if {![have_spec linux]} { puts "Run script requires Linux"; exit 0 }
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build { core init drivers/timer test/timer }
|
||||
|
||||
if {[catch { exec which setcap }]} {
|
||||
puts stderr "Error: setcap not available, please install the libcap2-bin package"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Clean up remains of a potentially failed previous run
|
||||
#
|
||||
|
||||
proc chroot_path { } { return "/tmp/chroot-test" }
|
||||
proc chroot_cwd_path { } { return "[chroot_path][pwd]/[run_dir]" }
|
||||
proc chroot_genode_tmp_path { } { return "[chroot_path]/tmp/genode-[exec id -u]" }
|
||||
|
||||
proc cleanup_chroot { } {
|
||||
umount_and_rmdir [chroot_cwd_path]
|
||||
umount_and_rmdir [chroot_path]/lib
|
||||
umount_and_rmdir [chroot_path]/lib64
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="LOG"/>
|
||||
<service name="CAP"/>
|
||||
<service name="RAM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="PD"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="test-timer" root="chroot_path">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
# replace 'chroot_path' marker in config with actual path
|
||||
regsub "chroot_path" $config [chroot_path] config
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Copy boot modules into run directory
|
||||
#
|
||||
# We cannot use the predefined 'build_boot_image' function here because
|
||||
# this would create mere symlinks. However, we want to hardlink the
|
||||
# run directory into the chroot environment. If the directory entries
|
||||
# were symlinks, those would point to nowhere within the chroot.
|
||||
#
|
||||
foreach binary { core init timer test-timer } {
|
||||
exec cp -H bin/$binary [run_dir] }
|
||||
|
||||
#
|
||||
# Grant chroot permission to core
|
||||
#
|
||||
# CAP_SYS_ADMIN is needed for bind mounting genode runtime directories
|
||||
# CAP_SYS_CHROOT is needed to perform the chroot syscall
|
||||
#
|
||||
exec sudo setcap cap_sys_admin,cap_sys_chroot=ep [run_dir]/core
|
||||
|
||||
#
|
||||
# Setup chroot environment
|
||||
#
|
||||
|
||||
# start with fresh directory
|
||||
cleanup_chroot
|
||||
exec mkdir -p [chroot_path]
|
||||
exec mkdir -p [chroot_path]/lib
|
||||
|
||||
# bind mount '/lib' as we need ldso and libc within the chroot environment
|
||||
exec sudo mount --bind /lib [chroot_path]/lib
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
run_genode_until {.*--- timer test finished ---.*} 60
|
||||
|
||||
#
|
||||
# Remove artifacts created while running the test
|
||||
#
|
||||
cleanup_chroot
|
||||
|
||||
# vi: set ft=tcl :
|
@ -1,145 +0,0 @@
|
||||
#
|
||||
# \brief Test for using chroot on Linux
|
||||
# \author Norman Feske
|
||||
# \date 2012-06-06
|
||||
#
|
||||
#
|
||||
if {![have_spec linux]} { puts "Run script requires Linux"; exit 0 }
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build { core init drivers/timer test/timer
|
||||
server/loader test/chroot_loader }
|
||||
|
||||
if {[catch { exec which setcap }]} {
|
||||
puts stderr "Error: setcap not available, please install the libcap2-bin package"
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Clean up remains of a potentially failed previous run
|
||||
#
|
||||
|
||||
proc chroot_path { id } { return "/tmp/chroot-test-$id" }
|
||||
proc chroot_cwd_path { id } { return "[chroot_path $id][pwd]/[run_dir]" }
|
||||
|
||||
proc cleanup_chroot { } {
|
||||
|
||||
foreach id { 1 2 } {
|
||||
umount_and_rmdir [chroot_cwd_path $id]
|
||||
umount_and_rmdir [chroot_path $id]/lib
|
||||
umount_and_rmdir [chroot_path $id]/lib64
|
||||
}
|
||||
}
|
||||
|
||||
cleanup_chroot
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="LOG"/>
|
||||
<service name="CAP"/>
|
||||
<service name="RAM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="RM"/>
|
||||
<service name="PD"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="loader">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Loader"/></provides>
|
||||
</start>
|
||||
<start name="test-chroot_loader">
|
||||
<resource name="RAM" quantum="32M"/>
|
||||
<config>
|
||||
<static_test chroot_path="chroot_path_1" />
|
||||
<dynamic_test chroot_path="chroot_path_2" />
|
||||
</config>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
# replace 'chroot_path' markers in config with actual paths
|
||||
foreach id { 1 2 } {
|
||||
regsub "chroot_path_$id" $config [chroot_path $id] config }
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Copy boot modules into run directory
|
||||
#
|
||||
# We cannot use the predefined 'build_boot_image' function here because
|
||||
# this would create mere symlinks. However, we want to hardlink the
|
||||
# run directory into the chroot environment. If the directory entries
|
||||
# were symlinks, those would point to nowhere within the chroot.
|
||||
#
|
||||
foreach binary { core init timer loader test-chroot_loader test-timer} {
|
||||
exec cp -H bin/$binary [run_dir] }
|
||||
|
||||
#
|
||||
# Grant chroot permission to 'core'
|
||||
#
|
||||
# CAP_SYS_ADMIN is needed for bind mounting genode runtime directories
|
||||
# CAP_SYS_CHROOT is needed to perform the chroot syscall
|
||||
#
|
||||
exec sudo setcap cap_sys_admin,cap_sys_chroot=ep [run_dir]/core
|
||||
|
||||
#
|
||||
# Setup chroot environment
|
||||
#
|
||||
|
||||
# start with fresh directory
|
||||
foreach id { 1 2 } {
|
||||
exec mkdir -p [chroot_path $id]
|
||||
exec mkdir -p [chroot_path $id]/lib
|
||||
exec mkdir -p [chroot_path $id]/lib64
|
||||
|
||||
# bind mount '/lib' as need libc within the chroot environment
|
||||
exec sudo mount --bind /lib [chroot_path $id]/lib
|
||||
catch { exec sudo mount --bind /lib64 [chroot_path $id]/lib64 }
|
||||
}
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
run_genode_until {.*--- chroot-loader test finished ---\s*\n} 60
|
||||
|
||||
#
|
||||
# Validate log output
|
||||
#
|
||||
|
||||
if {[regexp -all -- {--- timer test ---} $output] != 6} {
|
||||
puts stderr "Number of spawned subsystems differs from 6"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if {![regexp -- {init-1 -> test-timer] Done 500 ms period 4 times} $output]} {
|
||||
puts stderr "Long-running timer test has made too little progress"
|
||||
exit 3
|
||||
}
|
||||
|
||||
#
|
||||
# Remove artifacts created while running the test
|
||||
#
|
||||
cleanup_chroot
|
||||
|
||||
puts "Test succeeded"
|
||||
|
||||
# vi: set ft=tcl :
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* \brief Extract 'Native_pd_args' from '<start>' node of the init config
|
||||
* \author Norman Feske
|
||||
* \date 2012-11.21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 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.h>
|
||||
|
||||
|
||||
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)
|
||||
{ }
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* \brief Extract 'Native_pd_args' from '<start>' node of the init config
|
||||
* \author Norman Feske
|
||||
* \date 2012-11.21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 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.h>
|
||||
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
TARGET = init
|
||||
SRC_CC = main.cc
|
||||
LIBS = base init_pd_args config
|
||||
LIBS = base config
|
||||
|
@ -38,8 +38,6 @@ namespace Loader {
|
||||
Label(char const *l) { strncpy(string, l, sizeof(string)); }
|
||||
} _label;
|
||||
|
||||
Native_pd_args _pd_args;
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
|
||||
struct Resources
|
||||
@ -87,7 +85,6 @@ namespace Loader {
|
||||
|
||||
Init::Child_policy_provide_rom_file _binary_policy;
|
||||
Init::Child_policy_enforce_labeling _labeling_policy;
|
||||
Init::Child_policy_pd_args _pd_args_policy;
|
||||
|
||||
Genode::Child _child;
|
||||
|
||||
@ -107,7 +104,6 @@ namespace Loader {
|
||||
|
||||
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,
|
||||
@ -119,7 +115,6 @@ namespace Loader {
|
||||
Signal_context_capability fault_sigh)
|
||||
:
|
||||
_label(label),
|
||||
_pd_args(pd_args),
|
||||
_ep(ep),
|
||||
_resources(_label.string, ram_session_client, ram_quota, fault_sigh),
|
||||
_parent_services(parent_services),
|
||||
@ -130,7 +125,6 @@ namespace Loader {
|
||||
_binary_rom_session(_rom_session(binary_name)),
|
||||
_binary_policy("binary", _binary_rom_session.dataspace(), &_ep),
|
||||
_labeling_policy(_label.string),
|
||||
_pd_args_policy(&_pd_args),
|
||||
_child(_binary_rom_session.dataspace(), _resources.pd.cap(),
|
||||
_resources.ram.cap(), _resources.cpu.cap(),
|
||||
_resources.rm.cap(), &_ep, this)
|
||||
@ -146,13 +140,11 @@ namespace Loader {
|
||||
** Child-policy interface **
|
||||
****************************/
|
||||
|
||||
char const *name() const { return _label.string; }
|
||||
Native_pd_args const *pd_args() const { return &_pd_args; }
|
||||
char const *name() const { return _label.string; }
|
||||
|
||||
void filter_session_args(char const *service, char *args, size_t args_len)
|
||||
{
|
||||
_labeling_policy.filter_session_args(service, args, args_len);
|
||||
_pd_args_policy. filter_session_args(service, args, args_len);
|
||||
}
|
||||
|
||||
Service *resolve_session_request(const char *name,
|
||||
|
@ -363,8 +363,7 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
_fault_sigh = sigh;
|
||||
}
|
||||
|
||||
void start(Name const &binary_name, Name const &label,
|
||||
Genode::Native_pd_args const &pd_args) override
|
||||
void start(Name const &binary_name, Name const &label) override
|
||||
{
|
||||
if (_child) {
|
||||
PWRN("cannot start subsystem twice");
|
||||
@ -378,7 +377,7 @@ class Loader::Session_component : public Rpc_object<Session>
|
||||
try {
|
||||
_child = new (&_md_alloc)
|
||||
Child(binary_name.string(), label.string(),
|
||||
pd_args, _ep, _ram_session_client,
|
||||
_ep, _ram_session_client,
|
||||
ram_quota, _parent_services, _rom_service,
|
||||
_cpu_service, _rm_service, _nitpicker_service,
|
||||
_fault_sigh);
|
||||
|
@ -1,4 +1,4 @@
|
||||
TARGET = loader
|
||||
LIBS = base init_pd_args
|
||||
LIBS = base
|
||||
SRC_CC = main.cc
|
||||
INC_DIR += $(PRG_DIR)
|
||||
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* \brief Test for dynamically starting chrooted subsystems via the loader
|
||||
* \author Norman Feske
|
||||
* \date 2012-06-06
|
||||
*
|
||||
* This test creates two subsystems, each residing in a dedicated chroot
|
||||
* environment, by combining the loader service with the chroot mechanism.
|
||||
* One subsystem runs infinitely. The other subsystem will be repeatedly
|
||||
* started and killed.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/snprintf.h>
|
||||
#include <loader_session/connection.h>
|
||||
#include <os/config.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
|
||||
/*******************************************************
|
||||
** Helpers for obtaining test parameters from config **
|
||||
*******************************************************/
|
||||
|
||||
static char const *chroot_path_from_config(char const *node_name,
|
||||
char *dst, Genode::size_t dst_len)
|
||||
{
|
||||
Genode::config()->xml_node().sub_node(node_name)
|
||||
.attribute("chroot_path").value(dst, dst_len);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
static char const *chroot_path_of_static_test()
|
||||
{
|
||||
static char buf[1024];
|
||||
return chroot_path_from_config("static_test", buf, sizeof(buf));
|
||||
}
|
||||
|
||||
|
||||
static char const *chroot_path_of_dynamic_test()
|
||||
{
|
||||
static char buf[1024];
|
||||
return chroot_path_from_config("dynamic_test", buf, sizeof(buf));
|
||||
}
|
||||
|
||||
|
||||
/**********
|
||||
** Test **
|
||||
**********/
|
||||
|
||||
/**
|
||||
* Return subsystem configuration.
|
||||
*/
|
||||
static char const *subsystem_config()
|
||||
{
|
||||
return "<config verbose=\"yes\">\n"
|
||||
" <parent-provides>\n"
|
||||
" <service name=\"ROM\"/>\n"
|
||||
" <service name=\"LOG\"/>\n"
|
||||
" <service name=\"CAP\"/>\n"
|
||||
" <service name=\"RAM\"/>\n"
|
||||
" <service name=\"CPU\"/>\n"
|
||||
" <service name=\"RM\"/>\n"
|
||||
" <service name=\"PD\"/>\n"
|
||||
" <service name=\"SIGNAL\"/>\n"
|
||||
" <service name=\"Timer\"/>\n"
|
||||
" </parent-provides>\n"
|
||||
" <default-route>\n"
|
||||
" <any-service> <parent/> </any-service>\n"
|
||||
" </default-route>\n"
|
||||
" <start name=\"test-timer\">\n"
|
||||
" <resource name=\"RAM\" quantum=\"1G\"/>\n"
|
||||
" </start>\n"
|
||||
"</config>\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chroot subsystem corresponding to a loader session
|
||||
*/
|
||||
class Chroot_subsystem
|
||||
{
|
||||
private:
|
||||
|
||||
Loader::Connection _loader;
|
||||
|
||||
char _label[32];
|
||||
|
||||
/**
|
||||
* Import data as ROM module into the subsystem-specific ROM service
|
||||
*/
|
||||
void _import_rom_module(char const *name, void const *ptr, Genode::size_t size)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Dataspace_capability ds = _loader.alloc_rom_module(name, size);
|
||||
|
||||
/* fill ROM module with data */
|
||||
char *local_addr = env()->rm_session()->attach(ds);
|
||||
memcpy(local_addr, ptr, size);
|
||||
env()->rm_session()->detach(local_addr);
|
||||
|
||||
_loader.commit_rom_module(name);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Chroot_subsystem(char const *chroot_path, Genode::size_t ram_quota)
|
||||
:
|
||||
_loader(ram_quota)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/*
|
||||
* Import subsystem's configuration into the subsystem's loader
|
||||
* session as a ROM module named "config".
|
||||
*/
|
||||
_import_rom_module("config", subsystem_config(),
|
||||
strlen(subsystem_config()) + 1);
|
||||
|
||||
/*
|
||||
* Name of the Genode binary is start as the root of the new
|
||||
* subsystem.
|
||||
*/
|
||||
char const *binary_name = "init";
|
||||
|
||||
/*
|
||||
* Generate unique label name using a counter
|
||||
*
|
||||
* The label appears in the LOG output of the loaded subsystem.
|
||||
* Technically, it does need to be unique. It is solely used
|
||||
* for validating the test in the run script.
|
||||
*/
|
||||
static int cnt = 0;
|
||||
snprintf(_label, sizeof(_label), "%s-%d", binary_name, ++cnt);
|
||||
|
||||
/* start execution of new subsystem */
|
||||
_loader.start(binary_name,
|
||||
Loader::Session::Name(_label),
|
||||
Native_pd_args(chroot_path, 0, 0));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
Genode::printf("--- chroot-loader test started ---\n");
|
||||
|
||||
static Chroot_subsystem static_subsystem(chroot_path_of_static_test(),
|
||||
2*1024*1024);
|
||||
|
||||
static Timer::Connection timer;
|
||||
|
||||
for (unsigned i = 0; i < 5; i++) {
|
||||
|
||||
PLOG("dynamic test iteration %d", i);
|
||||
|
||||
Chroot_subsystem subsystem(chroot_path_of_dynamic_test(),
|
||||
2*1024*1024);
|
||||
|
||||
/* grant the subsystem one second of life */
|
||||
timer.msleep(1000);
|
||||
|
||||
/*
|
||||
* The local 'dynamic_subsystem' instance will be destructed at the of
|
||||
* the loop body.
|
||||
*/
|
||||
}
|
||||
|
||||
Genode::printf("--- chroot-loader test finished ---\n");
|
||||
return 0;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
TARGET = test-chroot_loader
|
||||
REQUIRES += linux
|
||||
SRC_CC = main.cc
|
||||
LIBS += base config
|
Loading…
Reference in New Issue
Block a user