file_vault: GUI control for encrypted virtual FS's

Warning!

The current version of the file vault is not thought for productive use but
for mere demonstrational purpose! Please refrain from storing sensitive data
with it!

The File Vault component implements a graphical frontend for setting up and
controlling encrypted virtual file systems using the Consistent Block Encrypter
(CBE) for encryption and snapshot management. For more details see
'repos/gems/src/app/file_vault/README'.

Fixes #4032
This commit is contained in:
Martin Stein 2021-02-24 17:06:40 +01:00 committed by Norman Feske
parent 3e375e4315
commit 870c5c7a81
31 changed files with 7607 additions and 0 deletions

View File

@ -0,0 +1 @@
See repos/gems/src/app/file_vault/README.

View File

@ -0,0 +1,19 @@
_/src/init
_/src/libc
_/src/libpng
_/src/zlib
_/src/fs_query
_/src/menu_view
_/src/cbe
_/src/spark
_/src/libsparkcrypto
_/src/vfs_block
_/src/vfs_jitterentropy
_/src/vfs
_/src/openssl
_/src/fs_tool
_/src/fs_utils
_/src/posix
_/src/rump
_/src/sandbox
_/src/file_vault

View File

@ -0,0 +1 @@
2021-04-26-a 405015723954822d3672b119d82e96262fe6763c

View File

@ -0,0 +1,105 @@
<runtime ram="220M" caps="2200" binary="init">
<provides>
<file_system/>
</provides>
<requires>
<file_system label="data" writeable="yes"/>
<file_system label="trust_anchor" writeable="yes"/>
<file_system label="fonts" writeable="no"/>
<rm/>
<gui/>
<timer/>
</requires>
<content>
<rom label="init"/>
<rom label="ld.lib.so"/>
<rom label="libc.lib.so"/>
<rom label="libm.lib.so"/>
<rom label="libpng.lib.so"/>
<rom label="zlib.lib.so"/>
<rom label="fs_query"/>
<rom label="menu_view"/>
<rom label="vfs"/>
<rom label="vfs.lib.so"/>
<rom label="vfs_block"/>
<rom label="vfs_jitterentropy.lib.so"/>
<rom label="vfs_cbe.lib.so"/>
<rom label="vfs_cbe_crypto_aes_cbc.lib.so"/>
<rom label="vfs_cbe_trust_anchor.lib.so"/>
<rom label="cbe_cxx.lib.so"/>
<rom label="cbe_init_cxx.lib.so"/>
<rom label="cbe_init"/>
<rom label="cbe_init_trust_anchor"/>
<rom label="libcrypto.lib.so"/>
<rom label="rump.lib.so"/>
<rom label="vfs_rump.lib.so"/>
<rom label="rump_fs.lib.so"/>
<rom label="sandbox.lib.so"/>
<rom label="libsparkcrypto.lib.so"/>
<rom label="spark.lib.so"/>
<rom label="fs_tool"/>
<rom label="mke2fs"/>
<rom label="resize2fs"/>
<rom label="posix.lib.so"/>
<rom label="file_vault"/>
<rom label="file_vault-sync_to_cbe_vfs_init"/>
<rom label="file_vault-truncate_file"/>
<rom label="menu_view_styles.tar"/>
</content>
<config>
<parent-provides>
<service name="ROM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="Gui"/>
<service name="Timer"/>
<service name="File_system"/>
</parent-provides>
<service name="File_system">
<default-policy>
<child name="file_vault"/>
</default-policy>
</service>
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<vfs>
<dir name="cbe">
<fs label="cbe"/>
</dir>
</vfs>
</config>
<route>
<service name="File_system" label="cbe_trust_anchor_vfs -> storage_dir"> <parent label="trust_anchor"/> </service>
<service name="File_system" label="vfs_block -> "> <parent label="data"/> </service>
<service name="File_system" label="cbe"> <parent label="data"/> </service>
<service name="File_system" label="fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="image_fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="cbe_vfs -> cbe_fs"> <parent label="data"/> </service>
<service name="File_system" label="truncate_file -> cbe"> <parent label="data"/> </service>
<service name="File_system" label="menu_view -> fonts"> <parent label="fonts"/> </service>
<service name="Timer"> <parent/> </service>
<service name="Gui"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config>
</runtime>

View File

@ -0,0 +1,3 @@
SRC_DIR := src/app/file_vault
include $(GENODE_DIR)/repos/base/recipes/src/content.inc

View File

@ -0,0 +1 @@
2021-04-26-a f1ce555a3cd5070870e541aab731d5b8aa7ed30b

View File

@ -0,0 +1,11 @@
base
os
cbe
vfs
report_session
gui_session
input_session
framebuffer_session
posix
libc
sandbox

View File

