diff --git a/gui/apps/taskbar.cpp b/gui/apps/taskbar.cpp index 6665dd1b..df2595c9 100644 --- a/gui/apps/taskbar.cpp +++ b/gui/apps/taskbar.cpp @@ -112,6 +112,7 @@ Result luna_main(int, char**) { ui::App app; TRY(app.init("/tmp/wsys.sock")); + app.pledge(ui::Pledge::ExtendedLayers); TRY(os::EventLoop::the().register_signal_handler(SIGQUIT, sigquit_handler)); @@ -126,6 +127,7 @@ Result luna_main(int, char**) window->set_background(TASKBAR_COLOR); window->set_layer(ui::Layer::Background); + app.pledge(0); ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No); window->set_main_widget(layout); diff --git a/gui/libui/include/ui/App.h b/gui/libui/include/ui/App.h index ce1e2496..ca2794ee 100644 --- a/gui/libui/include/ui/App.h +++ b/gui/libui/include/ui/App.h @@ -49,6 +49,8 @@ namespace ui return m_main_window; } + void pledge(i16 pledges); + Result register_window(OwnedPtr&& window, Badge); void unregister_window(Window* window, Badge); diff --git a/gui/libui/include/ui/ipc/Server.h b/gui/libui/include/ui/ipc/Server.h index ae37d77c..62344b60 100644 --- a/gui/libui/include/ui/ipc/Server.h +++ b/gui/libui/include/ui/ipc/Server.h @@ -26,6 +26,7 @@ namespace ui GET_SCREEN_RECT_ID, SET_TITLEBAR_HEIGHT_ID, SET_WINDOW_LAYER_ID, + UPDATE_PLEDGE_REQUEST_ID, }; struct CreateWindowRequest @@ -97,4 +98,16 @@ namespace ui int window; Layer layer; }; + + enum Pledge : i16 + { + ExtendedLayers = 1, + }; + + struct UpdatePledgeRequest + { + static constexpr u8 ID = UPDATE_PLEDGE_REQUEST_ID; + + i16 pledges; + }; } diff --git a/gui/libui/src/App.cpp b/gui/libui/src/App.cpp index d53b17b7..f40bff49 100644 --- a/gui/libui/src/App.cpp +++ b/gui/libui/src/App.cpp @@ -135,4 +135,11 @@ namespace ui m_window_clear_queue.clear_data(); return !m_should_close; } + + void App::pledge(i16 pledges) + { + ui::UpdatePledgeRequest request; + request.pledges = pledges; + client().send_async(request); + } } diff --git a/gui/wind/CMakeLists.txt b/gui/wind/CMakeLists.txt index 85455a93..d31e0eed 100644 --- a/gui/wind/CMakeLists.txt +++ b/gui/wind/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCES Keyboard.cpp Keyboard.h Client.h + Client.cpp Layer.cpp Layer.h ) diff --git a/gui/wind/Client.cpp b/gui/wind/Client.cpp new file mode 100644 index 00000000..4198ff4a --- /dev/null +++ b/gui/wind/Client.cpp @@ -0,0 +1,52 @@ +#include "Client.h" +#include + +Client::Client(OwnedPtr&& client, i16 _pledges) + : conn(move(client)), windows(), pledges(_pledges) +{ + conn->set_message_handler(wind::handle_ipc_message, this); +} + +bool Client::update_pledges(i16 _pledges) +{ + if (_pledges < 0) + { + os::eprintln("wind: Client trying to set an invalid pledge, disconnecting!"); + should_be_disconnected = true; + return false; + } + + if (pledges < 0) + { + pledges = _pledges; + return true; + } + + if (_pledges & ~pledges) + { + os::eprintln("wind: Client trying to add pledges, disconnecting!"); + should_be_disconnected = true; + return false; + } + + pledges = _pledges; + return true; +} + +bool Client::check_pledge(i16 pledge) +{ + check(pledge > 0); + + if (pledges < 0) + { + os::eprintln("wind: Client trying to use pledge-protected functions before pledging anything, disconnecting!"); + should_be_disconnected = true; + return false; + } + + if ((pledges & pledge) == pledge) return true; + + os::eprintln("wind: Client trying to use a function they haven't pledged, disconnecting!"); + should_be_disconnected = true; + return false; +} diff --git a/gui/wind/Client.h b/gui/wind/Client.h index ad3a0a7e..12cc1d2c 100644 --- a/gui/wind/Client.h +++ b/gui/wind/Client.h @@ -3,20 +3,19 @@ #include "Window.h" #include +constexpr i16 HAS_NOT_YET_PLEDGED = -1; +constexpr i16 EMPTY_PLEDGE = 0; + struct Client { OwnedPtr conn; Vector windows; const bool privileged { false }; bool should_be_disconnected { false }; + i16 pledges = 0; - Client(OwnedPtr&& client, bool priv) -#ifdef CLIENT_IMPLEMENTATION - : conn(move(client)), windows(), privileged(priv) - { - conn->set_message_handler(wind::handle_ipc_message, this); - } -#else - ; -#endif + bool update_pledges(i16 pledges); + bool check_pledge(i16 pledge); + + Client(OwnedPtr&& client, i16 pledges); }; diff --git a/gui/wind/IPC.cpp b/gui/wind/IPC.cpp index f879e20c..abe5c0b4 100644 --- a/gui/wind/IPC.cpp +++ b/gui/wind/IPC.cpp @@ -166,11 +166,9 @@ static Result handle_set_window_layer_message(Client& client) ui::SetWindowLayer request; if (!TRY(client.conn->read_message(request))) return {}; - if (request.layer != ui::Layer::Global && request.layer != ui::Layer::GlobalTop && !client.privileged) + if (request.layer != ui::Layer::Global && request.layer != ui::Layer::GlobalTop) { - os::eprintln("wind: Unprivileged client trying to set window layer to a privileged layer, disconnecting!"); - client.should_be_disconnected = true; - return {}; + if (!client.check_pledge(ui::Pledge::ExtendedLayers)) return {}; } CHECK_WINDOW_ID(request, "SetWindowLayer"); @@ -199,6 +197,16 @@ static Result handle_set_window_layer_message(Client& client) return {}; } +static Result handle_update_pledge_request_message(Client& client) +{ + ui::UpdatePledgeRequest request; + if (!TRY(client.conn->read_message(request))) return {}; + + client.update_pledges(request.pledges); // update_pledges does all the checking. + + return {}; +} + namespace wind { void handle_ipc_message(os::IPC::ClientConnection&, u8 id, void* c) @@ -214,6 +222,7 @@ namespace wind case ui::GET_SCREEN_RECT_ID: handle_get_screen_rect_message(client); break; case ui::SET_TITLEBAR_HEIGHT_ID: handle_set_titlebar_height_message(client); break; case ui::SET_WINDOW_LAYER_ID: handle_set_window_layer_message(client); break; + case ui::UPDATE_PLEDGE_REQUEST_ID: handle_update_pledge_request_message(client); break; default: os::eprintln("wind: Invalid IPC message from client!"); return; } } diff --git a/gui/wind/main.cpp b/gui/wind/main.cpp index bbebfc68..d35000d9 100644 --- a/gui/wind/main.cpp +++ b/gui/wind/main.cpp @@ -1,4 +1,3 @@ -#define CLIENT_IMPLEMENTATION #include "Client.h" #include "Keyboard.h" #include "Layer.h" @@ -138,7 +137,7 @@ Result luna_main(int argc, char** argv) auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client))); - OwnedPtr c = TRY(adopt_owned_if_nonnull(new Client(move(connection), false))); + OwnedPtr c = TRY(adopt_owned_if_nonnull(new Client(move(connection), EMPTY_PLEDGE))); TRY(clients.try_append(move(c))); } if (fds[3].revents & POLLIN) @@ -149,7 +148,7 @@ Result luna_main(int argc, char** argv) auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client))); - OwnedPtr c = TRY(adopt_owned_if_nonnull(new Client(move(connection), true))); + OwnedPtr c = TRY(adopt_owned_if_nonnull(new Client(move(connection), HAS_NOT_YET_PLEDGED))); TRY(clients.try_append(move(c))); } for (usize i = 0; i < clients.size(); i++)