sdcard.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. // Copyright (C) 2016 The Android Open Source Project
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #define LOG_TAG "sdcard"
  15. #include <dirent.h>
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <linux/fuse.h>
  19. #include <pthread.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <sys/inotify.h>
  23. #include <sys/mount.h>
  24. #include <sys/resource.h>
  25. #include <sys/stat.h>
  26. #include <sys/types.h>
  27. #include <unistd.h>
  28. #include <android-base/file.h>
  29. #include <android-base/logging.h>
  30. #include <android-base/macros.h>
  31. #include <android-base/stringprintf.h>
  32. #include <android-base/strings.h>
  33. #include <cutils/fs.h>
  34. #include <cutils/multiuser.h>
  35. #include <cutils/properties.h>
  36. #include <packagelistparser/packagelistparser.h>
  37. #include <libminijail.h>
  38. #include <scoped_minijail.h>
  39. #include <private/android_filesystem_config.h>
  40. // README
  41. //
  42. // What is this?
  43. //
  44. // sdcard is a program that uses FUSE to emulate FAT-on-sdcard style
  45. // directory permissions (all files are given fixed owner, group, and
  46. // permissions at creation, owner, group, and permissions are not
  47. // changeable, symlinks and hardlinks are not createable, etc.
  48. //
  49. // See usage() for command line options.
  50. //
  51. // It must be run as root, but will drop to requested UID/GID as soon as it
  52. // mounts a filesystem. It will refuse to run if requested UID/GID are zero.
  53. //
  54. // Things I believe to be true:
  55. //
  56. // - ops that return a fuse_entry (LOOKUP, MKNOD, MKDIR, LINK, SYMLINK,
  57. // CREAT) must bump that node's refcount
  58. // - don't forget that FORGET can forget multiple references (req->nlookup)
  59. // - if an op that returns a fuse_entry fails writing the reply to the
  60. // kernel, you must rollback the refcount to reflect the reference the
  61. // kernel did not actually acquire
  62. //
  63. // This daemon can also derive custom filesystem permissions based on directory
  64. // structure when requested. These custom permissions support several features:
  65. //
  66. // - Apps can access their own files in /Android/data/com.example/ without
  67. // requiring any additional GIDs.
  68. // - Separate permissions for protecting directories like Pictures and Music.
  69. // - Multi-user separation on the same physical device.
  70. #include "fuse.h"
  71. #define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs"
  72. #define PROP_SDCARDFS_USER "persist.sys.sdcardfs"
  73. /* Supplementary groups to execute with. */
  74. static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
  75. static bool package_parse_callback(pkg_info *info, void *userdata) {
  76. struct fuse_global *global = (struct fuse_global *)userdata;
  77. bool res = global->package_to_appid->emplace(info->name, info->uid).second;
  78. packagelist_free(info);
  79. return res;
  80. }
  81. static bool read_package_list(struct fuse_global* global) {
  82. pthread_mutex_lock(&global->lock);
  83. global->package_to_appid->clear();
  84. bool rc = packagelist_parse(package_parse_callback, global);
  85. DLOG(INFO) << "read_package_list: found " << global->package_to_appid->size() << " packages";
  86. // Regenerate ownership details using newly loaded mapping.
  87. derive_permissions_recursive_locked(global->fuse_default, &global->root);
  88. pthread_mutex_unlock(&global->lock);
  89. return rc;
  90. }
  91. static void watch_package_list(struct fuse_global* global) {
  92. struct inotify_event *event;
  93. char event_buf[512];
  94. int nfd = inotify_init();
  95. if (nfd == -1) {
  96. PLOG(ERROR) << "inotify_init failed";
  97. return;
  98. }
  99. bool active = false;
  100. while (1) {
  101. if (!active) {
  102. int res = inotify_add_watch(nfd, PACKAGES_LIST_FILE, IN_DELETE_SELF);
  103. if (res == -1) {
  104. if (errno == ENOENT || errno == EACCES) {
  105. /* Framework may not have created the file yet, sleep and retry. */
  106. LOG(ERROR) << "missing \"" << PACKAGES_LIST_FILE << "\"; retrying...";
  107. sleep(3);
  108. continue;
  109. } else {
  110. PLOG(ERROR) << "inotify_add_watch failed";
  111. return;
  112. }
  113. }
  114. /* Watch above will tell us about any future changes, so
  115. * read the current state. */
  116. if (read_package_list(global) == false) {
  117. LOG(ERROR) << "read_package_list failed";
  118. return;
  119. }
  120. active = true;
  121. }
  122. int event_pos = 0;
  123. ssize_t res = TEMP_FAILURE_RETRY(read(nfd, event_buf, sizeof(event_buf)));
  124. if (res == -1) {
  125. PLOG(ERROR) << "failed to read inotify event";
  126. return;
  127. } else if (static_cast<size_t>(res) < sizeof(*event)) {
  128. LOG(ERROR) << "failed to read inotify event: read " << res << " expected "
  129. << sizeof(event_buf);
  130. return;
  131. }
  132. while (res >= static_cast<ssize_t>(sizeof(*event))) {
  133. int event_size;
  134. event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
  135. DLOG(INFO) << "inotify event: " << std::hex << event->mask << std::dec;
  136. if ((event->mask & IN_IGNORED) == IN_IGNORED) {
  137. /* Previously watched file was deleted, probably due to move
  138. * that swapped in new data; re-arm the watch and read. */
  139. active = false;
  140. }
  141. event_size = sizeof(*event) + event->len;
  142. res -= event_size;
  143. event_pos += event_size;
  144. }
  145. }
  146. }
  147. static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) {
  148. char opts[256];
  149. fuse->fd = TEMP_FAILURE_RETRY(open("/dev/fuse", O_RDWR | O_CLOEXEC));
  150. if (fuse->fd == -1) {
  151. PLOG(ERROR) << "failed to open fuse device";
  152. return -1;
  153. }
  154. umount2(fuse->dest_path, MNT_DETACH);
  155. snprintf(opts, sizeof(opts),
  156. "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d",
  157. fuse->fd, fuse->global->uid, fuse->global->gid);
  158. if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME,
  159. opts) == -1) {
  160. PLOG(ERROR) << "failed to mount fuse filesystem";
  161. return -1;
  162. }
  163. fuse->gid = gid;
  164. fuse->mask = mask;
  165. return 0;
  166. }
  167. static void drop_privs(uid_t uid, gid_t gid) {
  168. ScopedMinijail j(minijail_new());
  169. minijail_set_supplementary_gids(j.get(), arraysize(kGroups), kGroups);
  170. minijail_change_gid(j.get(), gid);
  171. minijail_change_uid(j.get(), uid);
  172. /* minijail_enter() will abort if priv-dropping fails. */
  173. minijail_enter(j.get());
  174. }
  175. static void* start_handler(void* data) {
  176. struct fuse_handler* handler = static_cast<fuse_handler*>(data);
  177. handle_fuse_requests(handler);
  178. return NULL;
  179. }
  180. static void run(const char* source_path, const char* label, uid_t uid,
  181. gid_t gid, userid_t userid, bool multi_user, bool full_write) {
  182. struct fuse_global global;
  183. struct fuse fuse_default;
  184. struct fuse fuse_read;
  185. struct fuse fuse_write;
  186. struct fuse fuse_full;
  187. struct fuse_handler handler_default;
  188. struct fuse_handler handler_read;
  189. struct fuse_handler handler_write;
  190. struct fuse_handler handler_full;
  191. pthread_t thread_default;
  192. pthread_t thread_read;
  193. pthread_t thread_write;
  194. pthread_t thread_full;
  195. memset(&global, 0, sizeof(global));
  196. memset(&fuse_default, 0, sizeof(fuse_default));
  197. memset(&fuse_read, 0, sizeof(fuse_read));
  198. memset(&fuse_write, 0, sizeof(fuse_write));
  199. memset(&fuse_full, 0, sizeof(fuse_full));
  200. memset(&handler_default, 0, sizeof(handler_default));
  201. memset(&handler_read, 0, sizeof(handler_read));
  202. memset(&handler_write, 0, sizeof(handler_write));
  203. memset(&handler_full, 0, sizeof(handler_full));
  204. pthread_mutex_init(&global.lock, NULL);
  205. global.package_to_appid = new AppIdMap;
  206. global.uid = uid;
  207. global.gid = gid;
  208. global.multi_user = multi_user;
  209. global.next_generation = 0;
  210. global.inode_ctr = 1;
  211. memset(&global.root, 0, sizeof(global.root));
  212. global.root.nid = FUSE_ROOT_ID; /* 1 */
  213. global.root.refcount = 2;
  214. global.root.namelen = strlen(source_path);
  215. global.root.name = strdup(source_path);
  216. global.root.userid = userid;
  217. global.root.uid = AID_ROOT;
  218. global.root.under_android = false;
  219. strcpy(global.source_path, source_path);
  220. if (multi_user) {
  221. global.root.perm = PERM_PRE_ROOT;
  222. snprintf(global.obb_path, sizeof(global.obb_path), "%s/obb", source_path);
  223. } else {
  224. global.root.perm = PERM_ROOT;
  225. snprintf(global.obb_path, sizeof(global.obb_path), "%s/Android/obb", source_path);
  226. }
  227. fuse_default.global = &global;
  228. fuse_read.global = &global;
  229. fuse_write.global = &global;
  230. fuse_full.global = &global;
  231. global.fuse_default = &fuse_default;
  232. global.fuse_read = &fuse_read;
  233. global.fuse_write = &fuse_write;
  234. global.fuse_full = &fuse_full;
  235. snprintf(fuse_default.dest_path, PATH_MAX, "/mnt/runtime/default/%s", label);
  236. snprintf(fuse_read.dest_path, PATH_MAX, "/mnt/runtime/read/%s", label);
  237. snprintf(fuse_write.dest_path, PATH_MAX, "/mnt/runtime/write/%s", label);
  238. snprintf(fuse_full.dest_path, PATH_MAX, "/mnt/runtime/full/%s", label);
  239. handler_default.fuse = &fuse_default;
  240. handler_read.fuse = &fuse_read;
  241. handler_write.fuse = &fuse_write;
  242. handler_full.fuse = &fuse_full;
  243. handler_default.token = 0;
  244. handler_read.token = 1;
  245. handler_write.token = 2;
  246. handler_full.token = 3;
  247. umask(0);
  248. if (multi_user) {
  249. /* Multi-user storage is fully isolated per user, so "other"
  250. * permissions are completely masked off. */
  251. if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006)
  252. || fuse_setup(&fuse_read, AID_EVERYBODY, 0027)
  253. || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0027)
  254. || fuse_setup(&fuse_full, AID_EVERYBODY, 0007)) {
  255. PLOG(FATAL) << "failed to fuse_setup";
  256. }
  257. } else {
  258. /* Physical storage is readable by all users on device, but
  259. * the Android directories are masked off to a single user
  260. * deep inside attr_from_stat(). */
  261. if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006)
  262. || fuse_setup(&fuse_read, AID_EVERYBODY, full_write ? 0027 : 0022)
  263. || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0022)
  264. || fuse_setup(&fuse_full, AID_EVERYBODY, 0007)) {
  265. PLOG(FATAL) << "failed to fuse_setup";
  266. }
  267. }
  268. // Will abort if priv-dropping fails.
  269. drop_privs(uid, gid);
  270. if (multi_user) {
  271. fs_prepare_dir(global.obb_path, 0775, uid, gid);
  272. }
  273. if (pthread_create(&thread_default, NULL, start_handler, &handler_default)
  274. || pthread_create(&thread_read, NULL, start_handler, &handler_read)
  275. || pthread_create(&thread_write, NULL, start_handler, &handler_write)
  276. || pthread_create(&thread_full, NULL, start_handler, &handler_full)) {
  277. LOG(FATAL) << "failed to pthread_create";
  278. }
  279. LOG(WARNING) << "run func watch...";
  280. watch_package_list(&global);
  281. LOG(WARNING) << "run func watch end...";
  282. LOG(FATAL) << "terminated prematurely";
  283. }
  284. static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path,
  285. uid_t fsuid, gid_t fsgid, bool multi_user, userid_t userid, gid_t gid,
  286. mode_t mask, bool derive_gid, bool default_normal, bool unshared_obb) {
  287. std::string opts = android::base::StringPrintf(
  288. "fsuid=%d,fsgid=%d,%s%s%s%smask=%d,userid=%d,gid=%d", fsuid, fsgid,
  289. multi_user ? "multiuser," : "", derive_gid ? "derive_gid," : "",
  290. default_normal ? "default_normal," : "", unshared_obb ? "unshared_obb," : "", mask, userid, gid);
  291. if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
  292. MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
  293. if (derive_gid) {
  294. PLOG(ERROR) << "trying to mount sdcardfs filesystem without derive_gid";
  295. /* Maybe this isn't supported on this kernel. Try without. */
  296. opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d",
  297. fsuid, fsgid, multi_user ? "multiuser," : "", mask,
  298. userid, gid);
  299. if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
  300. MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
  301. PLOG(ERROR) << "failed to mount sdcardfs filesystem";
  302. return false;
  303. }
  304. } else {
  305. PLOG(ERROR) << "failed to mount sdcardfs filesystem";
  306. return false;
  307. }
  308. }
  309. return true;
  310. }
  311. static bool sdcardfs_setup_bind_remount(const std::string& source_path, const std::string& dest_path,
  312. gid_t gid, mode_t mask) {
  313. std::string opts = android::base::StringPrintf("mask=%d,gid=%d", mask, gid);
  314. if (mount(source_path.c_str(), dest_path.c_str(), nullptr,
  315. MS_BIND, nullptr) != 0) {
  316. PLOG(ERROR) << "failed to bind mount sdcardfs filesystem";
  317. return false;
  318. }
  319. if (mount(source_path.c_str(), dest_path.c_str(), "none",
  320. MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
  321. PLOG(ERROR) << "failed to mount sdcardfs filesystem";
  322. if (umount2(dest_path.c_str(), MNT_DETACH))
  323. PLOG(WARNING) << "Failed to unmount bind";
  324. return false;
  325. }
  326. return true;
  327. }
  328. static void run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
  329. gid_t gid, userid_t userid, bool multi_user, bool full_write,
  330. bool derive_gid, bool default_normal, bool unshared_obb) {
  331. std::string dest_path_default = "/mnt/runtime/default/" + label;
  332. std::string dest_path_read = "/mnt/runtime/read/" + label;
  333. std::string dest_path_write = "/mnt/runtime/write/" + label;
  334. std::string dest_path_full = "/mnt/runtime/full/" + label;
  335. umask(0);
  336. if (multi_user) {
  337. // Multi-user storage is fully isolated per user, so "other"
  338. // permissions are completely masked off.
  339. if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
  340. AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb) ||
  341. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, AID_EVERYBODY, 0027) ||
  342. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write, AID_EVERYBODY, full_write ? 0007 : 0027)||
  343. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_full, AID_EVERYBODY, 0007)) {
  344. LOG(FATAL) << "failed to sdcardfs_setup";
  345. }
  346. } else {
  347. // Physical storage is readable by all users on device, but
  348. // the Android directories are masked off to a single user
  349. // deep inside attr_from_stat().
  350. if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
  351. AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb) ||
  352. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, AID_EVERYBODY,
  353. full_write ? 0027 : 0022) ||
  354. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write, AID_EVERYBODY,
  355. full_write ? 0007 : 0022) ||
  356. !sdcardfs_setup_bind_remount(dest_path_default, dest_path_full, AID_EVERYBODY,
  357. 0007)) {
  358. LOG(FATAL) << "failed to sdcardfs_setup";
  359. }
  360. }
  361. // Will abort if priv-dropping fails.
  362. drop_privs(uid, gid);
  363. if (multi_user) {
  364. std::string obb_path = source_path + "/obb";
  365. fs_prepare_dir(obb_path.c_str(), 0775, uid, gid);
  366. }
  367. LOG(WARNING) << "run_sdcardfs func exit...";
  368. exit(0);
  369. }
  370. static bool supports_sdcardfs(void) {
  371. std::string filesystems;
  372. if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) {
  373. PLOG(ERROR) << "Could not read /proc/filesystems";
  374. return false;
  375. }
  376. for (const auto& fs : android::base::Split(filesystems, "\n")) {
  377. if (fs.find("sdcardfs") != std::string::npos) return true;
  378. }
  379. return false;
  380. }
  381. static bool should_use_sdcardfs(void) {
  382. char property[PROPERTY_VALUE_MAX];
  383. // Allow user to have a strong opinion about state
  384. property_get(PROP_SDCARDFS_USER, property, "");
  385. if (!strcmp(property, "force_on")) {
  386. LOG(WARNING) << "User explicitly enabled sdcardfs";
  387. return supports_sdcardfs();
  388. } else if (!strcmp(property, "force_off")) {
  389. LOG(WARNING) << "User explicitly disabled sdcardfs";
  390. return false;
  391. }
  392. // Fall back to device opinion about state
  393. if (property_get_bool(PROP_SDCARDFS_DEVICE, true)) {
  394. LOG(WARNING) << "Device explicitly enabled sdcardfs";
  395. return supports_sdcardfs();
  396. } else {
  397. LOG(WARNING) << "Device explicitly disabled sdcardfs";
  398. return false;
  399. }
  400. }
  401. static int usage() {
  402. LOG(ERROR) << "usage: sdcard [OPTIONS] <source_path> <label>"
  403. << " -u: specify UID to run as"
  404. << " -g: specify GID to run as"
  405. << " -U: specify user ID that owns device"
  406. << " -m: source_path is multi-user"
  407. << " -w: runtime write mount has full write access"
  408. << " -P preserve owners on the lower file system";
  409. return 1;
  410. }
  411. int main(int argc, char **argv) {
  412. const char *source_path = NULL;
  413. const char *label = NULL;
  414. uid_t uid = 0;
  415. gid_t gid = 0;
  416. userid_t userid = 0;
  417. bool multi_user = false;
  418. bool full_write = false;
  419. bool derive_gid = false;
  420. bool default_normal = false;
  421. bool unshared_obb = false;
  422. int i;
  423. struct rlimit rlim;
  424. int fs_version;
  425. int opt;
  426. while ((opt = getopt(argc, argv, "u:g:U:mwGio")) != -1) {
  427. switch (opt) {
  428. case 'u':
  429. uid = strtoul(optarg, NULL, 10);
  430. break;
  431. case 'g':
  432. gid = strtoul(optarg, NULL, 10);
  433. break;
  434. case 'U':
  435. userid = strtoul(optarg, NULL, 10);
  436. break;
  437. case 'm':
  438. multi_user = true;
  439. break;
  440. case 'w':
  441. full_write = true;
  442. break;
  443. case 'G':
  444. derive_gid = true;
  445. break;
  446. case 'i':
  447. default_normal = true;
  448. break;
  449. case 'o':
  450. unshared_obb = true;
  451. break;
  452. case '?':
  453. default:
  454. return usage();
  455. }
  456. }
  457. for (i = optind; i < argc; i++) {
  458. char* arg = argv[i];
  459. if (!source_path) {
  460. source_path = arg;
  461. } else if (!label) {
  462. label = arg;
  463. } else {
  464. LOG(ERROR) << "too many arguments";
  465. return usage();
  466. }
  467. }
  468. if (!source_path) {
  469. LOG(ERROR) << "no source path specified";
  470. return usage();
  471. }
  472. if (!label) {
  473. LOG(ERROR) << "no label specified";
  474. return usage();
  475. }
  476. if (!uid || !gid) {
  477. LOG(ERROR) << "uid and gid must be nonzero";
  478. return usage();
  479. }
  480. rlim.rlim_cur = 8192;
  481. rlim.rlim_max = 8192;
  482. if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
  483. PLOG(ERROR) << "setting RLIMIT_NOFILE failed";
  484. }
  485. while ((fs_read_atomic_int("/data/.layout_version", &fs_version) == -1) || (fs_version < 3)) {
  486. LOG(ERROR) << "installd fs upgrade not yet complete; waiting...";
  487. sleep(1);
  488. }
  489. if (should_use_sdcardfs()) {
  490. run_sdcardfs(source_path, label, uid, gid, userid, multi_user, full_write, derive_gid, default_normal, unshared_obb);
  491. } else {
  492. run(source_path, label, uid, gid, userid, multi_user, full_write);
  493. }
  494. return 1;
  495. }