@ -0,0 +1,300 @@
assert_spec x86_64
build { app/file_vault }
create_boot_directory
append archives "
[depot_user]/src/[base_src]
[depot_user]/pkg/[drivers_interactive_pkg]
[depot_user]/pkg/fonts_fs
[depot_user]/src/init
[depot_user]/src/nitpicker
[depot_user]/src/libc
[depot_user]/src/libpng
[depot_user]/src/zlib
[depot_user]/src/fs_query
[depot_user]/src/menu_view
[depot_user]/src/cbe
[depot_user]/src/spark
[depot_user]/src/libsparkcrypto
[depot_user]/src/vfs_block
[depot_user]/src/vfs_jitterentropy
[depot_user]/src/vfs
[depot_user]/src/openssl
[depot_user]/src/fs_tool
[depot_user]/src/fs_utils
[depot_user]/src/posix
[depot_user]/src/rump
[depot_user]/src/sandbox
"
append_if [have_board linux] archives [depot_user]/src/lx_fs
import_from_depot $archives
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
</parent-provides>
<start name="timer" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="drivers" caps="1500" managing_system="yes">
<resource name="RAM" quantum="64M"/>
<binary name="init"/>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Capture"> <child name="nitpicker"/> </service>
<service name="Event"> <child name="nitpicker"/> </service>
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
<start name="nitpicker" caps="100">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Gui"/> <service name="Capture"/> <service name="Event"/>
</provides>
<config focus="rom">
<capture/> <event/>
<background color="#123456"/>
<domain name="pointer" layer="1" content="client" label="no" origin="pointer" />
<domain name="default" layer="3" content="client" label="no" hover="always" />
<domain name="second" layer="2" xpos="200" ypos="300" content="client" label="no" hover="always" />
<policy label_prefix="pointer" domain="pointer"/>
<policy label_prefix="text_area.2" domain="second"/>
<default-policy domain="default"/>
</config>
<route>
<service name="Timer"> <child name="timer" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="pointer" caps="100">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Gui"> <child name="nitpicker" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
if {[have_board linux]} {
append config {
<start name="data_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> data"
root="/file_vault_dir/data"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> trust_anchor"
root="/file_vault_dir/trust_anchor"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
} else {
append config {
<start name="data_fs" caps="2000">
<binary name="vfs"/>
<resource name="RAM" quantum="200M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="data">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> data" root="/data" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="100">
<binary name="vfs"/>
<resource name="RAM" quantum="5M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="trust_anchor">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> trust_anchor" root="/trust_anchor" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
}
append config {
<start name="fonts_fs" caps="150">
<binary name="vfs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>
<dir name="fonts">
<dir name="title">
<ttf name="regular" path="/Vera.ttf" size_px="18" cache="256K"/>
</dir>
<dir name="text">
<ttf name="regular" path="/Vera.ttf" size_px="14" cache="256K"/>
</dir>
<dir name="annotation">
<ttf name="regular" path="/Vera.ttf" size_px="11" cache="256K"/>
</dir>
<dir name="monospace">
<ttf name="regular" path="/VeraMono.ttf" size_px="14" cache="256K"/>
</dir>
</dir>
</vfs>
<policy label="file_vault -> fonts" root="/fonts" />
</config>
<route>
<service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<config>
<vfs>
<dir name="cbe">
<fs label="cbe"/>
</dir>
</vfs>
</config>
<route>
<service name="File_system" label="cbe_trust_anchor_vfs -> storage_dir"> <child name="trust_anchor_fs" label="file_vault -> trust_anchor"/> </service>
<service name="File_system" label="vfs_block -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="cbe"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="image_fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="cbe_vfs -> cbe_fs"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="truncate_file -> cbe"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="menu_view -> fonts"> <child name="fonts_fs" label="file_vault -> fonts"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Gui"> <child name="nitpicker"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config>
}
install_config $config
set fd [open [run_dir]/genode/focus w]
puts $fd "<focus label=\"file_vault -> \"/>"
close $fd
if {[have_board linux]} {
exec mkdir -p bin/file_vault_dir/data
exec mkdir -p bin/file_vault_dir/trust_anchor
}
append boot_modules {
file_vault
file_vault-sync_to_cbe_vfs_init
file_vault-truncate_file
}
append qemu_args " -display gtk "
append_if [have_board linux] boot_modules file_vault_dir
build_boot_image $boot_modules
run_genode_until forever

View File

@ -0,0 +1,149 @@
The file vault
Martin Stein
Warning
~~~~~~~
The current version of the file vault is not thought for productive use but
for mere demonstrational purpose! Please refrain from storing sensitive data
with it!
Brief
~~~~~
The file vault is a graphical front end for creating and controlling a virtual
encrypted block device using Genodes Consistent Block Encrypter (CBE). The
vault also takes care of creating and managing a Trust Anchor for securing
the block device and formatting the block device with the ext2 file system
which is then provided to clients through Genodes File System service.
Internal structure
~~~~~~~~~~~~~~~~~~
The file vault uses the Sandbox library to spawn child components according to
its needs. It starts, closes or adapts children by re-writing the Sandbox
configuration and listens to the Sandbox state report in order to wait for a
specific child to finish or recognize resource requests.
One child that is always present is an instance of the Menu View component used
by the vault to display its dialog window. The user input however is received
and handled by the vault itself, which, if necessary, then adapts the
graphical output accordingly by re-writing the Menu View configuration. In
order to correlate input events to GUI changes, the vault always keeps track
of the currently hovered GUI element by listening to the hover report of the
Menu View child.
Whenever possible, the vault doesn't access the back end file systems itself
but instead spawns helper components like fs_tool or fs_query. This allows the
vault to remain simple and protected against problems during file system
access.
In general, the implementation of the file vault tries to set the focus on
state-driven decisions. The internal state machine of the vault is divided
into 4 major steps: Setup, Startup, Controls, and Shutdown.
Setup means creating a new Trust Anchor and CBE device as well as formatting
the CBE device. Startup means bringing up an already existing Trust Anchor
and CBE device for use. Controls means showing the main window that allows
manipulating a running CBE device (snapshot management, rekeying, resizing).
Consequently, the Controls step follows after a successful Setup or Startup
step. From the Controls step, the user can trigger a transition to the Shutdown
step. Shutdown means gracefully terminating the use of a running CBE device and
closing the file vault.
Each of these major steps is subdivided into smaller steps. For instance, the
startup consists of requesting the user to input the device passphrase,
unlocking the trust anchor, and starting the CBE device driver. Examining all
minor steps would be to much in the context of this document but the class
_File_vault::Main::State_ in _gems/src/app/file_vault/main.cc_ lists them in
very descriptive way.
When the vault is started, it will first try to read the initial state from
the _/file_vault/state_ file in the back-end file system. There are basically
only two results to this: If the file doesn't exist, the Setup step is startet.
If the file exists, however, it's expected to yield the initial state of the
Startup step indicating that the Setup step has already been done on this back
end during a former run of the file vault.
Once the CBE device is up and running, the file vault enters the Controls
step. This step has several sub-states, for instance the states of rekeying or
creating a snapshot (_File_vault::Main::Rekeying_state_,
_File_vault::Main::Create_snapshot_state_, ...). This is because each of these
operations can be executed independent from each other and in parallel. In
order to execute the operations, the vault accesses the VFS control interface
of the CBE (the CBE VFS plugin) spawned in a dedicated VFS server child.
Like with the back-end file systems, the vault doesn't access the CBE VFS
itself when executing a device operation. It rather spawns an fs_tool instance
to write to the file that starts the operation and an fs_query instance to
watch the file that provides the operation progress.
Configuration
~~~~~~~~~~~~~
The file vault should always have the following configuration:
! <config>
! <vfs>
! <dir name="cbe">
! <fs label="cbe"/>
! </dir>
! </vfs>
! </config>
The vault doesn't consider any further user configuration.
Provided service and session requests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The vault provides a File System service to the ext2 file system once a CBE
device was successfully created and formatted respectively unlocked. Besides
the common Genode environment sessions, the vault requests one File System
session to a fonts file system, one File System session for the back-end
storage of the Trust Anchor, several File System session for the file system
that holds the CBE image file and the persistent vault data, one Gui session,
several timer sessions and an RM session for the Rump kernel it spawns.
Further resources
~~~~~~~~~~~~~~~~~
The _gems/run/file_vault.run_ provides an example on how to manually integrate
the file vault. It can also be used for analyzing and developing the vault -
when targeting native Linux execution even with a persistent storage back-end.
The file vault was also packaged in _gems/recipes/pkg/file_vault_ and can be
deployed in Sculpt via _+ -> depot -> mstein -> Tools -> File Vault_.
Open issues
~~~~~~~~~~~
* The vault should show the percantage of used and free blocks in the CBE trees
in order to enable the user to resize or sync to prevent an out-of-resource
situation.
* Although the Trust Anchor data (private key and superblock hash) can
already be stored on a separate device like an USB stick it still has to be
exposed to the system (device driver, file system driver, file vault)
during operation as the file vault yet can't access "real" Trust-Anchor
interfaces like OpenPGP-Smartcard.
* While some device controls (rekeying, resizing, ...) can be controlled via
the vault only in a serial way (the button only shows up again as soon as
the operation is done) creating and discarding snapshots is controlled in a
fire-and-forget fashion (the button immediately shows up again). This is
because the CBE VFS yet doesn't fully propagate the completely asynchronous
way of handling requests of the CBE.
* The creation of the CBE image file is done yet in serial inside the vault
itself which causes the GUI to hang till the image creation is done.
* Shrinking the client FS or the journaling buffer is not yet supported.
* Creating, discarding, and accessing snapshots isn't supported by now in the
file vault, although the underlying CBE and its VFS plugin have full support.
* The CBE might run into a ressource limit when writing block data or replacing
the block encryption key. This is because it doesn't take care yet whether
its Free Tree has enough free blocks left for finishing an operation. It will
just through an exception in the middle of the operation. This won't affect
the integrity of the vault on disk but might lead to the loss of cached
block data.

View File

@ -0,0 +1,58 @@
/*
* \brief Printable byte capacity
* \author Norman Feske
* \author Martin Stein
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <capacity.h>
/**************
** Capacity_**
**************/
void File_vault::Capacity::print(Output &out) const
{
static constexpr uint64_t KB = 1024;
static constexpr uint64_t MB = 1024 * KB;
static constexpr uint64_t GB = 1024 * MB;
Text const text {
(_value >= GB) ? Text((float)_value/GB, " GiB") :
(_value >= MB) ? Text((float)_value/MB, " MiB") :
(_value >= KB) ? Text((float)_value/KB, " KiB") :
Text(_value, " bytes") };
Genode::print(out, text);
}
File_vault::Capacity::Capacity(uint64_t value)
:
_value { value }
{ }
/*********************
** Capacity_string **
*********************/
File_vault::Capacity_string::Capacity_string(uint64_t value)
:
Capacity::Text { Capacity { value } }
{ }
File_vault::Capacity_string::operator char const *()
{
return Capacity::Text::string();
}

View File

@ -0,0 +1,51 @@
/*
* \brief Printable byte capacity
* \author Norman Feske
* \author Martin Stein
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CAPACITY_H_
#define _CAPACITY_H_
/* local includes */
#include <types.h>
namespace File_vault {
class Capacity;
class Capacity_string;
}
class File_vault::Capacity
{
private:
uint64_t const _value;
public:
using Text = String<64>;
Capacity(uint64_t value);
void print(Output &out) const;
};
class File_vault::Capacity_string : public Capacity::Text
{
public:
Capacity_string(uint64_t value);
operator char const *();
};
#endif /* _CAPACITY_H_ */

View File

@ -0,0 +1,70 @@
/*
* \brief Utility for querying the child-exit state from init's state report
* \author Norman Feske
* \author Martin Stein
* \date 2021-03-05
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CHILD_EXIT_STATE_H_
#define _CHILD_EXIT_STATE_H_
/* Genode includes */
#include <util/xml_node.h>
/* local includes */
#include <types.h>
namespace File_vault {
class Child_exit_state;
}
class File_vault::Child_exit_state
{
public:
typedef String<128> Name;
typedef String<16> Version;
private:
bool _exists = false;
bool _exited = false;
bool _responsive = true;
int _code = 0;
Version _version { };
public:
Child_exit_state(Xml_node init_state, Name const &name)
{
init_state.for_each_sub_node("child", [&] (Xml_node child) {
if (child.attribute_value("name", Name()) == name) {
_exists = true;
_version = child.attribute_value("version", Version());
if (child.has_attribute("exited")) {
_exited = true;
_code = child.attribute_value("exited", 0L);
}
_responsive = (child.attribute_value("skipped_heartbeats", 0U) <= 2);
}
});
}
bool exists() const { return _exists ; }
bool exited() const { return _exited ; }
bool responsive() const { return _responsive ; }
int code() const { return _code ; }
Version version() const { return _version ; }
};
#endif /* _CHILD_EXIT_STATE_H_ */

View File

@ -0,0 +1,147 @@
/*
* \brief Runtime state of a child hosted in the runtime subsystem
* \author Martin Stein
* \author Norman Feske
* \date 2021-02-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CHILD_STATE_H_
#define _CHILD_STATE_H_
/* Genode includes */
#include <util/xml_node.h>
#include <util/noncopyable.h>
#include <util/string.h>
#include <base/registry.h>
#include <base/quota_guard.h>
/* local includes */
#include <types.h>
namespace File_vault {
class Child_state;
}
class File_vault::Child_state : Noncopyable
{
private:
using Start_name = String<128>;
using Binary_name = String<128>;
using Registry_element = Registry<Child_state>::Element;
struct Version
{
unsigned value;
};
Registry_element _registry_element;
Start_name const _start_name;
Binary_name const _binary_name;
Ram_quota const _initial_ram_quota;
Cap_quota const _initial_cap_quota;
Ram_quota _ram_quota { _initial_ram_quota };
Cap_quota _cap_quota { _initial_cap_quota };
Version _version { 0 };
public:
Child_state(Registry<Child_state> &registry,
Start_name const &start_name,
Binary_name const &binary_name,
Ram_quota ram_quota,
Cap_quota cap_quota)
:
_registry_element { registry, *this },
_start_name { start_name },
_binary_name { binary_name },
_initial_ram_quota { ram_quota },
_initial_cap_quota { cap_quota }
{ }
Child_state(Registry<Child_state> &registry,
Start_name const &start_name,
Ram_quota ram_quota,
Cap_quota cap_quota)
:
_registry_element { registry, *this },
_start_name { start_name },
_binary_name { start_name },
_initial_ram_quota { ram_quota },
_initial_cap_quota { cap_quota }
{ }
void trigger_restart()
{
_version.value++;
_ram_quota = _initial_ram_quota;
_cap_quota = _initial_cap_quota;
}
void gen_start_node_version(Xml_generator &xml) const
{
if (_version.value)
xml.attribute("version", _version.value);
}
template <typename GEN_CONTENT>
void gen_start_node(Xml_generator &xml,
GEN_CONTENT const &gen_content) const
{
xml.node("start", [&] () {
xml.attribute("name", _start_name);
xml.attribute("caps", _cap_quota.value);
gen_start_node_version(xml);
if (_start_name != _binary_name) {
xml.node("binary", [&] () {
xml.attribute("name", _binary_name);
});
}
xml.node("resource", [&] () {
xml.attribute("name", "RAM");
Number_of_bytes const bytes(_ram_quota.value);
xml.attribute("quantum", String<64>(bytes)); });
gen_content();
});
}
bool apply_child_state_report(Xml_node const &child)
{
bool result = false;
if (child.attribute_value("name", Start_name()) != _start_name)
return false;
if (child.has_sub_node("ram") &&
child.sub_node("ram").has_attribute("requested"))
{
_ram_quota.value *= 2;
result = true;
}
if (child.has_sub_node("caps") &&
child.sub_node("caps").has_attribute("requested"))
{
_cap_quota.value += 100;
result = true;
}
return result;
}
Ram_quota ram_quota() const { return _ram_quota; }
Start_name start_name() const { return _start_name; }
};
#endif /* _CHILD_STATE_H_ */

View File

@ -0,0 +1,64 @@
/*
* \brief Pointer of const object safe against null dereferencing
* \author Martin Stein
* \date 2021-04-02
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CONST_POINTER_H_
#define _CONST_POINTER_H_
/* local includes */
#include <types.h>
namespace File_vault {
template <typename T>
class Const_pointer;
}
template <typename OBJECT_TYPE>
class File_vault::Const_pointer
{
private:
OBJECT_TYPE const *_object;
public:
struct Invalid : Genode::Exception { };
Const_pointer() : _object { nullptr } { }
Const_pointer(OBJECT_TYPE const &object) : _object { &object } { }
OBJECT_TYPE const &object() const
{
if (_object == nullptr)
throw Invalid();
return *_object;
}
bool valid() const { return _object != nullptr; }
bool operator != (Const_pointer const &other) const
{
if (valid() != other.valid()) {
return true;
}
if (valid()) {
return _object != other._object;
}
return false;
}
};
#endif /* _CONST_POINTER_H_ */

View File

@ -0,0 +1,194 @@
/*
* \brief Dynamically growing array
* \author Norman Feske
* \date 2020-01-12
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DYNAMIC_ARRAY_H_
#define _DYNAMIC_ARRAY_H_
/* Genode includes */
#include <base/allocator.h>
namespace File_vault {
using namespace Genode;
template <typename>
struct Dynamic_array;
}
template <typename ET>
struct File_vault::Dynamic_array
{
public:
struct Index { unsigned value; };
private:
Allocator &_alloc;
using Element = Constructible<ET>;
Element *_array = nullptr;
unsigned _capacity = 0;
unsigned _upper_bound = 0; /* index after last used element */
bool _index_valid(Index at) const
{
return (at.value < _upper_bound) && _array[at.value].constructed();
}
/*
* Noncopyable
*/
Dynamic_array(Dynamic_array const &other);
void operator = (Dynamic_array const &);
public:
/**
* Moving constructor
*/
Dynamic_array(Dynamic_array &other)
:
_alloc(other._alloc), _array(other._array),
_capacity(other._capacity), _upper_bound(other._upper_bound)
{
other._array = nullptr;
other._capacity = 0;
other._upper_bound = 0;
}
Dynamic_array(Allocator &alloc) : _alloc(alloc) { }
~Dynamic_array()
{
if (!_array)
return;
clear();
_alloc.free(_array, _capacity*sizeof(Element));
}
void clear()
{
if (_upper_bound > 0)
for (unsigned i = _upper_bound; i > 0; i--)
destruct(Index{i - 1});
}
template <typename... ARGS>
void insert(Index at, ARGS &&... args)
{
/* grow array if index exceeds current capacity or if it's full */
if (at.value >= _capacity || _upper_bound == _capacity) {
size_t const new_capacity =
2 * max(_capacity, max(8U, at.value));
Element *new_array = nullptr;
try {
(void)_alloc.alloc(sizeof(Element)*new_capacity, &new_array);
for (unsigned i = 0; i < new_capacity; i++)
construct_at<Element>(&new_array[i]);
}
catch (... /* Out_of_ram, Out_of_caps */ ) { throw; }
if (_array) {
for (unsigned i = 0; i < _upper_bound; i++)
new_array[i].construct(*_array[i]);
_alloc.free(_array, sizeof(Element)*_capacity);
}
_array = new_array;
_capacity = new_capacity;
}
/* make room for new element */
if (_upper_bound > 0)
for (unsigned i = _upper_bound; i > at.value; i--)
_array[i].construct(*_array[i - 1]);
_array[at.value].construct(args...);
_upper_bound = max(at.value + 1, _upper_bound + 1);
}
template <typename... ARGS>
void append(ARGS &&... args) { insert(Index{_upper_bound}, args...); }
bool exists(Index at) const { return _index_valid(at); }
Index upper_bound() const { return Index { _upper_bound }; }
void destruct(Index at)
{
if (!_index_valid(at))
return;
_array[at.value].destruct();
if (_upper_bound > 0)
for (unsigned i = at.value; i < _upper_bound - 1; i++)
_array[i].construct(*_array[i + 1]);
_upper_bound--;
_array[_upper_bound].destruct();
}
template <typename FN>
void apply(Index at, FN const &fn)
{
if (_index_valid(at))
fn(*_array[at.value]);
}
template <typename FN>
void apply(Index at, FN const &fn) const
{
if (_index_valid(at))
fn(*_array[at.value]);
}
struct Range { Index at; unsigned length; };
template <typename FN>
void for_each(Range range, FN const &fn) const
{
unsigned const first = range.at.value;
unsigned const limit = min(_upper_bound, first + range.length);
for (unsigned i = first; i < limit; i++)
if (_array[i].constructed())
fn(Index{i}, *_array[i]);
}
template <typename FN>
void for_each(FN const &fn) const
{
for_each(Range { .at = { 0U }, .length = ~0U }, fn);
}
void print(Output &out) const
{
for (unsigned i = 0; i < _upper_bound; i++)
if (_array[i].constructed())
Genode::print(out, *_array[i]);
}
};
#endif /* _DYNAMIC_ARRAY_H_ */

View File

@ -0,0 +1,28 @@
/*
* \brief Interface for handling input events
* \author Norman Feske
* \date 2018-05-02
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _GUI_INPUT_EVENT_HANDLER_H_
#define _GUI_INPUT_EVENT_HANDLER_H_
/* Genode includes */
#include <util/interface.h>
#include <input/event.h>
namespace Gui { struct Input_event_handler; }
struct Gui::Input_event_handler : Genode::Interface
{
virtual void handle_input_event(Input::Event const &) = 0;
};
#endif /* _GUI_INPUT_EVENT_HANDLER_H_ */

View File

@ -0,0 +1,122 @@
/*
* \brief GUI wrapper for monitoring the user input of GUI components
* \author Norman Feske
* \date 2020-01-12
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _GUI_SESSION_COMPONENT_H_
#define _GUI_SESSION_COMPONENT_H_
/* Genode includes */
#include <input/component.h>
#include <base/session_object.h>
#include <gui_session/connection.h>
/* local includes */
#include <gui_input_event_handler.h>
namespace Gui {
using namespace Genode;
struct Session_component;
}
struct Gui::Session_component : Session_object<Gui::Session>
{
Env &_env;
Input_event_handler &_event_handler;
Gui::Connection _connection;
Input::Session_component _input_component { _env, _env.ram() };
Signal_handler<Session_component> _input_handler {
_env.ep(), *this, &Session_component::_handle_input };
void _handle_input()
{
_connection.input()->for_each_event([&] (Input::Event ev) {
/* handle event locally within the sculpt manager */
_event_handler.handle_input_event(ev);
_input_component.submit(ev);
});
}
template <typename... ARGS>
Session_component(Env &env, Input_event_handler &event_handler, ARGS &&... args)
:
Session_object(args...),
_env(env), _event_handler(event_handler),
_connection(env, _label.string())
{
_connection.input()->sigh(_input_handler);
_env.ep().manage(_input_component);
_input_component.event_queue().enabled(true);
}
~Session_component() { _env.ep().dissolve(_input_component); }
void upgrade(Session::Resources const &resources)
{
_connection.upgrade(resources);
}
Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); }
Input::Session_capability input_session() override {
return _input_component.cap(); }
View_handle create_view(View_handle parent) override {
return _connection.create_view(parent); }
void destroy_view(View_handle view) override {
_connection.destroy_view(view); }
View_handle view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override {
return _connection.view_capability(view); }
void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); }
Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); }
void execute() override {
_connection.execute(); }
Framebuffer::Mode mode() override {
return _connection.mode(); }
void mode_sigh(Signal_context_capability sigh) override {
_connection.mode_sigh(sigh); }
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Client::buffer(mode, use_alpha);
}
void focus(Capability<Gui::Session> session) override {
_connection.focus(session); }
};
#endif /* _GUI_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,261 @@
/*
* \brief Text buffer for a passphrase
* \author Norman Feske
* \author Martin Stein
* \date 2021-03-02
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INPUT_H_
#define _INPUT_H_
/* Genode includes */
#include <base/output.h>
#include <util/utf8.h>
#include <base/buffered_output.h>
/* local includes */
#include <types.h>
namespace File_vault {
class Input_single_line;
class Input_passphrase;
class Input_number_of_bytes;
class Input_number_of_blocks;
}
class File_vault::Input_single_line
{
public:
enum { MAX_LENGTH = 64 };
protected:
Codepoint _characters[MAX_LENGTH] { };
unsigned _length = 0;
void _print_characters(Output &out) const
{
/*
* FIXME This was copied from gems/src/server/terminal/main.cc
*/
struct Utf8 { char b0, b1, b2, b3, b4; };
auto utf8_from_codepoint = [] (unsigned c) {
/* extract 'n' bits 'at' bit position of value 'c' */
auto bits = [c] (unsigned at, unsigned n) {
return (c >> at) & ((1 << n) - 1); };
return (c < 2<<7) ? Utf8 { char(bits( 0, 7)), 0, 0, 0, 0 }
: (c < 2<<11) ? Utf8 { char(bits( 6, 5) | 0xc0),
char(bits( 0, 6) | 0x80), 0, 0, 0 }
: (c < 2<<16) ? Utf8 { char(bits(12, 4) | 0xe0),
char(bits( 6, 6) | 0x80),
char(bits( 0, 6) | 0x80), 0, 0 }
: (c < 2<<21) ? Utf8 { char(bits(18, 3) | 0xf0),
char(bits(12, 6) | 0x80),
char(bits( 6, 6) | 0x80),
char(bits( 0, 6) | 0x80), 0 }
: Utf8 { };
};
for (unsigned i = 0; i < _length; i++) {
Utf8 const utf8 = utf8_from_codepoint(_characters[i].value);
auto _print = [&] (char c) {
if (c)
Genode::print(out, Char(c)); };
_print(utf8.b0); _print(utf8.b1); _print(utf8.b2);
_print(utf8.b3); _print(utf8.b4);
}
}
public:
void append_character(Codepoint c)
{
if (_length < MAX_LENGTH) {
_characters[_length] = c;
_length++;
}
}
void remove_last_character()
{
if (_length > 0) {
_length--;
_characters[_length].value = 0;
}
}
bool equals(Input_single_line const &other) const
{
if (other._length != _length) {
return false;
}
if (memcmp(other._characters, _characters, _length) != 0) {
return false;
}
return true;
}
unsigned length() const { return _length; }
};
class File_vault::Input_passphrase : public Input_single_line
{
private:
bool _hide { true };
void _print_bullets(Output &out) const
{
char const bullet_utf8[4] {
(char)0xe2, (char)0x80, (char)0xa2, 0 };
for (unsigned i = 0; i < _length; i++)
Genode::print(out, bullet_utf8);
}
public:
bool suitable() const
{
return _length >= 8;
}
char const *not_suitable_text() const
{
return "Must have at least 8 characters!";
}
void print(Output &out) const
{
if (_hide) {
_print_bullets(out);
} else {
_print_characters(out);
}
}
void hide(bool value)
{
_hide = value;
}
bool hide() const
{
return _hide;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_printable {
code.value >= 0x20 && code.value < 0xf000 };
return is_printable;
}
String<MAX_LENGTH * 3> plaintext() const
{
String<MAX_LENGTH * 3> result { };
auto write = [&] (char const *str)
{
result = Cstring(str, strlen(str));
};
Buffered_output<MAX_LENGTH * 3, decltype(write)> output(write);
_print_characters(output);
return result;
}
};
class File_vault::Input_number_of_bytes : public Input_single_line
{
public:
void print(Output &out) const
{
_print_characters(out);
}
size_t value() const
{
String<32> const str { *this };
Number_of_bytes result { 0 };
ascii_to(str.string(), result);
return result;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_number {
code.value >= 48 && code.value <= 57 };
bool const is_unit_prefix {
code.value == 71 || code.value == 75 || code.value == 77 };
return is_number || is_unit_prefix;
}
};
class File_vault::Input_number_of_blocks : public Input_single_line
{
public:
void print(Output &out) const
{
_print_characters(out);
}
unsigned long to_unsigned_long() const
{
String<32> const str { *this };
unsigned long result { 0 };
ascii_to(str.string(), result);
return result;
}
bool is_nr_greater_than_zero() const
{
return (size_t)to_unsigned_long() > 0;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_number {
code.value >= 48 && code.value <= 57 };
return is_number;
}
};
#endif /* _INPUT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,389 @@
/*
* \brief Local utilities for the menu view dialog
* \author Martin Stein
* \date 2021-02-24
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <menu_view_dialog.h>
#include <capacity.h>
using namespace File_vault;
void File_vault::gen_normal_font_attribute(Xml_generator &xml)
{
xml.attribute("font", "text/regular");
}
void File_vault::gen_frame_title(Xml_generator &xml,
char const *name,
unsigned long min_width)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.attribute("north", "yes");
xml.node("label", [&] () {
xml.attribute("text", "" );
xml.attribute("min_ex", min_width);
});
});
}
void File_vault::gen_info_frame(Xml_generator &xml,
char const *name,
char const *info,
unsigned long min_width)
{
gen_main_frame(xml, name, min_width, [&] (Xml_generator &xml) {
gen_centered_info_line(xml, "info", info);
gen_info_line(xml, "pad_1", "");
});
}
void File_vault::gen_action_button_at_bottom(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("east", "yes");
xml.attribute("west", "yes");
xml.attribute("south", "yes");
xml.node("button", [&] () {
if (hovered) {
xml.attribute("hovered", "yes");
}
if (selected) {
xml.attribute("selected", "yes");
}
xml.node("float", [&] () {
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", label);
});
});
});
});
}
void File_vault::gen_action_button_at_bottom(Xml_generator &xml,
char const *label,
bool hovered,
bool selected)
{
gen_action_button_at_bottom(xml, label, label, hovered, selected);
}
void File_vault::gen_action_button(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected,
size_t min_ex)
{
xml.node("button", [&] () {
xml.attribute("name", name);
if (hovered) {
xml.attribute("hovered", "yes");
}
if (selected) {
xml.attribute("selected", "yes");
}
xml.node("label", [&] () {
if (min_ex != 0) {
xml.attribute("min_ex", min_ex);
}
xml.attribute("text", label);
});
});
}
void File_vault::gen_text_input(Xml_generator &xml,
char const *name,
String<256> const &text,
bool selected)
{
String<256> const padded_text { " ", text };
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", padded_text);
if (selected) {
xml.node("cursor", [&] () {
xml.attribute("at", padded_text.length() - 1 );
});
}
});
});
});
}
void
File_vault::
gen_input_passphrase(Xml_generator &xml,
size_t max_width,
Input_passphrase const &passphrase,
bool input_selected,
bool show_hide_button_hovered,
bool show_hide_button_selected)
{
char const *show_hide_button_label;
size_t cursor_at;
if (passphrase.hide()) {
show_hide_button_label = "Show";
cursor_at = passphrase.length() + 1;
} else {
show_hide_button_label = "Hide";
cursor_at = passphrase.length() + 1;
}
xml.node("float", [&] () {
xml.attribute("name", "Passphrase Label");
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", " Passphrase: ");
});
});
xml.node("hbox", [&] () {
String<256> const padded_text { " ", passphrase, " " };
xml.node("frame", [&] () {
xml.attribute("name", "Passphrase");
xml.node("float", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
xml.attribute("min_ex", max_width - 11);
gen_normal_font_attribute(xml);
xml.attribute("text", padded_text);
if (input_selected) {
xml.node("cursor", [&] () {
xml.attribute("at", cursor_at );
});
}
});
});
});
xml.node("float", [&] () {
xml.attribute("name", "1");
xml.attribute("east", "yes");
gen_action_button(
xml, "Show Hide", show_hide_button_label,
show_hide_button_hovered, show_hide_button_selected, 5);
});
});
}
void File_vault::gen_titled_text_input(Xml_generator &xml,
char const *name,
char const *title,
String<256> const &text,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", String<64> { name, "_label" });
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<64> { " ", title, ": " });
});
});
gen_text_input(xml, name, text, selected);
}
void File_vault::gen_empty_line(Xml_generator &xml,
char const *name,
size_t min_width)
{
xml.node("label", [&] () {
xml.attribute("name", name);
xml.attribute("min_ex", min_width);
xml.attribute("text", "");
});
}
void File_vault::gen_info_line(Xml_generator &xml,
char const *name,
char const *text)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<256> { " ", text, " "});
});
});
}
void File_vault::gen_centered_info_line(Xml_generator &xml,
char const *name,
char const *text)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<256> { " ", text, " "});
});
});
}
void File_vault::gen_multiple_choice_entry(Xml_generator &xml,
char const *name,
char const *text,
bool hovered,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
xml.node("button", [&] () {
if (selected) {
xml.attribute("selected", "yes");
}
if (hovered) {
xml.attribute("hovered", "yes");
}
xml.attribute("style", "radio");
xml.node("hbox", [&] () { });
});
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<64> { " ", text });
});
});
});
}
void File_vault::gen_menu_title(Xml_generator &xml,
char const *name,
char const *label,
char const *label_annex,
bool hovered,
bool selected)
{
xml.node("hbox", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("name", "0");
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
xml.node("button", [&] () {
if (selected) {
xml.attribute("style", "back");
xml.attribute("selected", "yes");
} else {
xml.attribute("style", "radio");
}
if (hovered) {
xml.attribute("hovered", "yes");
}
xml.attribute("hovered", "no");
xml.node("hbox", [&] () { });
});
xml.node("label", [&] () {
if (selected) {
xml.attribute("font", "title/regular");
}
xml.attribute("text", String<64> { " ", label });
});
});
});
xml.node("float", [&] () {
xml.attribute("name", "2");
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("font", "title/regular");
xml.attribute(
"text", label_annex);
});
});
});
}
void File_vault::gen_closed_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered)
{
xml.node("vbox", [&] () {
xml.attribute("name", label);
gen_menu_title(xml, "Enter", label, label_annex, hovered, false);
});
}
void File_vault::gen_global_controls(Xml_generator &xml,
size_t min_width,
size_t cbe_image_size,
size_t client_fs_size,
size_t nr_of_clients,
bool shut_down_button_hovered,
bool shut_down_button_selected)
{
gen_empty_line(xml, "Status 0", min_width);
gen_centered_info_line(xml, "Status 1",
String<256> {
" Image: ",
Capacity_string { cbe_image_size },
", Client FS: ",
Capacity_string { client_fs_size },
", Clients: ",
nr_of_clients
}.string()
);
gen_empty_line(xml, "Status 3", 0);
xml.node("hbox", [&] () {
gen_action_button(
xml, "Shut down", "Shut down",
shut_down_button_hovered,
shut_down_button_selected);
});
}

View File

@ -0,0 +1,181 @@
/*
* \brief Local utilities for the menu view dialog
* \author Martin Stein
* \date 2021-02-24
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _MENU_VIEW_DIALOG_H_
#define _MENU_VIEW_DIALOG_H_
/* Genode includes */
#include <util/xml_generator.h>
/* local includes */
#include <types.h>
#include <input.h>
namespace File_vault {
void gen_normal_font_attribute(Xml_generator &xml);
void gen_frame_title(Xml_generator &xml,
char const *name,
unsigned long min_width);
template <typename GEN_FRAME_CONTENT>
void gen_main_frame(Xml_generator &xml,
char const *name,
unsigned long min_width,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("vbox", [&] () {
gen_frame_title(xml, "title", min_width);
gen_frame_content(xml);
});
});
}
template <typename GEN_FRAME_CONTENT>
void gen_controls_frame(Xml_generator &xml,
char const *name,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("vbox", [&] () {
gen_frame_content(xml);
});
});
}
template <typename GEN_FRAME_CONTENT>
void gen_untitled_frame(Xml_generator &xml,
char const *name,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("name", "xxx");
xml.attribute("east", "yes");
xml.attribute("west", "yes");
xml.attribute("north", "yes");
xml.node("vbox", [&] () {
gen_frame_content(xml);
});
});
});
}
void gen_info_frame(Xml_generator &xml,
char const *name,
char const *info,
unsigned long min_width);
void gen_action_button_at_bottom(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected);
void gen_action_button_at_bottom(Xml_generator &xml,
char const *label,
bool hovered,
bool selected);
void gen_text_input(Xml_generator &xml,
char const *name,
String<256> const &text,
bool selected);
void gen_titled_text_input(Xml_generator &xml,
char const *name,
char const *title,
String<256> const &text,
bool selected);
void gen_info_line(Xml_generator &xml,
char const *name,
char const *text);
void gen_centered_info_line(Xml_generator &xml,
char const *name,
char const *text);
void gen_empty_line(Xml_generator &xml,
char const *name,
size_t min_width);
void gen_multiple_choice_entry(Xml_generator &xml,
char const *name,
char const *text,
bool hovered,
bool selected);
void gen_menu_title(Xml_generator &xml,
char const *name,
char const *label,
char const *label_annex,
bool hovered,
bool selected);
void gen_closed_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered);
template <typename GEN_CONTENT>
void gen_opened_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered,
GEN_CONTENT const &gen_content)
{
xml.node("vbox", [&] () {
xml.attribute("name", label);
gen_menu_title(xml, "Leave", label, label_annex, hovered, true);
gen_content(xml);
});
}
void gen_input_passphrase(Xml_generator &xml,
size_t max_width,
Input_passphrase const &passphrase,
bool input_selected,
bool show_hide_button_hovered,
bool show_hide_button_selected);
void gen_action_button(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected,
size_t min_ex = 0);
void gen_global_controls(Xml_generator &xml,
size_t min_width,
size_t cbe_image_size,
size_t client_fs_size,
size_t nr_of_clients,
bool shut_down_button_hovered,
bool shut_down_button_selected);
}
#endif /* _MENU_VIEW_DIALOG_H_ */

