SystemServerTakeover.cpp 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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<DeprecatedString, 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. s_overtaken_sockets.set(params[0].to_deprecated_string(), strtol(params[1].to_deprecated_string().characters(), nullptr, 10));
  24. }
  25. s_overtaken_sockets_parsed = true;
  26. // We wouldn't want our children to think we're passing
  27. // them a socket either, so unset the env variable.
  28. unsetenv(socket_takeover);
  29. }
  30. ErrorOr<NonnullOwnPtr<Core::LocalSocket>> take_over_socket_from_system_server(DeprecatedString const& socket_path)
  31. {
  32. if (!s_overtaken_sockets_parsed)
  33. parse_sockets_from_system_server();
  34. int fd;
  35. if (socket_path.is_empty()) {
  36. // We want the first (and only) socket.
  37. VERIFY(s_overtaken_sockets.size() == 1);
  38. fd = s_overtaken_sockets.begin()->value;
  39. } else {
  40. auto it = s_overtaken_sockets.find(socket_path);
  41. if (it == s_overtaken_sockets.end())
  42. return Error::from_string_literal("Non-existent socket requested");
  43. fd = it->value;
  44. }
  45. // Sanity check: it has to be a socket.
  46. auto stat = TRY(Core::System::fstat(fd));
  47. if (!S_ISSOCK(stat.st_mode))
  48. return Error::from_string_literal("The fd we got from SystemServer is not a socket");
  49. auto socket = TRY(Core::LocalSocket::adopt_fd(fd));
  50. // It had to be !CLOEXEC for obvious reasons, but we
  51. // don't need it to be !CLOEXEC anymore, so set the
  52. // CLOEXEC flag now.
  53. TRY(socket->set_close_on_exec(true));
  54. return socket;
  55. }
  56. }