setuid.cpp 5.0 KB

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