VFS: catch Out_of_ram and Out_of_cap exceptions

Catch out of RAM and capability exceptions and return error values.
Abort opening a composite directory at Dir_file_system where an
opendir call on any child file-system returns an OUT_OF_RAM or
OUT_OF_CAPS error.

Ref #2642
This commit is contained in:
Emery Hemingway
2018-01-12 13:47:48 -06:00
committed by Norman Feske
parent c34a4bfdb4
commit c7d0accac0
14 changed files with 194 additions and 80 deletions

View File

@ -540,8 +540,12 @@ class Vfs::Dir_file_system : public File_system
* are subjected to the stacked file-system layout. * are subjected to the stacked file-system layout.
*/ */
if (directory(path)) { if (directory(path)) {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0); try {
return OPEN_OK; *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
/* /*
@ -558,8 +562,12 @@ class Vfs::Dir_file_system : public File_system
/* path equals directory name */ /* path equals directory name */
if (strlen(path) == 0) { if (strlen(path) == 0) {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0); try {
return OPEN_OK; *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
/* path refers to any of our sub file systems */ /* path refers to any of our sub file systems */
@ -595,6 +603,9 @@ class Vfs::Dir_file_system : public File_system
switch (r) { switch (r) {
case OPENDIR_OK: case OPENDIR_OK:
break; break;
case OPEN_ERR_OUT_OF_RAM:
case OPEN_ERR_OUT_OF_CAPS:
return r;
case OPENDIR_ERR_LOOKUP_FAILED: case OPENDIR_ERR_LOOKUP_FAILED:
default: default:
continue; continue;
@ -625,8 +636,13 @@ class Vfs::Dir_file_system : public File_system
* only, VFS root additionally calls 'open_composite_dirs' in order to * only, VFS root additionally calls 'open_composite_dirs' in order to
* open its file systems * open its file systems
*/ */
Dir_vfs_handle *root_handle = new (alloc) Dir_vfs_handle *root_handle;
Dir_vfs_handle(*this, *this, alloc, path); try {
root_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
/* the VFS root may contain more file systems */ /* the VFS root may contain more file systems */
if (_vfs_root) if (_vfs_root)
@ -667,8 +683,13 @@ class Vfs::Dir_file_system : public File_system
return opendir_result; return opendir_result;
} }
Dir_vfs_handle *dir_vfs_handle = new (alloc) Dir_vfs_handle *dir_vfs_handle;
Dir_vfs_handle(*this, *this, alloc, path); try {
dir_vfs_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
/* path equals "/" (for reading the name of this directory) */ /* path equals "/" (for reading the name of this directory) */
if (strlen(sub_path) == 0) if (strlen(sub_path) == 0)

View File

@ -202,10 +202,14 @@ class Vfs::Single_file_system : public File_system
if (create) if (create)
return OPENDIR_ERR_PERMISSION_DENIED; return OPENDIR_ERR_PERMISSION_DENIED;
*out_handle = try {
new (alloc) Single_vfs_dir_handle(*this, *this, alloc, *out_handle = new (alloc)
_node_type, _filename); Single_vfs_dir_handle(*this, *this, alloc,
return OPENDIR_OK; _node_type, _filename);
return OPENDIR_OK;
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
} }
void close(Vfs_handle *handle) override void close(Vfs_handle *handle) override

View File

@ -384,22 +384,26 @@ class Vfs::Block_file_system : public Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Block_vfs_handle(*this, *this, alloc, try {
_label, _lock, *out_handle = new (alloc) Block_vfs_handle(*this, *this, alloc,
_block_buffer, _label, _lock,
_block_buffer_count, _block_buffer,
_tx_block_alloc, _block_buffer_count,
_block, _tx_block_alloc,
_block_size, _block,
_block_count, _block_size,
_block_ops, _block_count,
_tx_source, _block_ops,
_readable, _tx_source,
_writeable, _readable,
_signal_receiver, _writeable,
_signal_context, _signal_receiver,
_source_submit_cap); _signal_context,
return OPEN_OK; _source_submit_cap);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
Stat_result stat(char const *path, Stat &out) override Stat_result stat(char const *path, Stat &out) override

View File

@ -775,9 +775,9 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Invalid_name) { return OPEN_ERR_NAME_TOO_LONG; } catch (::File_system::Invalid_name) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::Name_too_long) { return OPEN_ERR_NAME_TOO_LONG; } catch (::File_system::Name_too_long) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; } catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
catch (::File_system::Unavailable) { return OPEN_ERR_UNACCESSIBLE; } catch (::File_system::Unavailable) { return OPEN_ERR_UNACCESSIBLE; }
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
return OPEN_OK; return OPEN_OK;
} }
@ -800,9 +800,9 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Name_too_long) { return OPENDIR_ERR_NAME_TOO_LONG; } catch (::File_system::Name_too_long) { return OPENDIR_ERR_NAME_TOO_LONG; }
catch (::File_system::Node_already_exists) { return OPENDIR_ERR_NODE_ALREADY_EXISTS; } catch (::File_system::Node_already_exists) { return OPENDIR_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENDIR_ERR_NO_SPACE; } catch (::File_system::No_space) { return OPENDIR_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
catch (::File_system::Permission_denied) { return OPENDIR_ERR_PERMISSION_DENIED; } catch (::File_system::Permission_denied) { return OPENDIR_ERR_PERMISSION_DENIED; }
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
return OPENDIR_OK; return OPENDIR_OK;
} }
@ -844,10 +844,10 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Lookup_failed) { return OPENLINK_ERR_LOOKUP_FAILED; } catch (::File_system::Lookup_failed) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (::File_system::Node_already_exists) { return OPENLINK_ERR_NODE_ALREADY_EXISTS; } catch (::File_system::Node_already_exists) { return OPENLINK_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENLINK_ERR_NO_SPACE; } catch (::File_system::No_space) { return OPENLINK_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
catch (::File_system::Permission_denied) { return OPENLINK_ERR_PERMISSION_DENIED; } catch (::File_system::Permission_denied) { return OPENLINK_ERR_PERMISSION_DENIED; }
catch (::File_system::Unavailable) { return OPENLINK_ERR_LOOKUP_FAILED; } catch (::File_system::Unavailable) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
} }
void close(Vfs_handle *vfs_handle) override void close(Vfs_handle *vfs_handle) override

