From 88757a674abb3d9ec7bbe065144cfa3d46180196 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 12 Dec 2017 17:32:49 -0600 Subject: [PATCH] libc: sync socket control files to check for write errors Ref #2335 --- .../libports/src/lib/libc/socket_fs_plugin.cc | 24 ++++++++------ repos/libports/src/lib/libc/vfs_plugin.cc | 3 +- repos/libports/src/lib/libc/vfs_plugin.h | 31 +++++++++++++------ 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/repos/libports/src/lib/libc/socket_fs_plugin.cc b/repos/libports/src/lib/libc/socket_fs_plugin.cc index 8bf024611..9d03b2c53 100644 --- a/repos/libports/src/lib/libc/socket_fs_plugin.cc +++ b/repos/libports/src/lib/libc/socket_fs_plugin.cc @@ -82,6 +82,8 @@ namespace Socket_fs { struct Local_functor; Plugin & plugin(); + + enum { MAX_CONTROL_PATH_LEN = 16 }; } @@ -447,7 +449,7 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen) /* TODO EOPNOTSUPP - no SOCK_STREAM */ /* TODO ECONNABORTED */ - char accept_socket[10]; + char accept_socket[MAX_CONTROL_PATH_LEN]; { int n = 0; /* XXX currently reading accept may return without new connection */ @@ -503,8 +505,9 @@ extern "C" int socket_fs_bind(int libc_fd, sockaddr const *addr, socklen_t addrl int const len = strlen(addr_string.base()); int const n = write(context->bind_fd(), addr_string.base(), len); if (n != len) return Errno(EACCES); - fsync(context->bind_fd()); - return 0; + + /* sync to block for write completion */ + return fsync(context->bind_fd()); } catch (Socket_fs::Context::Inaccessible) { return Errno(EINVAL); } @@ -537,7 +540,8 @@ extern "C" int socket_fs_connect(int libc_fd, sockaddr const *addr, socklen_t ad int const n = write(context->connect_fd(), addr_string.base(), len); if (n != len) return Errno(ECONNREFUSED); - return 0; + /* sync to block for write completion */ + return fsync(context->connect_fd()); } @@ -549,7 +553,7 @@ extern "C" int socket_fs_listen(int libc_fd, int backlog) Socket_fs::Context *context = dynamic_cast(fd->context); if (!context) return Errno(ENOTSOCK); - char buf[10]; + char buf[MAX_CONTROL_PATH_LEN]; int const len = snprintf(buf, sizeof(buf), "%d", backlog); int const n = write(context->listen_fd(), buf, len); if (n != len) return Errno(EOPNOTSUPP); @@ -742,23 +746,23 @@ extern "C" int socket_fs_shutdown(int libc_fd, int how) } -static Genode::String<16> new_socket(Absolute_path const &path) +static Genode::String new_socket(Absolute_path const &path) { Absolute_path new_socket("new_socket", path.base()); int const fd = open(new_socket.base(), O_RDONLY); if (fd == -1) { - Genode::error(__func__, ": new_socket file not accessible - socket fs not mounted?"); + Genode::error(__func__, ": ", new_socket, " file not accessible - socket fs not mounted?"); throw New_socket_failed(); } - char buf[10]; + char buf[MAX_CONTROL_PATH_LEN]; int const n = read(fd, buf, sizeof(buf)); close(fd); if (n == -1 || !n || n >= (int)sizeof(buf) - 1) throw New_socket_failed(); buf[n] = 0; - return Genode::String<16>(buf); + return Genode::String(buf); } @@ -789,7 +793,7 @@ extern "C" int socket_fs_socket(int domain, int type, int protocol) case Proto::UDP: proto_path.append("/udp"); break; } - Genode::String<16> socket_path = new_socket(proto_path); + auto socket_path = new_socket(proto_path); path.append("/"); path.append(socket_path.string()); } catch (New_socket_failed) { return Errno(EACCES); } diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index cf8d338df..e23fb7fe7 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -884,8 +884,7 @@ int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) int Libc::Vfs_plugin::fsync(Libc::File_descriptor *fd) { Vfs::Vfs_handle *handle = vfs_handle(fd); - _vfs_sync(handle); - return 0; + return _vfs_sync(handle); } diff --git a/repos/libports/src/lib/libc/vfs_plugin.h b/repos/libports/src/lib/libc/vfs_plugin.h index c844e0e7d..42f603bf4 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.h +++ b/repos/libports/src/lib/libc/vfs_plugin.h @@ -18,7 +18,6 @@ /* Genode includes */ #include -#include "task.h" /* libc includes */ #include @@ -28,6 +27,11 @@ #include #include +/* local includes */ +#include "task.h" +#include "libc_errno.h" + + namespace Libc { class Vfs_plugin; } @@ -76,8 +80,14 @@ class Libc::Vfs_plugin : public Libc::Plugin } } - void _vfs_sync(Vfs::Vfs_handle *vfs_handle) + /** + * Sync a handle and propagate errors + */ + int _vfs_sync(Vfs::Vfs_handle *vfs_handle) { + typedef Vfs::File_io_service::Sync_result Result; + Result result = Result::SYNC_QUEUED; + { struct Check : Libc::Suspend_functor { @@ -112,29 +122,32 @@ class Libc::Vfs_plugin : public Libc::Plugin bool retry { false }; Vfs::Vfs_handle *vfs_handle; + Result &result; - Check(Vfs::Vfs_handle *vfs_handle) - : vfs_handle(vfs_handle) { } + Check(Vfs::Vfs_handle *vfs_handle, Result &result) + : vfs_handle(vfs_handle), result(result) { } bool suspend() override { - retry = (vfs_handle->fs().complete_sync(vfs_handle) == - Vfs::File_io_service::SYNC_QUEUED); + result = vfs_handle->fs().complete_sync(vfs_handle); + retry = result == Vfs::File_io_service::SYNC_QUEUED; return retry; } - } check(vfs_handle); + } check(vfs_handle, result); /* * Cannot call Libc::suspend() immediately, because the Libc kernel * might not be running yet. */ - if (vfs_handle->fs().complete_sync(vfs_handle) == - Vfs::File_io_service::SYNC_QUEUED) { + result = vfs_handle->fs().complete_sync(vfs_handle); + if (result == Result::SYNC_QUEUED) { do { Libc::suspend(check); } while (check.retry); } } + + return result == Result::SYNC_OK ? 0 : Libc::Errno(EIO); } public: