wind+libui: Add "pledge" functionality to access special features for system programs
All checks were successful
Build and test / build (push) Successful in 1m42s
All checks were successful
Build and test / build (push) Successful in 1m42s
This segments privileges more, making it so that any app connecting to wsys.sock can't just always access every single advanced feature in wind if they don't need to. Of course, apps have to restrict themselves, which is why only privileged apps have access to this feature in the first place. Normal apps' pledges are all empty and can't be changed. An example: taskbar uses the "ExtendedLayers" pledge to move its window to the background, but relinquishes it afterwards, and doesn't need any other advanced feature for now. If a pledge-capable app tries to use a pledge-protected function without having pledged anything, it can't. Pledges are mandatory if you want to access certain functionality, unlike the kernel's pledges which make every syscall available if you don't use pledge().
This commit is contained in:
parent
fb3333a086
commit
ac260d0397
@ -112,6 +112,7 @@ Result<int> luna_main(int, char**)
|
|||||||
{
|
{
|
||||||
ui::App app;
|
ui::App app;
|
||||||
TRY(app.init("/tmp/wsys.sock"));
|
TRY(app.init("/tmp/wsys.sock"));
|
||||||
|
app.pledge(ui::Pledge::ExtendedLayers);
|
||||||
|
|
||||||
TRY(os::EventLoop::the().register_signal_handler(SIGQUIT, sigquit_handler));
|
TRY(os::EventLoop::the().register_signal_handler(SIGQUIT, sigquit_handler));
|
||||||
|
|
||||||
@ -126,6 +127,7 @@ Result<int> luna_main(int, char**)
|
|||||||
|
|
||||||
window->set_background(TASKBAR_COLOR);
|
window->set_background(TASKBAR_COLOR);
|
||||||
window->set_layer(ui::Layer::Background);
|
window->set_layer(ui::Layer::Background);
|
||||||
|
app.pledge(0);
|
||||||
|
|
||||||
ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
ui::HorizontalLayout layout(ui::Margins { 0, 0, 0, 0 }, ui::AdjustHeight::Yes, ui::AdjustWidth::No);
|
||||||
window->set_main_widget(layout);
|
window->set_main_widget(layout);
|
||||||
|
@ -49,6 +49,8 @@ namespace ui
|
|||||||
return m_main_window;
|
return m_main_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pledge(i16 pledges);
|
||||||
|
|
||||||
Result<void> register_window(OwnedPtr<Window>&& window, Badge<Window>);
|
Result<void> register_window(OwnedPtr<Window>&& window, Badge<Window>);
|
||||||
void unregister_window(Window* window, Badge<Window>);
|
void unregister_window(Window* window, Badge<Window>);
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ namespace ui
|
|||||||
GET_SCREEN_RECT_ID,
|
GET_SCREEN_RECT_ID,
|
||||||
SET_TITLEBAR_HEIGHT_ID,
|
SET_TITLEBAR_HEIGHT_ID,
|
||||||
SET_WINDOW_LAYER_ID,
|
SET_WINDOW_LAYER_ID,
|
||||||
|
UPDATE_PLEDGE_REQUEST_ID,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CreateWindowRequest
|
struct CreateWindowRequest
|
||||||
@ -97,4 +98,16 @@ namespace ui
|
|||||||
int window;
|
int window;
|
||||||
Layer layer;
|
Layer layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Pledge : i16
|
||||||
|
{
|
||||||
|
ExtendedLayers = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UpdatePledgeRequest
|
||||||
|
{
|
||||||
|
static constexpr u8 ID = UPDATE_PLEDGE_REQUEST_ID;
|
||||||
|
|
||||||
|
i16 pledges;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -135,4 +135,11 @@ namespace ui
|
|||||||
m_window_clear_queue.clear_data();
|
m_window_clear_queue.clear_data();
|
||||||
return !m_should_close;
|
return !m_should_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::pledge(i16 pledges)
|
||||||
|
{
|
||||||
|
ui::UpdatePledgeRequest request;
|
||||||
|
request.pledges = pledges;
|
||||||
|
client().send_async(request);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ set(SOURCES
|
|||||||
Keyboard.cpp
|
Keyboard.cpp
|
||||||
Keyboard.h
|
Keyboard.h
|
||||||
Client.h
|
Client.h
|
||||||
|
Client.cpp
|
||||||
Layer.cpp
|
Layer.cpp
|
||||||
Layer.h
|
Layer.h
|
||||||
)
|
)
|
||||||
|
52
gui/wind/Client.cpp
Normal file
52
gui/wind/Client.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "Client.h"
|
||||||
|
#include <os/File.h>
|
||||||
|
|
||||||
|
Client::Client(OwnedPtr<os::IPC::ClientConnection>&& 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;
|
||||||
|
}
|
@ -3,20 +3,19 @@
|
|||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include <os/IPC.h>
|
#include <os/IPC.h>
|
||||||
|
|
||||||
|
constexpr i16 HAS_NOT_YET_PLEDGED = -1;
|
||||||
|
constexpr i16 EMPTY_PLEDGE = 0;
|
||||||
|
|
||||||
struct Client
|
struct Client
|
||||||
{
|
{
|
||||||
OwnedPtr<os::IPC::ClientConnection> conn;
|
OwnedPtr<os::IPC::ClientConnection> conn;
|
||||||
Vector<Window*> windows;
|
Vector<Window*> windows;
|
||||||
const bool privileged { false };
|
const bool privileged { false };
|
||||||
bool should_be_disconnected { false };
|
bool should_be_disconnected { false };
|
||||||
|
i16 pledges = 0;
|
||||||
|
|
||||||
Client(OwnedPtr<os::IPC::ClientConnection>&& client, bool priv)
|
bool update_pledges(i16 pledges);
|
||||||
#ifdef CLIENT_IMPLEMENTATION
|
bool check_pledge(i16 pledge);
|
||||||
: conn(move(client)), windows(), privileged(priv)
|
|
||||||
{
|
Client(OwnedPtr<os::IPC::ClientConnection>&& client, i16 pledges);
|
||||||
conn->set_message_handler(wind::handle_ipc_message, this);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
@ -166,11 +166,9 @@ static Result<void> handle_set_window_layer_message(Client& client)
|
|||||||
ui::SetWindowLayer request;
|
ui::SetWindowLayer request;
|
||||||
if (!TRY(client.conn->read_message(request))) return {};
|
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!");
|
if (!client.check_pledge(ui::Pledge::ExtendedLayers)) return {};
|
||||||
client.should_be_disconnected = true;
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_WINDOW_ID(request, "SetWindowLayer");
|
CHECK_WINDOW_ID(request, "SetWindowLayer");
|
||||||
@ -199,6 +197,16 @@ static Result<void> handle_set_window_layer_message(Client& client)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result<void> 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
|
namespace wind
|
||||||
{
|
{
|
||||||
void handle_ipc_message(os::IPC::ClientConnection&, u8 id, void* c)
|
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::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_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::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;
|
default: os::eprintln("wind: Invalid IPC message from client!"); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#define CLIENT_IMPLEMENTATION
|
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "Keyboard.h"
|
#include "Keyboard.h"
|
||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
@ -138,7 +137,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client)));
|
auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client)));
|
||||||
|
|
||||||
OwnedPtr<Client> c = TRY(adopt_owned_if_nonnull(new Client(move(connection), false)));
|
OwnedPtr<Client> c = TRY(adopt_owned_if_nonnull(new Client(move(connection), EMPTY_PLEDGE)));
|
||||||
TRY(clients.try_append(move(c)));
|
TRY(clients.try_append(move(c)));
|
||||||
}
|
}
|
||||||
if (fds[3].revents & POLLIN)
|
if (fds[3].revents & POLLIN)
|
||||||
@ -149,7 +148,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
|
|
||||||
auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client)));
|
auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client)));
|
||||||
|
|
||||||
OwnedPtr<Client> c = TRY(adopt_owned_if_nonnull(new Client(move(connection), true)));
|
OwnedPtr<Client> c = TRY(adopt_owned_if_nonnull(new Client(move(connection), HAS_NOT_YET_PLEDGED)));
|
||||||
TRY(clients.try_append(move(c)));
|
TRY(clients.try_append(move(c)));
|
||||||
}
|
}
|
||||||
for (usize i = 0; i < clients.size(); i++)
|
for (usize i = 0; i < clients.size(); i++)
|
||||||
|
Loading…
Reference in New Issue
Block a user