Unify client policy across File_system servers

File_system servers shall deny clients not matching a defined policy.
Servers shall also apply session root offset policy followed by a client
offset.

Fix #2365
This commit is contained in:
Emery Hemingway 2017-04-03 12:24:19 -05:00 committed by Christian Helmuth
parent 2668a55688
commit dde11de008
3 changed files with 56 additions and 55 deletions

View File

@ -410,28 +410,24 @@ class File_system::Root : public Root_component<Session_component>
try {
Session_policy policy(label);
/* Determine the session root directory.
* Defaults to '/' if not specified by session
* policy or session arguments.
*/
/* determine policy root offset */
try {
policy.attribute("root").value(tmp, sizeof(tmp));
session_root.import(tmp, "/");
} catch (Xml_node::Nonexistent_attribute) { }
/* Determine if the session is writeable.
* Policy overrides arguments, both default to false.
/*
* Determine if the session is writeable.
* Policy overrides client argument, both default to false.
*/
if (policy.attribute_value("writeable", false))
writeable = Arg_string::find_arg(args, "writeable").bool_value(false);
} catch (Session_policy::No_policy_defined) {
/* missing policy - deny request */
throw Root::Unavailable();
}
} catch (...) { }
/*
* If no policy matches the client gets
* read-only access to the root.
*/
/* apply client's root offset */
Arg_string::find_arg(args, "root").string(tmp, sizeof(tmp), "/");
if (Genode::strcmp("/", tmp, sizeof(tmp))) {
session_root.append("/");

View File

@ -441,12 +441,12 @@ class File_system::Root : public Root_component<Session_component>
* the client's label.
*/
Directory *session_root_dir = 0;
bool writeable = false;
enum { ROOT_MAX_LEN = 256 };
char root[ROOT_MAX_LEN];
root[0] = 0;
Genode::Path<MAX_PATH_LEN> session_root;
char tmp[MAX_PATH_LEN];
Directory *session_root_dir = nullptr;
bool writeable = false;
Session_label const label = label_from_args(args);
try {
@ -454,48 +454,56 @@ class File_system::Root : public Root_component<Session_component>
/*
* Determine directory that is used as root directory of
* the session.
* the session. Clients without a specified root are denied.
*/
try {
policy.attribute("root").value(root, sizeof(root));
if (strcmp("/", root) == 0) {
session_root_dir = &_root_dir;
} else {
/*
* Make sure the root path is specified with a
* leading path delimiter. For performing the
* lookup, we skip the first character.
*/
if (root[0] != '/')
throw Lookup_failed();
session_root_dir = _root_dir.lookup_and_lock_dir(root + 1);
session_root_dir->unlock();
}
policy.attribute("root").value(tmp, sizeof(tmp));
session_root.import(tmp, "/");
} catch (Xml_node::Nonexistent_attribute) {
Genode::error("missing \"root\" attribute in policy definition");
throw Root::Unavailable();
} catch (Lookup_failed) {
Genode::error("session root directory \"",
Genode::Cstring(root), "\" does not exist");
throw Root::Unavailable();
}
/*
* Determine if write access is permitted for the session.
* Determine if the session is writeable.
* Policy overrides client argument, both default to false.
*/
writeable = policy.attribute_value("writeable", false);
if (policy.attribute_value("writeable", false))
writeable = Arg_string::find_arg(args, "writeable").bool_value(false);
} catch (Session_policy::No_policy_defined) {
Genode::error("invalid session request, no matching policy");
throw Root::Unavailable();
}
/* apply client's root offset */
Arg_string::find_arg(args, "root").string(tmp, sizeof(tmp), "/");
if (Genode::strcmp("/", tmp, sizeof(tmp))) {
session_root.append("/");
session_root.append(tmp);
}
session_root.remove_trailing('/');
if (session_root == "/") {
session_root_dir = &_root_dir;
} else {
try {
/*
* The root path is specified with a leading path
* delimiter. For performing the lookup, we skip the first
* character.
*/
session_root_dir = _root_dir.lookup_and_lock_dir(
session_root.base() + 1);
session_root_dir->unlock();
} catch (Lookup_failed) {
throw Root::Unavailable();
}
}
size_t ram_quota =
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
Arg_string::find_arg(args, "ram_quota" ).aligned_size();
size_t tx_buf_size =
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
Arg_string::find_arg(args, "tx_buf_size").aligned_size();
if (!tx_buf_size) {
Genode::error(label, " requested a session with a zero length transmission buffer");

View File

@ -685,34 +685,31 @@ class Vfs_server::Root :
try {
Session_policy policy(label, _config_rom.xml());
/* Determine the session root directory.
* Defaults to '/' if not specified by session
* policy or session arguments.
*/
/* determine optional session root offset. */
try {
policy.attribute("root").value(tmp, sizeof(tmp));
session_root.import(tmp, "/");
} catch (Xml_node::Nonexistent_attribute) { }
/* Determine if the session is writeable.
* Policy overrides arguments, both default to false.
/*
* Determine if the session is writeable.
* Policy overrides client argument, both default to false.
*/
if (policy.attribute_value("writeable", false))
writeable = Arg_string::find_arg(args, "writeable").bool_value(false);
} catch (Session_policy::No_policy_defined) { }
} catch (Session_policy::No_policy_defined) {
/* missing policy - deny request */
throw Root::Unavailable();
}
/* apply client's root offset. */
Arg_string::find_arg(args, "root").string(tmp, sizeof(tmp), "/");
if (Genode::strcmp("/", tmp, sizeof(tmp))) {
session_root.append("/");
session_root.append(tmp);
}
/*
* If no policy matches the client gets
* read-only access to the root.
*/
/* check if the session root exists */
if (!((session_root == "/") || _vfs.directory(session_root.base()))) {
error("session root '", session_root, "' not found for '", label, "'");