vold_prepare_subdirs.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * Tool to create a directory with the right SELinux context applied, or
  18. * apply the context if it's absent. Also fixes mode, uid, gid.
  19. */
  20. #include <iostream>
  21. #include <string>
  22. #include <vector>
  23. #include <dirent.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <sys/stat.h>
  27. #include <sys/types.h>
  28. #include <android-base/logging.h>
  29. #include <android-base/scopeguard.h>
  30. #include <cutils/fs.h>
  31. #include <selinux/android.h>
  32. #include "Utils.h"
  33. #include "android/os/IVold.h"
  34. #include <private/android_filesystem_config.h>
  35. static void usage(const char* progname) {
  36. std::cerr << "Usage: " << progname << " [ prepare | destroy ] <volume_uuid> <user_id> <flags>"
  37. << std::endl;
  38. exit(-1);
  39. }
  40. static bool small_int(const std::string& s) {
  41. return !s.empty() && s.size() < 7 && s.find_first_not_of("0123456789") == std::string::npos;
  42. }
  43. static bool valid_uuid(const std::string& s) {
  44. return s.size() < 40 && s.find_first_not_of("0123456789abcdefABCDEF-_") == std::string::npos;
  45. }
  46. static bool prepare_dir(struct selabel_handle* sehandle, mode_t mode, uid_t uid, gid_t gid,
  47. const std::string& path) {
  48. auto clearfscreatecon = android::base::make_scope_guard([] { setfscreatecon(nullptr); });
  49. auto secontext = std::unique_ptr<char, void (*)(char*)>(nullptr, freecon);
  50. char* tmp_secontext;
  51. if (sehandle && selabel_lookup(sehandle, &tmp_secontext, path.c_str(), S_IFDIR) == 0) {
  52. secontext.reset(tmp_secontext);
  53. }
  54. LOG(DEBUG) << "Setting up mode " << std::oct << mode << std::dec << " uid " << uid << " gid "
  55. << gid << " context " << (secontext ? secontext.get() : "null")
  56. << " on path: " << path;
  57. if (secontext) {
  58. if (setfscreatecon(secontext.get()) != 0) {
  59. PLOG(ERROR) << "Unable to read setfscreatecon for: " << path;
  60. return false;
  61. }
  62. }
  63. if (fs_prepare_dir(path.c_str(), mode, uid, gid) != 0) {
  64. return false;
  65. }
  66. if (secontext) {
  67. char* tmp_oldsecontext = nullptr;
  68. if (lgetfilecon(path.c_str(), &tmp_oldsecontext) < 0) {
  69. PLOG(ERROR) << "Unable to read secontext for: " << path;
  70. return false;
  71. }
  72. auto oldsecontext = std::unique_ptr<char, void (*)(char*)>(tmp_oldsecontext, freecon);
  73. if (strcmp(secontext.get(), oldsecontext.get()) != 0) {
  74. LOG(INFO) << "Relabelling from " << ((char*)oldsecontext.get()) << " to "
  75. << ((char*)secontext.get()) << ": " << path;
  76. if (lsetfilecon(path.c_str(), secontext.get()) != 0) {
  77. PLOG(ERROR) << "Relabelling failed for: " << path;
  78. return false;
  79. }
  80. }
  81. }
  82. return true;
  83. }
  84. static bool rmrf_contents(const std::string& path) {
  85. auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(path.c_str()), closedir);
  86. if (!dirp) {
  87. PLOG(ERROR) << "Unable to open directory: " << path;
  88. return false;
  89. }
  90. bool res = true;
  91. for (;;) {
  92. errno = 0;
  93. auto const entry = readdir(dirp.get());
  94. if (!entry) {
  95. if (errno) {
  96. PLOG(ERROR) << "readdir failed on: " << path;
  97. return false;
  98. }
  99. return res;
  100. }
  101. if (entry->d_name[0] == '.') continue;
  102. auto subdir = path + "/" + entry->d_name;
  103. if (0 !=
  104. android::vold::ForkExecvp(std::vector<std::string>{"/system/bin/rm", "-rf", subdir})) {
  105. LOG(ERROR) << "rm -rf failed on " << subdir;
  106. res = false;
  107. }
  108. }
  109. }
  110. static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int flags) {
  111. struct selabel_handle* sehandle = selinux_android_file_context_handle();
  112. if (volume_uuid.empty()) {
  113. if (flags & android::os::IVold::STORAGE_FLAG_DE) {
  114. auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
  115. if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/vold")) return false;
  116. if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/storaged")) return false;
  117. if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/rollback")) return false;
  118. auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
  119. if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, vendor_de_path + "/fpdata")) {
  120. return false;
  121. }
  122. auto facedata_path = vendor_de_path + "/facedata";
  123. if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, facedata_path)) {
  124. return false;
  125. }
  126. }
  127. if (flags & android::os::IVold::STORAGE_FLAG_CE) {
  128. auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
  129. if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/vold")) return false;
  130. if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/storaged")) return false;
  131. if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/rollback")) return false;
  132. auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
  133. if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, system_ce_path + "/backup")) {
  134. return false;
  135. }
  136. if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM,
  137. system_ce_path + "/backup_stage")) {
  138. return false;
  139. }
  140. auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
  141. auto facedata_path = vendor_ce_path + "/facedata";
  142. if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, facedata_path)) {
  143. return false;
  144. }
  145. }
  146. }
  147. return true;
  148. }
  149. static bool destroy_subdirs(const std::string& volume_uuid, int user_id, int flags) {
  150. bool res = true;
  151. if (volume_uuid.empty()) {
  152. if (flags & android::os::IVold::STORAGE_FLAG_CE) {
  153. auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
  154. res &= rmrf_contents(misc_ce_path);
  155. auto vendor_ce_path = android::vold::BuildDataVendorCePath(user_id);
  156. res &= rmrf_contents(vendor_ce_path);
  157. }
  158. if (flags & android::os::IVold::STORAGE_FLAG_DE) {
  159. auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
  160. res &= rmrf_contents(misc_de_path);
  161. auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
  162. res &= rmrf_contents(vendor_de_path);
  163. }
  164. }
  165. return res;
  166. }
  167. int main(int argc, const char* const argv[]) {
  168. android::base::InitLogging(const_cast<char**>(argv));
  169. std::vector<std::string> args(argv + 1, argv + argc);
  170. if (args.size() != 4 || !valid_uuid(args[1]) || !small_int(args[2]) || !small_int(args[3])) {
  171. usage(argv[0]);
  172. return -1;
  173. }
  174. auto volume_uuid = args[1];
  175. int user_id = stoi(args[2]);
  176. int flags = stoi(args[3]);
  177. if (args[0] == "prepare") {
  178. if (!prepare_subdirs(volume_uuid, user_id, flags)) return -1;
  179. } else if (args[0] == "destroy") {
  180. if (!destroy_subdirs(volume_uuid, user_id, flags)) return -1;
  181. } else {
  182. usage(argv[0]);
  183. return -1;
  184. }
  185. return 0;
  186. }