setuid.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/Process.h>
  7. namespace Kernel {
  8. KResultOr<FlatPtr> Process::sys$seteuid(uid_t new_euid)
  9. {
  10. REQUIRE_PROMISE(id);
  11. if (new_euid != uid() && new_euid != suid() && !is_superuser())
  12. return EPERM;
  13. if (euid() != new_euid)
  14. set_dumpable(false);
  15. ProtectedDataMutationScope scope { *this };
  16. m_euid = new_euid;
  17. return 0;
  18. }
  19. KResultOr<FlatPtr> Process::sys$setegid(gid_t new_egid)
  20. {
  21. REQUIRE_PROMISE(id);
  22. if (new_egid != gid() && new_egid != sgid() && !is_superuser())
  23. return EPERM;
  24. if (egid() != new_egid)
  25. set_dumpable(false);
  26. ProtectedDataMutationScope scope { *this };
  27. m_egid = new_egid;
  28. return 0;
  29. }
  30. KResultOr<FlatPtr> Process::sys$setuid(uid_t new_uid)
  31. {
  32. REQUIRE_PROMISE(id);
  33. if (new_uid != uid() && new_uid != euid() && !is_superuser())
  34. return EPERM;
  35. if (euid() != new_uid)
  36. set_dumpable(false);
  37. ProtectedDataMutationScope scope { *this };
  38. m_uid = new_uid;
  39. m_euid = new_uid;
  40. m_suid = new_uid;
  41. return 0;
  42. }
  43. KResultOr<FlatPtr> Process::sys$setgid(gid_t new_gid)
  44. {
  45. REQUIRE_PROMISE(id);
  46. if (new_gid != gid() && new_gid != egid() && !is_superuser())
  47. return EPERM;
  48. if (egid() != new_gid)
  49. set_dumpable(false);
  50. ProtectedDataMutationScope scope { *this };
  51. m_gid = new_gid;
  52. m_egid = new_gid;
  53. m_sgid = new_gid;
  54. return 0;
  55. }
  56. KResultOr<FlatPtr> Process::sys$setreuid(uid_t new_ruid, uid_t new_euid)
  57. {
  58. REQUIRE_PROMISE(id);
  59. if (new_ruid == (uid_t)-1)
  60. new_ruid = uid();
  61. if (new_euid == (uid_t)-1)
  62. new_euid = euid();
  63. auto ok = [this](uid_t id) { return id == uid() || id == euid() || id == suid(); };
  64. if (!ok(new_ruid) || !ok(new_euid))
  65. return EPERM;
  66. if (new_ruid < (uid_t)-1 || new_euid < (uid_t)-1)
  67. return EINVAL;
  68. if (euid() != new_euid)
  69. set_dumpable(false);
  70. ProtectedDataMutationScope scope { *this };
  71. m_uid = new_ruid;
  72. m_euid = new_euid;
  73. return 0;
  74. }
  75. KResultOr<FlatPtr> Process::sys$setresuid(uid_t new_ruid, uid_t new_euid, uid_t new_suid)
  76. {
  77. REQUIRE_PROMISE(id);
  78. if (new_ruid == (uid_t)-1)
  79. new_ruid = uid();
  80. if (new_euid == (uid_t)-1)
  81. new_euid = euid();
  82. if (new_suid == (uid_t)-1)
  83. new_suid = suid();
  84. auto ok = [this](uid_t id) { return id == uid() || id == euid() || id == suid(); };
  85. if ((!ok(new_ruid) || !ok(new_euid) || !ok(new_suid)) && !is_superuser())
  86. return EPERM;
  87. if (euid() != new_euid)
  88. set_dumpable(false);
  89. ProtectedDataMutationScope scope { *this };
  90. m_uid = new_ruid;
  91. m_euid = new_euid;
  92. m_suid = new_suid;
  93. return 0;
  94. }
  95. KResultOr<FlatPtr> Process::sys$setresgid(gid_t new_rgid, gid_t new_egid, gid_t new_sgid)
  96. {
  97. REQUIRE_PROMISE(id);
  98. if (new_rgid == (gid_t)-1)
  99. new_rgid = gid();
  100. if (new_egid == (gid_t)-1)
  101. new_egid = egid();
  102. if (new_sgid == (gid_t)-1)
  103. new_sgid = sgid();
  104. auto ok = [this](gid_t id) { return id == gid() || id == egid() || id == sgid(); };
  105. if ((!ok(new_rgid) || !ok(new_egid) || !ok(new_sgid)) && !is_superuser())
  106. return EPERM;
  107. if (egid() != new_egid)
  108. set_dumpable(false);
  109. ProtectedDataMutationScope scope { *this };
  110. m_gid = new_rgid;
  111. m_egid = new_egid;
  112. m_sgid = new_sgid;
  113. return 0;
  114. }
  115. KResultOr<FlatPtr> Process::sys$setgroups(size_t count, Userspace<const gid_t*> user_gids)
  116. {
  117. REQUIRE_PROMISE(id);
  118. if (!is_superuser())
  119. return EPERM;
  120. if (!count) {
  121. ProtectedDataMutationScope scope { *this };
  122. m_extra_gids.clear();
  123. return 0;
  124. }
  125. Vector<gid_t> new_extra_gids;
  126. if (!new_extra_gids.try_resize(count))
  127. return ENOMEM;
  128. if (!copy_n_from_user(new_extra_gids.data(), user_gids, count))
  129. return EFAULT;
  130. HashTable<gid_t> unique_extra_gids;
  131. for (auto& extra_gid : new_extra_gids) {
  132. if (extra_gid != gid())
  133. unique_extra_gids.set(extra_gid);
  134. }
  135. ProtectedDataMutationScope scope { *this };
  136. if (!m_extra_gids.try_resize(unique_extra_gids.size()))
  137. return ENOMEM;
  138. size_t i = 0;
  139. for (auto& extra_gid : unique_extra_gids) {
  140. if (extra_gid == gid())
  141. continue;
  142. m_extra_gids[i++] = extra_gid;
  143. }
  144. return 0;
  145. }
  146. }