View File

@ -0,0 +1,91 @@
/*
* \brief Report session provided by the CBE manager
* \author Martin Stein
* \author Norman Feske
* \date 2021-02-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _REPORT_SESSION_COMPONENT_H_
#define _REPORT_SESSION_COMPONENT_H_
/* Genode includes */
#include <base/attached_ram_dataspace.h>
#include <base/session_object.h>
#include <report_session/report_session.h>
namespace Report {
using namespace Genode;
class Session_component;
}
class Report::Session_component : public Session_object<Report::Session>
{
public:
struct Handler_base : Interface, Genode::Noncopyable
{
virtual void handle_report(char const *, size_t) = 0;
};
template <typename T>
struct Xml_handler : Handler_base
{
T &_obj;
void (T::*_member) (Xml_node const &);
Xml_handler(T &obj, void (T::*member)(Xml_node const &))
: _obj(obj), _member(member) { }
void handle_report(char const *start, size_t length) override
{
(_obj.*_member)(Xml_node(start, length));
}
};
private:
Attached_ram_dataspace _ds;
Handler_base &_handler;
/*******************************
** Report::Session interface **
*******************************/
Dataspace_capability dataspace() override { return _ds.cap(); }
void submit(size_t length) override
{
_handler.handle_report(_ds.local_addr<char const>(),
min(_ds.size(), length));
}
void response_sigh(Signal_context_capability) override { }
size_t obtain_response() override { return 0; }
public:
template <typename... ARGS>
Session_component(Env &env, Handler_base &handler,
Entrypoint &ep, Resources const &resources,
ARGS &&... args)
:
Session_object(ep, resources, args...),
_ds(env.ram(), env.rm(), resources.ram_quota.value),
_handler(handler)
{ }
};
#endif /* _REPORT_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,997 @@
/*
* \brief Local utilities for the sandbox API
* \author Martin Stein
* \date 2021-02-24
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SANDBOX_H_
#define _SANDBOX_H_
/* Genode includes */
#include <util/string.h>
#include <sandbox/sandbox.h>
/* local includes */
#include <input.h>
namespace File_vault {
template <typename ARG>
void gen_arg(Xml_generator &xml, ARG const &arg)
{
xml.node("arg", [&] () { xml.attribute("value", arg); });
}
template <typename FN>
static inline void gen_named_node(Xml_generator &xml,
char const *type, char const *name, FN const &fn)
{
xml.node(type, [&] () {
xml.attribute("name", name);
fn();
});
}
static inline void gen_common_start_content(Xml_generator &xml,
char const *name,
Cap_quota const caps,
Ram_quota const ram)
{
xml.attribute("name", name);
xml.attribute("caps", caps.value);
gen_named_node(xml, "resource", "RAM", [&] () {
xml.attribute("quantum", String<64>(Number_of_bytes(ram.value))); });
}
void route_to_child_service(Genode::Xml_generator &xml,
char const *child_name,
char const *service_name,
char const *service_label = "")
{
xml.node("service", [&] () {
xml.attribute("name", service_name);
if (Genode::strcmp(service_label, "")) {
xml.attribute("label", service_label);
}
xml.attribute("name", service_name);
xml.node("child", [&] () {
xml.attribute("name", child_name);
});
});
};
void route_to_parent_service(Genode::Xml_generator &xml,
char const *service_name,
char const *src_label = "",
char const *dst_label = "")
{
xml.node("service", [&] () {
xml.attribute("name", service_name);
if (Genode::strcmp(src_label, "")) {
xml.attribute("label", src_label);
}
xml.node("parent", [&] () {
if (Genode::strcmp(dst_label, "")) {
xml.attribute("label", dst_label);
}
});
});
};
void route_to_local_service(Genode::Xml_generator &xml,
char const *service_name,
char const *service_label = "")
{
xml.node("service", [&] () {
xml.attribute("name", service_name);
if (Genode::strcmp(service_label, "")) {
xml.attribute("label", service_label);
}
xml.node("local", [&] () { });
});
};
void service_node(Genode::Xml_generator &xml,
char const *service_name)
{
xml.node("service", [&] () {
xml.attribute("name", service_name);
});
};
void gen_provides_service(Xml_generator &xml,
char const *service_name)
{
xml.node("provides", [&] () {
xml.node("service", [&] () {
xml.attribute("name", service_name);
});
});
}
void gen_parent_routes_for_pd_rom_cpu_log(Xml_generator &xml)
{
route_to_parent_service(xml, "PD");
route_to_parent_service(xml, "ROM");
route_to_parent_service(xml, "CPU");
route_to_parent_service(xml, "LOG");
}
void gen_parent_provides_and_report_nodes(Xml_generator &xml)
{
xml.attribute("verbose", "no");
xml.node("report", [&] () {
xml.attribute("provided", "yes");
xml.attribute("child_ram", "yes");
xml.attribute("child_caps", "yes");
xml.attribute("delay_ms", 500);
});
xml.node("parent-provides", [&] () {
service_node(xml, "ROM");
service_node(xml, "CPU");
service_node(xml, "PD");
service_node(xml, "LOG");
service_node(xml, "RM");
service_node(xml, "File_system");
service_node(xml, "Gui");
service_node(xml, "Timer");
service_node(xml, "Report");
});
}
void gen_menu_view_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("xpos", "100");
xml.attribute("ypos", "50");
xml.node("report", [&] () {
xml.attribute("hover", "yes"); });
xml.node("libc", [&] () {
xml.attribute("stderr", "/dev/log"); });
xml.node("vfs", [&] () {
xml.node("tar", [&] () {
xml.attribute("name", "menu_view_styles.tar"); });
xml.node("dir", [&] () {
xml.attribute("name", "dev");
xml.node("log", [&] () { });
});
xml.node("dir", [&] () {
xml.attribute("name", "fonts");
xml.node("fs", [&] () {
xml.attribute("label", "fonts");
});
});
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "ROM", "dialog");
route_to_local_service(xml, "Report", "hover");
route_to_local_service(xml, "Gui");
route_to_parent_service(xml, "File_system", "fonts");
route_to_parent_service(xml, "Timer");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_mke2fs_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("libc", [&] () {
xml.attribute("stdout", "/dev/log");
xml.attribute("stderr", "/dev/log");
xml.attribute("stdin", "/dev/null");
xml.attribute("rtc", "/dev/rtc");
});
xml.node("vfs", [&] () {
gen_named_node(xml, "dir", "dev", [&] () {
gen_named_node(xml, "block", "block", [&] () {
xml.attribute("label", "default");
xml.attribute("block_buffer_count", 128);
});
gen_named_node(xml, "inline", "rtc", [&] () {
xml.append("2018-01-01 00:01");
});
xml.node("null", [&] () {});
xml.node("log", [&] () {});
});
});
gen_arg(xml, "mkfs.ext2");
gen_arg(xml, "-F");
gen_arg(xml, "/dev/block");
});
xml.node("route", [&] () {
route_to_child_service(xml, "vfs_block", "Block");
route_to_parent_service(xml, "Timer");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_resize2fs_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("libc", [&] () {
xml.attribute("stdout", "/dev/log");
xml.attribute("stderr", "/dev/log");
xml.attribute("stdin", "/dev/null");
xml.attribute("rtc", "/dev/rtc");
});
xml.node("vfs", [&] () {
gen_named_node(xml, "dir", "dev", [&] () {
gen_named_node(xml, "block", "block", [&] () {
xml.attribute("label", "default");
xml.attribute("block_buffer_count", 128);
});
gen_named_node(xml, "inline", "rtc", [&] () {
xml.append("2018-01-01 00:01");
});
xml.node("null", [&] () {});
xml.node("log", [&] () {});
});
});
gen_arg(xml, "resize2fs");
gen_arg(xml, "-f");
gen_arg(xml, "-p");
gen_arg(xml, "/dev/block");
});
xml.node("route", [&] () {
route_to_child_service(xml, "vfs_block", "Block");
route_to_parent_service(xml, "Timer");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_vfs_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
gen_provides_service(xml, "File_system");
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("buffer_size", "1M");
xml.attribute("label", "cbe_fs");
});
xml.node("cbe_crypto_aes_cbc", [&] () {
xml.attribute("name", "crypto");
});
xml.node("dir", [&] () {
xml.attribute("name", "trust_anchor");
xml.node("fs", [&] () {
xml.attribute("buffer_size", "1M");
xml.attribute("label", "trust_anchor");
});
});
xml.node("dir", [&] () {
xml.attribute("name", "dev");
xml.node("cbe", [&] () {
xml.attribute("name", "cbe");
xml.attribute("verbose", "no");
xml.attribute("debug", "no");
xml.attribute("block", "/cbe.img");
xml.attribute("crypto", "/crypto");
xml.attribute("trust_anchor", "/trust_anchor");
});
});
});
xml.node("policy", [&] () {
xml.attribute("label", "resizing_fs_tool -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "rekeying_fs_tool -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "shut_down_fs_tool -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "create_snap_fs_tool -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "discard_snap_fs_tool -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "snapshots_fs_query -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "resizing_fs_query -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "rekeying_fs_query -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "shut_down_fs_query -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "vfs_block -> ");
xml.attribute("root", "/dev/cbe/current");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "client_fs_fs_query -> ");
xml.attribute("root", "/dev/cbe/current");
xml.attribute("writeable", "no");
});
xml.node("policy", [&] () {
xml.attribute("label", "sync_to_cbe_vfs_init -> ");
xml.attribute("root", "/dev");
xml.attribute("writeable", "no");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor");
route_to_parent_service(xml, "File_system", "cbe_fs");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_trust_anchor_vfs_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
gen_provides_service(xml, "File_system");
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "storage_dir");
xml.node("fs", [&] () {
xml.attribute("buffer_size", "1M");
xml.attribute("label", "storage_dir");
});
});
xml.node("dir", [&] () {
xml.attribute("name", "dev");
xml.node("cbe_trust_anchor", [&] () {
xml.attribute("name", "cbe_trust_anchor");
xml.attribute("storage_dir", "/storage_dir");
});
xml.node("jitterentropy", [&] () {
xml.attribute("name", "jitterentropy");
});
});
});
xml.node("policy", [&] () {
xml.attribute("label", "cbe_init_trust_anchor -> trust_anchor");
xml.attribute("root", "/dev/cbe_trust_anchor");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "cbe_init -> trust_anchor");
xml.attribute("root", "/dev/cbe_trust_anchor");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "cbe_vfs -> trust_anchor");
xml.attribute("root", "/dev/cbe_trust_anchor");
xml.attribute("writeable", "yes");
});
});
xml.node("route", [&] () {
route_to_parent_service(xml, "File_system", "storage_dir");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_rump_vfs_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
gen_provides_service(xml, "File_system");
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("rump", [&] () {
xml.attribute("fs", "ext2fs");
xml.attribute("ram", "10M");
});
});
xml.node("default-policy", [&] () {
xml.attribute("root", "/");
xml.attribute("writeable", "yes");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "vfs_block", "Block");
route_to_parent_service(xml, "Timer");
route_to_parent_service(xml, "RM");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_truncate_file_start_node(Xml_generator &xml,
Child_state const &child,
char const *path,
size_t size)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("size", size);
xml.attribute("path", path);
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("label", "cbe");
});
});
});
});
xml.node("route", [&] () {
route_to_parent_service(xml, "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_sync_to_cbe_vfs_init_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("ld_verbose", "no");
xml.node("libc", [&] () {
xml.attribute("stdin", "/dev/log");
xml.attribute("stdout", "/dev/log");
xml.attribute("stderr", "/dev/log");
});
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "dev");
xml.node("log", [&] () { });
});
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_vfs_block_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
gen_provides_service(xml, "Block");
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("buffer_size", "1M");
});
});
xml.node("policy", [&] () {
xml.attribute("label", "mke2fs -> default");
xml.attribute("block_size", "512");
xml.attribute("file", "/data");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "resize2fs -> default");
xml.attribute("block_size", "512");
xml.attribute("file", "/data");
xml.attribute("writeable", "yes");
});
xml.node("policy", [&] () {
xml.attribute("label", "rump_vfs -> ");
xml.attribute("block_size", "512");
xml.attribute("file", "/data");
xml.attribute("writeable", "yes");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_image_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "no");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/");
xml.attribute("content", "no");
xml.attribute("size", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_parent_service(xml, "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_client_fs_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "no");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/");
xml.attribute("content", "no");
xml.attribute("size", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/file_vault");
xml.attribute("content", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_parent_service(xml, "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_init_trust_anchor_start_node(Xml_generator &xml,
Child_state const &child,
Input_passphrase const &passphrase)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("passphrase", passphrase.plaintext().string());
xml.attribute("trust_anchor_dir", "/trust_anchor");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "trust_anchor");
xml.node("fs", [&] () {
xml.attribute("label", "trust_anchor");
});
});
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_image_vfs_block_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
gen_provides_service(xml, "Block");
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("buffer_size", "1M");
});
});
xml.node("policy", [&] () {
xml.attribute("label", "cbe_init -> ");
xml.attribute("block_size", "512");
xml.attribute("file", "/cbe.img");
xml.attribute("writeable", "yes");
});
});
xml.node("route", [&] () {
route_to_parent_service(xml, "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_cbe_init_start_node(Xml_generator &xml,
Child_state const &child,
Tree_geometry const &vbd_geom,
Tree_geometry const &ft_geom)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("trust_anchor_dir", "/trust_anchor");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "trust_anchor");
xml.node("fs", [&] () {
xml.attribute("label", "trust_anchor");
});
});
});
xml.node("key", [&] () {
xml.attribute("id", "12");
});
xml.node("virtual-block-device", [&] () {
xml.attribute("nr_of_levels", vbd_geom.nr_of_levels());
xml.attribute("nr_of_children", vbd_geom.nr_of_children());
xml.attribute("nr_of_leafs", vbd_geom.nr_of_leaves());
});
xml.node("free-tree", [&] () {
xml.attribute("nr_of_levels", ft_geom.nr_of_levels());
xml.attribute("nr_of_children", ft_geom.nr_of_children());
xml.attribute("nr_of_leafs", ft_geom.nr_of_leaves());
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor");
route_to_child_service(xml, "vfs_block", "Block");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_policy_for_child_service(Xml_generator &xml,
char const *service_name,
Child_state const &child)
{
xml.node("service", [&] () {
xml.attribute("name", service_name);
xml.node("default-policy", [&] () {
xml.node("child", [&] () {
xml.attribute("name", child.start_name());
});
});
});
}
void gen_snapshots_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/cbe/snapshots");
xml.attribute("content", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_resizing_fs_tool_start_node(Xml_generator &xml,
Child_state const &child,
char const *tree,
unsigned long nr_of_blocks)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("exit", "yes");
xml.attribute("verbose", "no");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
xml.node("new-file", [&] () {
xml.attribute("path", "/cbe/cbe/control/extend");
xml.append_content("tree=", tree, ",blocks=", nr_of_blocks);
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_resizing_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/cbe/control");
xml.attribute("content", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_shut_down_fs_tool_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("exit", "yes");
xml.attribute("verbose", "no");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
xml.node("new-file", [&] () {
xml.attribute("path", "/cbe/cbe/control/deinitialize");
xml.append_content("true");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_rekeying_fs_tool_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("exit", "yes");
xml.attribute("verbose", "no");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
xml.node("new-file", [&] () {
xml.attribute("path", "/cbe/cbe/control/rekey");
xml.append_content("true");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_shut_down_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/cbe/control");
xml.attribute("content", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_rekeying_fs_query_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.node("vfs", [&] () {
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
xml.node("query", [&] () {
xml.attribute("path", "/cbe/control");
xml.attribute("content", "yes");
});
});
xml.node("route", [&] () {
route_to_local_service(xml, "Report");
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_create_snap_fs_tool_start_node(Xml_generator &xml,
Child_state const &child)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("exit", "yes");
xml.attribute("verbose", "no");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
xml.node("new-file", [&] () {
xml.attribute("path", "/cbe/cbe/control/create_snapshot");
xml.append_content("true");
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
void gen_discard_snap_fs_tool_start_node(Xml_generator &xml,
Child_state const &child,
Generation generation)
{
child.gen_start_node(xml, [&] () {
xml.node("config", [&] () {
xml.attribute("exit", "yes");
xml.attribute("verbose", "no");
xml.node("vfs", [&] () {
xml.node("dir", [&] () {
xml.attribute("name", "cbe");
xml.node("fs", [&] () {
xml.attribute("writeable", "yes");
});
});
});
xml.node("new-file", [&] () {
xml.attribute("path", "/cbe/cbe/control/discard_snapshot");
xml.append_content(Generation_string(generation));
});
});
xml.node("route", [&] () {
route_to_child_service(xml, "cbe_vfs", "File_system");
gen_parent_routes_for_pd_rom_cpu_log(xml);
});
});
}
}
#endif /* SANDBOX_H_ */

View File

@ -0,0 +1,45 @@
/*
* \brief Pointer of const object safe against null dereferencing
* \author Martin Stein
* \date 2021-04-02
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SNAPSHOT_H_
#define _SNAPSHOT_H_
namespace File_vault {
class Snapshot;
}
class File_vault::Snapshot
{
private:
Generation const _generation;
public:
Snapshot(Generation const &generation)
:
_generation { generation }
{ }
virtual ~Snapshot() { }
/***************
** Accessors **
***************/
Generation const &generation() const { return _generation; }
};
#endif /* _SNAPSHOT_H_ */

View File

@ -0,0 +1,36 @@
/*
* \brief Helps synchronizing the CBE manager to the CBE-driver initialization
* \author Martin Stein
* \date 2021-03-19
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* libC includes */
extern "C" {
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
}
int main(int, char **)
{
char const *file_path { "/cbe/cbe/current/data" };
int const file_descriptor = open(file_path, O_RDONLY);
if (file_descriptor < 0) {
printf("Error: failed to open file %s\n", file_path);
exit(-1);
}
int const result { fsync(file_descriptor) };
if (result != 0) {
printf("Error: fsync on file %s failed\n", file_path);
exit(-1);
}
exit(0);
}

View File

@ -0,0 +1,3 @@
TARGET = file_vault-sync_to_cbe_vfs_init
LIBS = posix
SRC_CC = main.cc

View File

@ -0,0 +1,6 @@
TARGET := file_vault
SRC_CC += main.cc menu_view_dialog.cc capacity.cc
INC_DIR += $(PRG_DIR)
LIBS += base sandbox vfs
CC_OPT += -Os

View File

@ -0,0 +1,85 @@
/*
* \brief Helps synchronizing the CBE manager to the CBE-driver initialization
* \author Martin Stein
* \date 2021-03-19
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/heap.h>
#include <os/vfs.h>
namespace Truncate_file {
class Main;
}
using namespace Truncate_file;
using namespace Genode;
class Truncate_file::Main
{
private:
Env &_env;
Heap _heap { _env.ram(), _env.rm() };
Attached_rom_dataspace _config { _env, "config" };
Root_directory _vfs { _env, _heap, _config.xml().sub_node("vfs") };
Vfs::File_system &_fs { _vfs.root_dir() };
Directory::Path const _path { _config.xml().attribute_value("path", Directory::Path { }) };
Number_of_bytes const _size { _config.xml().attribute_value("size", Number_of_bytes { }) };
public:
Main(Env &env);
};
/*************************
** Truncate_file::Main **
*************************/
Main::Main(Env &env)
:
_env { env }
{
unsigned mode = Vfs::Directory_service::OPEN_MODE_WRONLY;
Vfs::Directory_service::Stat stat { };
if (_fs.stat(_path.string(), stat) != Vfs::Directory_service::STAT_OK) {
mode |= Vfs::Directory_service::OPEN_MODE_CREATE;
}
Vfs::Vfs_handle *handle_ptr = nullptr;
Vfs::Directory_service::Open_result const res =
_fs.open(_path.string(), mode, &handle_ptr, _heap);
if (res != Vfs::Directory_service::OPEN_OK || (handle_ptr == nullptr)) {
error("failed to create file '", _path, "'");
class Create_failed { };
throw Create_failed { };
}
handle_ptr->fs().ftruncate(handle_ptr, _size);
handle_ptr->ds().close(handle_ptr);
_env.parent().exit(0);
}
/***********************
** Genode::Component **
***********************/
void Component::construct(Genode::Env &env)
{
static Truncate_file::Main main { env };
}

View File

@ -0,0 +1,4 @@
TARGET := file_vault-truncate_file
SRC_CC += main.cc
INC_DIR += $(PRG_DIR)/..
LIBS += base vfs

View File

@ -0,0 +1,55 @@
/*
* \brief Common types
* \author Martin Stein
* \date 2021-02-25
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TYPES_H_
#define _TYPES_H_
/* Genode includes */
#include <cbe/types.h>
namespace Genode { }
namespace File_vault {
using namespace Cbe;
using namespace Genode;
using Node_name = String<32>;
class Tree_geometry
{
private:
uint64_t const _nr_of_levels;
uint64_t const _nr_of_children;
uint64_t const _nr_of_leaves;
public:
Tree_geometry(
uint64_t nr_of_levels,
uint64_t nr_of_children,
uint64_t nr_of_leaves)
:
_nr_of_levels { nr_of_levels },
_nr_of_children { nr_of_children },
_nr_of_leaves { nr_of_leaves }
{ }
uint64_t nr_of_levels() const { return _nr_of_levels ; }
uint64_t nr_of_children() const { return _nr_of_children; }
uint64_t nr_of_leaves() const { return _nr_of_leaves ; }
};
}
#endif /* _TYPES_H_ */

View File

@ -0,0 +1,32 @@
/*
* \brief Local extension of Genodes UTF8 utilities
* \author Norman Feske
* \author Martin Stein
* \date 2021-03-04
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _UTF8_H_
#define _UTF8_H_
/* Genode includes */
#include <util/utf8.h>
/* local includes */
#include <types.h>
namespace File_vault {
enum {
CODEPOINT_BACKSPACE = 8,
CODEPOINT_TAB = 9,
};
}
#endif /* _UTF8_H_ */