pledge.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StringView.h>
  7. #include <Kernel/Process.h>
  8. namespace Kernel {
  9. KResultOr<FlatPtr> Process::sys$pledge(Userspace<const Syscall::SC_pledge_params*> user_params)
  10. {
  11. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  12. Syscall::SC_pledge_params params;
  13. if (!copy_from_user(&params, user_params))
  14. return EFAULT;
  15. if (params.promises.length > 1024 || params.execpromises.length > 1024)
  16. return E2BIG;
  17. OwnPtr<KString> promises;
  18. if (params.promises.characters) {
  19. auto promises_or_error = try_copy_kstring_from_user(params.promises);
  20. if (promises_or_error.is_error())
  21. return promises_or_error.error();
  22. promises = promises_or_error.release_value();
  23. }
  24. OwnPtr<KString> execpromises;
  25. if (params.execpromises.characters) {
  26. auto execpromises_or_error = try_copy_kstring_from_user(params.execpromises);
  27. if (execpromises_or_error.is_error())
  28. return execpromises_or_error.error();
  29. execpromises = execpromises_or_error.release_value();
  30. }
  31. auto parse_pledge = [&](auto pledge_spec, u32& mask) {
  32. auto parts = pledge_spec.split_view(' ');
  33. for (auto& part : parts) {
  34. #define __ENUMERATE_PLEDGE_PROMISE(x) \
  35. if (part == StringView { #x }) { \
  36. mask |= (1u << (u32)Pledge::x); \
  37. continue; \
  38. }
  39. ENUMERATE_PLEDGE_PROMISES
  40. #undef __ENUMERATE_PLEDGE_PROMISE
  41. return false;
  42. }
  43. return true;
  44. };
  45. ProtectedDataMutationScope scope { *this };
  46. u32 new_promises = 0;
  47. if (promises) {
  48. if (!parse_pledge(promises->view(), new_promises))
  49. return EINVAL;
  50. if (m_protected_values.has_promises && (new_promises & ~m_protected_values.promises))
  51. return EPERM;
  52. }
  53. u32 new_execpromises = 0;
  54. if (execpromises) {
  55. if (!parse_pledge(execpromises->view(), new_execpromises))
  56. return EINVAL;
  57. if (m_protected_values.has_execpromises && (new_execpromises & ~m_protected_values.execpromises))
  58. return EPERM;
  59. }
  60. // Only apply promises after all validation has occurred, this ensures
  61. // we don't introduce logic bugs like applying the promises, and then
  62. // erroring out when parsing the exec promises later. Such bugs silently
  63. // leave the caller in an unexpected state.
  64. if (promises) {
  65. m_protected_values.has_promises = true;
  66. m_protected_values.promises = new_promises;
  67. }
  68. if (execpromises) {
  69. m_protected_values.has_execpromises = true;
  70. m_protected_values.execpromises = new_execpromises;
  71. }
  72. return 0;
  73. }
  74. }