View File

@ -125,9 +125,13 @@ class Vfs::Inline_file_system : public Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Inline_vfs_handle(*this, *this, alloc, try {
_base, _size); *out_handle = new (alloc)
return OPEN_OK; Inline_vfs_handle(*this, *this, alloc, _base, _size);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
Stat_result stat(char const *path, Stat &out) override Stat_result stat(char const *path, Stat &out) override

View File

@ -115,9 +115,13 @@ class Vfs::Log_file_system : public Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Log_vfs_handle(*this, *this, alloc, try {
_log); *out_handle = new (alloc)
return OPEN_OK; Log_vfs_handle(*this, *this, alloc, _log);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
}; };

View File

@ -69,8 +69,13 @@ struct Vfs::Null_file_system : Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Null_vfs_handle(*this, *this, alloc); try {
return OPEN_OK; *out_handle = new (alloc)
Null_vfs_handle(*this, *this, alloc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
/******************************** /********************************

View File

@ -551,8 +551,9 @@ class Vfs::Ram_file_system : public Vfs::File_system
File *file; File *file;
char const *name = basename(path); char const *name = basename(path);
bool const create = mode & OPEN_MODE_CREATE;
if (mode & OPEN_MODE_CREATE) { if (create) {
Directory *parent = lookup_parent(path); Directory *parent = lookup_parent(path);
if (!parent) return OPEN_ERR_UNACCESSIBLE; if (!parent) return OPEN_ERR_UNACCESSIBLE;
Node::Guard guard(parent); Node::Guard guard(parent);
@ -573,8 +574,22 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!file) return OPEN_ERR_UNACCESSIBLE; if (!file) return OPEN_ERR_UNACCESSIBLE;
} }
*handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file); try {
return OPEN_OK; *handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file);
return OPEN_OK;
} catch (Genode::Out_of_ram) {
if (create) {
lookup_parent(path)->release(file);
remove(file);
}
return OPEN_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
lookup_parent(path)->release(file);
remove(file);
}
return OPEN_ERR_OUT_OF_CAPS;
}
} }
Opendir_result opendir(char const *path, bool create, Opendir_result opendir(char const *path, bool create,
@ -599,9 +614,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (parent->child(name)) if (parent->child(name))
return OPENDIR_ERR_NODE_ALREADY_EXISTS; return OPENDIR_ERR_NODE_ALREADY_EXISTS;
try { try { dir = new (_alloc) Directory(name); }
dir = new (_alloc) Directory(name); catch (Out_of_memory) { return OPENDIR_ERR_NO_SPACE; }
} catch (Out_of_memory) { return OPENDIR_ERR_NO_SPACE; }
parent->adopt(dir); parent->adopt(dir);
@ -614,11 +628,24 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!dir) return OPENDIR_ERR_LOOKUP_FAILED; if (!dir) return OPENDIR_ERR_LOOKUP_FAILED;
} }
*handle = new (alloc) Ram_vfs_handle(*this, alloc, try {
Ram_vfs_handle::STATUS_RDONLY, *handle = new (alloc) Ram_vfs_handle(*this, alloc,
*dir); Ram_vfs_handle::STATUS_RDONLY,
*dir);
return OPENDIR_OK; return OPENDIR_OK;
} catch (Genode::Out_of_ram) {
if (create) {
parent->release(dir);
remove(dir);
}
return OPENDIR_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
parent->release(dir);
remove(dir);
}
return OPENDIR_ERR_OUT_OF_CAPS;
}
} }
Openlink_result openlink(char const *path, bool create, Openlink_result openlink(char const *path, bool create,
@ -660,11 +687,24 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!link) return OPENLINK_ERR_LOOKUP_FAILED; if (!link) return OPENLINK_ERR_LOOKUP_FAILED;
} }
*handle = new (alloc) Ram_vfs_handle(*this, alloc, try {
Ram_vfs_handle::STATUS_RDWR, *handle = new (alloc) Ram_vfs_handle(*this, alloc,
*link); Ram_vfs_handle::STATUS_RDWR,
*link);
return OPENLINK_OK; return OPENLINK_OK;
} catch (Genode::Out_of_ram) {
if (create) {
parent->release(link);
remove(link);
}
return OPENLINK_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
parent->release(link);
remove(link);
}
return OPENLINK_ERR_OUT_OF_CAPS;
}
} }
void close(Vfs_handle *vfs_handle) override void close(Vfs_handle *vfs_handle) override

View File

@ -128,8 +128,13 @@ class Vfs::Rom_file_system : public Single_file_system
_rom.update(); _rom.update();
*out_handle = new (alloc) Rom_vfs_handle(*this, *this, alloc, _rom); try {
return OPEN_OK; *out_handle = new (alloc)
Rom_vfs_handle(*this, *this, alloc, _rom);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
Dataspace_capability dataspace(char const *) override Dataspace_capability dataspace(char const *) override

View File

@ -109,9 +109,13 @@ class Vfs::Rtc_file_system : public Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Rtc_vfs_handle(*this, *this, alloc, try {
_rtc); *out_handle = new (alloc)
return OPEN_OK; Rtc_vfs_handle(*this, *this, alloc, _rtc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
Stat_result stat(char const *path, Stat &out) override Stat_result stat(char const *path, Stat &out) override

View File

@ -59,8 +59,12 @@ class Vfs::Symlink_file_system : public Single_file_system
if (create) if (create)
return OPENLINK_ERR_NODE_ALREADY_EXISTS; return OPENLINK_ERR_NODE_ALREADY_EXISTS;
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0); try {
return OPENLINK_OK; *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPENLINK_OK;
}
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
} }
void close(Vfs_handle *vfs_handle) override void close(Vfs_handle *vfs_handle) override

View File

@ -651,9 +651,13 @@ class Vfs::Tar_file_system : public File_system
if (!node || !node->record || node->record->type() != Record::TYPE_FILE) if (!node || !node->record || node->record->type() != Record::TYPE_FILE)
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Tar_vfs_file_handle(*this, alloc, 0, node); try {
*out_handle = new (alloc)
return OPEN_OK; Tar_vfs_file_handle(*this, alloc, 0, node);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
Opendir_result opendir(char const *path, bool /* create */, Opendir_result opendir(char const *path, bool /* create */,
@ -666,9 +670,13 @@ class Vfs::Tar_file_system : public File_system
(node->record && (node->record->type() != Record::TYPE_DIR))) (node->record && (node->record->type() != Record::TYPE_DIR)))
return OPENDIR_ERR_LOOKUP_FAILED; return OPENDIR_ERR_LOOKUP_FAILED;
*out_handle = new (alloc) Tar_vfs_dir_handle(*this, alloc, 0, node); try {
*out_handle = new (alloc)
return OPENDIR_OK; Tar_vfs_dir_handle(*this, alloc, 0, node);
return OPENDIR_OK;
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
} }
Openlink_result openlink(char const *path, bool /* create */, Openlink_result openlink(char const *path, bool /* create */,
@ -679,9 +687,13 @@ class Vfs::Tar_file_system : public File_system
node->record->type() != Record::TYPE_SYMLINK) node->record->type() != Record::TYPE_SYMLINK)
return OPENLINK_ERR_LOOKUP_FAILED; return OPENLINK_ERR_LOOKUP_FAILED;
*out_handle = new (alloc) Tar_vfs_symlink_handle(*this, alloc, 0, node); try {
*out_handle = new (alloc)
return OPENLINK_OK; Tar_vfs_symlink_handle(*this, alloc, 0, node);
return OPENLINK_OK;
}
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
} }
void close(Vfs_handle *vfs_handle) override void close(Vfs_handle *vfs_handle) override

View File

@ -128,10 +128,13 @@ class Vfs::Terminal_file_system : public Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) try {
Registered_handle(_handle_registry, *this, *this, alloc, 0); *out_handle = new (alloc)
Registered_handle(_handle_registry, *this, *this, alloc, 0);
return OPEN_OK; return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
/******************************** /********************************

View File

@ -71,8 +71,12 @@ struct Vfs::Zero_file_system : Single_file_system
if (!_single_file(path)) if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc); try {
return OPEN_OK; *out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
} }
}; };