SystemServerTakeover.cpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /*
  2. * Copyright (c) 2022, sin-ack <sin-ack@protonmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "SystemServerTakeover.h"
  7. #include <LibCore/Socket.h>
  8. #include <LibCore/System.h>
  9. namespace Core {
  10. HashMap<ByteString, int> s_overtaken_sockets {};
  11. bool s_overtaken_sockets_parsed { false };
  12. static void parse_sockets_from_system_server()
  13. {
  14. VERIFY(!s_overtaken_sockets_parsed);
  15. constexpr auto socket_takeover = "SOCKET_TAKEOVER";
  16. char const* sockets = getenv(socket_takeover);
  17. if (!sockets) {
  18. s_overtaken_sockets_parsed = true;
  19. return;
  20. }
  21. for (auto const socket : StringView { sockets, strlen(sockets) }.split_view(';')) {
  22. auto params = socket.split_view(':');
  23. VERIFY(params.size() == 2);
  24. s_overtaken_sockets.set(params[0].to_byte_string(), params[1].to_number<int>().value());
  25. }
  26. s_overtaken_sockets_parsed = true;
  27. // We wouldn't want our children to think we're passing
  28. // them a socket either, so unset the env variable.
  29. unsetenv(socket_takeover);
  30. }
  31. ErrorOr<NonnullOwnPtr<Core::LocalSocket>> take_over_socket_from_system_server(ByteString const& socket_path)
  32. {
  33. if (!s_overtaken_sockets_parsed)
  34. parse_sockets_from_system_server();
  35. int fd;
  36. if (socket_path.is_empty()) {
  37. // We want the first (and only) socket.
  38. VERIFY(s_overtaken_sockets.size() == 1);
  39. fd = s_overtaken_sockets.begin()->value;
  40. } else {
  41. auto it = s_overtaken_sockets.find(socket_path);
  42. if (it == s_overtaken_sockets.end())
  43. return Error::from_string_literal("Non-existent socket requested");
  44. fd = it->value;
  45. }
  46. // Sanity check: it has to be a socket.
  47. auto stat = TRY(Core::System::fstat(fd));
  48. if (!S_ISSOCK(stat.st_mode))
  49. return Error::from_string_literal("The fd we got from SystemServer is not a socket");
  50. auto socket = TRY(Core::LocalSocket::adopt_fd(fd));
  51. // It had to be !CLOEXEC for obvious reasons, but we
  52. // don't need it to be !CLOEXEC anymore, so set the
  53. // CLOEXEC flag now.
  54. TRY(socket->set_close_on_exec(true));
  55. return socket;
  56. }
  57. }