sdcard.c revision aa04e818a4904b193e00d603785c93e888eab174
1/* 2 * Copyright (C) 2010 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#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21#include <errno.h> 22#include <fcntl.h> 23#include <sys/mount.h> 24#include <sys/stat.h> 25#include <sys/statfs.h> 26#include <sys/uio.h> 27#include <dirent.h> 28#include <limits.h> 29#include <ctype.h> 30#include <pthread.h> 31#include <sys/time.h> 32#include <sys/resource.h> 33#include <sys/inotify.h> 34 35#include <cutils/hashmap.h> 36#include <cutils/multiuser.h> 37 38#include <private/android_filesystem_config.h> 39 40#include "fuse.h" 41 42/* README 43 * 44 * What is this? 45 * 46 * sdcard is a program that uses FUSE to emulate FAT-on-sdcard style 47 * directory permissions (all files are given fixed owner, group, and 48 * permissions at creation, owner, group, and permissions are not 49 * changeable, symlinks and hardlinks are not createable, etc. 50 * 51 * See usage() for command line options. 52 * 53 * It must be run as root, but will drop to requested UID/GID as soon as it 54 * mounts a filesystem. It will refuse to run if requested UID/GID are zero. 55 * 56 * Things I believe to be true: 57 * 58 * - ops that return a fuse_entry (LOOKUP, MKNOD, MKDIR, LINK, SYMLINK, 59 * CREAT) must bump that node's refcount 60 * - don't forget that FORGET can forget multiple references (req->nlookup) 61 * - if an op that returns a fuse_entry fails writing the reply to the 62 * kernel, you must rollback the refcount to reflect the reference the 63 * kernel did not actually acquire 64 * 65 * This daemon can also derive custom filesystem permissions based on directory 66 * structure when requested. These custom permissions support several features: 67 * 68 * - Apps can access their own files in /Android/data/com.example/ without 69 * requiring any additional GIDs. 70 * - Separate permissions for protecting directories like Pictures and Music. 71 * - Multi-user separation on the same physical device. 72 * 73 * The derived permissions look like this: 74 * 75 * rwxrwx--x root:sdcard_rw / 76 * rwxrwx--- root:sdcard_pics /Pictures 77 * rwxrwx--- root:sdcard_av /Music 78 * 79 * rwxrwx--x root:sdcard_rw /Android 80 * rwxrwx--x root:sdcard_rw /Android/data 81 * rwxrwx--- u0_a12:sdcard_rw /Android/data/com.example 82 * rwxrwx--x root:sdcard_rw /Android/obb/ 83 * rwxrwx--- u0_a12:sdcard_rw /Android/obb/com.example 84 * 85 * rwxrwx--- root:sdcard_all /Android/user 86 * rwxrwx--x root:sdcard_rw /Android/user/10 87 * rwxrwx--- u10_a12:sdcard_rw /Android/user/10/Android/data/com.example 88 */ 89 90#define FUSE_TRACE 0 91 92#if FUSE_TRACE 93#define TRACE(x...) fprintf(stderr,x) 94#else 95#define TRACE(x...) do {} while (0) 96#endif 97 98#define ERROR(x...) fprintf(stderr,x) 99 100#define FUSE_UNKNOWN_INO 0xffffffff 101 102/* Maximum number of bytes to write in one request. */ 103#define MAX_WRITE (256 * 1024) 104 105/* Maximum number of bytes to read in one request. */ 106#define MAX_READ (128 * 1024) 107 108/* Largest possible request. 109 * The request size is bounded by the maximum size of a FUSE_WRITE request because it has 110 * the largest possible data payload. */ 111#define MAX_REQUEST_SIZE (sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in) + MAX_WRITE) 112 113/* Default number of threads. */ 114#define DEFAULT_NUM_THREADS 2 115 116/* Pseudo-error constant used to indicate that no fuse status is needed 117 * or that a reply has already been written. */ 118#define NO_STATUS 1 119 120/* Path to system-provided mapping of package name to appIds */ 121static const char* const kPackagesListFile = "/data/system/packages.list"; 122 123/* Supplementary groups to execute with */ 124static const gid_t kGroups[1] = { AID_PACKAGE_INFO }; 125 126/* Permission mode for a specific node. Controls how file permissions 127 * are derived for children nodes. */ 128typedef enum { 129 /* Nothing special; this node should just inherit from its parent. */ 130 PERM_INHERIT, 131 /* This node is one level above a normal root; used for legacy layouts 132 * which use the first level to represent user_id. */ 133 PERM_LEGACY_PRE_ROOT, 134 /* This node is "/" */ 135 PERM_ROOT, 136 /* This node is "/Android" */ 137 PERM_ANDROID, 138 /* This node is "/Android/data" */ 139 PERM_ANDROID_DATA, 140 /* This node is "/Android/obb" */ 141 PERM_ANDROID_OBB, 142 /* This node is "/Android/user" */ 143 PERM_ANDROID_USER, 144} perm_t; 145 146/* Permissions structure to derive */ 147typedef enum { 148 DERIVE_NONE, 149 DERIVE_LEGACY, 150 DERIVE_UNIFIED, 151} derive_t; 152 153struct handle { 154 int fd; 155}; 156 157struct dirhandle { 158 DIR *d; 159}; 160 161struct node { 162 __u32 refcount; 163 __u64 nid; 164 __u64 gen; 165 166 /* State derived based on current position in hierarchy. */ 167 perm_t perm; 168 userid_t userid; 169 uid_t uid; 170 gid_t gid; 171 mode_t mode; 172 173 struct node *next; /* per-dir sibling list */ 174 struct node *child; /* first contained file by this dir */ 175 struct node *parent; /* containing directory */ 176 177 size_t namelen; 178 char *name; 179 /* If non-null, this is the real name of the file in the underlying storage. 180 * This may differ from the field "name" only by case. 181 * strlen(actual_name) will always equal strlen(name), so it is safe to use 182 * namelen for both fields. 183 */ 184 char *actual_name; 185 186 /* If non-null, an exact underlying path that should be grafted into this 187 * position. Used to support things like OBB. */ 188 char* graft_path; 189 size_t graft_pathlen; 190}; 191 192static int str_hash(void *key) { 193 return hashmapHash(key, strlen(key)); 194} 195 196static bool str_equals(void *keyA, void *keyB) { 197 return strcmp(keyA, keyB) == 0; 198} 199 200static int int_hash(void *key) { 201 return (int) key; 202} 203 204static bool int_equals(void *keyA, void *keyB) { 205 return keyA == keyB; 206} 207 208/* Global data structure shared by all fuse handlers. */ 209struct fuse { 210 pthread_mutex_t lock; 211 212 __u64 next_generation; 213 int fd; 214 derive_t derive; 215 bool split_perms; 216 struct node root; 217 char obbpath[PATH_MAX]; 218 219 Hashmap* package_to_appid; 220 Hashmap* appid_with_rw; 221}; 222 223/* Private data used by a single fuse handler. */ 224struct fuse_handler { 225 struct fuse* fuse; 226 int token; 227 228 /* To save memory, we never use the contents of the request buffer and the read 229 * buffer at the same time. This allows us to share the underlying storage. */ 230 union { 231 __u8 request_buffer[MAX_REQUEST_SIZE]; 232 __u8 read_buffer[MAX_READ]; 233 }; 234}; 235 236static inline void *id_to_ptr(__u64 nid) 237{ 238 return (void *) (uintptr_t) nid; 239} 240 241static inline __u64 ptr_to_id(void *ptr) 242{ 243 return (__u64) (uintptr_t) ptr; 244} 245 246static void acquire_node_locked(struct node* node) 247{ 248 node->refcount++; 249 TRACE("ACQUIRE %p (%s) rc=%d\n", node, node->name, node->refcount); 250} 251 252static void remove_node_from_parent_locked(struct node* node); 253 254static void release_node_locked(struct node* node) 255{ 256 TRACE("RELEASE %p (%s) rc=%d\n", node, node->name, node->refcount); 257 if (node->refcount > 0) { 258 node->refcount--; 259 if (!node->refcount) { 260 TRACE("DESTROY %p (%s)\n", node, node->name); 261 remove_node_from_parent_locked(node); 262 263 /* TODO: remove debugging - poison memory */ 264 memset(node->name, 0xef, node->namelen); 265 free(node->name); 266 free(node->actual_name); 267 memset(node, 0xfc, sizeof(*node)); 268 free(node); 269 } 270 } else { 271 ERROR("Zero refcnt %p\n", node); 272 } 273} 274 275static void add_node_to_parent_locked(struct node *node, struct node *parent) { 276 node->parent = parent; 277 node->next = parent->child; 278 parent->child = node; 279 acquire_node_locked(parent); 280} 281 282static void remove_node_from_parent_locked(struct node* node) 283{ 284 if (node->parent) { 285 if (node->parent->child == node) { 286 node->parent->child = node->parent->child->next; 287 } else { 288 struct node *node2; 289 node2 = node->parent->child; 290 while (node2->next != node) 291 node2 = node2->next; 292 node2->next = node->next; 293 } 294 release_node_locked(node->parent); 295 node->parent = NULL; 296 node->next = NULL; 297 } 298} 299 300/* Gets the absolute path to a node into the provided buffer. 301 * 302 * Populates 'buf' with the path and returns the length of the path on success, 303 * or returns -1 if the path is too long for the provided buffer. 304 */ 305static ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize) { 306 const char* name; 307 size_t namelen; 308 if (node->graft_path) { 309 name = node->graft_path; 310 namelen = node->graft_pathlen; 311 } else if (node->actual_name) { 312 name = node->actual_name; 313 namelen = node->namelen; 314 } else { 315 name = node->name; 316 namelen = node->namelen; 317 } 318 319 if (bufsize < namelen + 1) { 320 return -1; 321 } 322 323 ssize_t pathlen = 0; 324 if (node->parent && node->graft_path == NULL) { 325 pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 2); 326 if (pathlen < 0) { 327 return -1; 328 } 329 buf[pathlen++] = '/'; 330 } 331 332 memcpy(buf + pathlen, name, namelen + 1); /* include trailing \0 */ 333 return pathlen + namelen; 334} 335 336/* Finds the absolute path of a file within a given directory. 337 * Performs a case-insensitive search for the file and sets the buffer to the path 338 * of the first matching file. If 'search' is zero or if no match is found, sets 339 * the buffer to the path that the file would have, assuming the name were case-sensitive. 340 * 341 * Populates 'buf' with the path and returns the actual name (within 'buf') on success, 342 * or returns NULL if the path is too long for the provided buffer. 343 */ 344static char* find_file_within(const char* path, const char* name, 345 char* buf, size_t bufsize, int search) 346{ 347 size_t pathlen = strlen(path); 348 size_t namelen = strlen(name); 349 size_t childlen = pathlen + namelen + 1; 350 char* actual; 351 352 if (bufsize <= childlen) { 353 return NULL; 354 } 355 356 memcpy(buf, path, pathlen); 357 buf[pathlen] = '/'; 358 actual = buf + pathlen + 1; 359 memcpy(actual, name, namelen + 1); 360 361 if (search && access(buf, F_OK)) { 362 struct dirent* entry; 363 DIR* dir = opendir(path); 364 if (!dir) { 365 ERROR("opendir %s failed: %s\n", path, strerror(errno)); 366 return actual; 367 } 368 while ((entry = readdir(dir))) { 369 if (!strcasecmp(entry->d_name, name)) { 370 /* we have a match - replace the name, don't need to copy the null again */ 371 memcpy(actual, entry->d_name, namelen); 372 break; 373 } 374 } 375 closedir(dir); 376 } 377 return actual; 378} 379 380static void attr_from_stat(struct fuse_attr *attr, const struct stat *s, const struct node* node) 381{ 382 attr->ino = node->nid; 383 attr->size = s->st_size; 384 attr->blocks = s->st_blocks; 385 attr->atime = s->st_atime; 386 attr->mtime = s->st_mtime; 387 attr->ctime = s->st_ctime; 388 attr->atimensec = s->st_atime_nsec; 389 attr->mtimensec = s->st_mtime_nsec; 390 attr->ctimensec = s->st_ctime_nsec; 391 attr->mode = s->st_mode; 392 attr->nlink = s->st_nlink; 393 394 attr->uid = node->uid; 395 attr->gid = node->gid; 396 397 /* Filter requested mode based on underlying file, and 398 * pass through file type. */ 399 int owner_mode = s->st_mode & 0700; 400 int filtered_mode = node->mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); 401 attr->mode = (attr->mode & S_IFMT) | filtered_mode; 402} 403 404static void derive_permissions_locked(struct fuse* fuse, struct node *parent, 405 struct node *node) { 406 appid_t appid; 407 408 /* By default, each node inherits from its parent */ 409 node->perm = PERM_INHERIT; 410 node->userid = parent->userid; 411 node->uid = parent->uid; 412 node->gid = parent->gid; 413 node->mode = parent->mode; 414 415 if (fuse->derive == DERIVE_NONE) { 416 return; 417 } 418 419 /* Derive custom permissions based on parent and current node */ 420 switch (parent->perm) { 421 case PERM_INHERIT: 422 /* Already inherited above */ 423 break; 424 case PERM_LEGACY_PRE_ROOT: 425 /* Legacy internal layout places users at top level */ 426 node->perm = PERM_ROOT; 427 node->userid = strtoul(node->name, NULL, 10); 428 break; 429 case PERM_ROOT: 430 /* Assume masked off by default. */ 431 node->mode = 0770; 432 if (!strcmp(node->name, "Android")) { 433 /* App-specific directories inside; let anyone traverse */ 434 node->perm = PERM_ANDROID; 435 node->mode = 0771; 436 } else if (fuse->split_perms) { 437 if (!strcmp(node->name, "DCIM") 438 || !strcmp(node->name, "Pictures")) { 439 node->gid = AID_SDCARD_PICS; 440 } else if (!strcmp(node->name, "Alarms") 441 || !strcmp(node->name, "Movies") 442 || !strcmp(node->name, "Music") 443 || !strcmp(node->name, "Notifications") 444 || !strcmp(node->name, "Podcasts") 445 || !strcmp(node->name, "Ringtones")) { 446 node->gid = AID_SDCARD_AV; 447 } 448 } 449 break; 450 case PERM_ANDROID: 451 if (!strcmp(node->name, "data")) { 452 /* App-specific directories inside; let anyone traverse */ 453 node->perm = PERM_ANDROID_DATA; 454 node->mode = 0771; 455 } else if (!strcmp(node->name, "obb")) { 456 /* App-specific directories inside; let anyone traverse */ 457 node->perm = PERM_ANDROID_OBB; 458 node->mode = 0771; 459 /* Single OBB directory is always shared */ 460 node->graft_path = fuse->obbpath; 461 node->graft_pathlen = strlen(fuse->obbpath); 462 } else if (!strcmp(node->name, "user")) { 463 /* User directories must only be accessible to system, protected 464 * by sdcard_all. Zygote will bind mount the appropriate user- 465 * specific path. */ 466 node->perm = PERM_ANDROID_USER; 467 node->gid = AID_SDCARD_ALL; 468 node->mode = 0770; 469 } 470 break; 471 case PERM_ANDROID_DATA: 472 case PERM_ANDROID_OBB: 473 appid = (appid_t) hashmapGet(fuse->package_to_appid, node->name); 474 if (appid != 0) { 475 node->uid = multiuser_get_uid(parent->userid, appid); 476 } 477 node->mode = 0770; 478 break; 479 case PERM_ANDROID_USER: 480 /* Root of a secondary user */ 481 node->perm = PERM_ROOT; 482 node->userid = strtoul(node->name, NULL, 10); 483 node->gid = AID_SDCARD_R; 484 node->mode = 0771; 485 break; 486 } 487} 488 489/* Return if the calling UID holds sdcard_rw. */ 490static bool get_caller_has_rw_locked(struct fuse* fuse, const struct fuse_in_header *hdr) { 491 appid_t appid = multiuser_get_app_id(hdr->uid); 492 return hashmapContainsKey(fuse->appid_with_rw, (void*) appid); 493} 494 495/* Kernel has already enforced everything we returned through 496 * derive_permissions_locked(), so this is used to lock down access 497 * even further, such as enforcing that apps hold sdcard_rw. */ 498static bool check_caller_access_to_name(struct fuse* fuse, 499 const struct fuse_in_header *hdr, const struct node* parent_node, 500 const char* name, int mode, bool has_rw) { 501 /* Always block security-sensitive files at root */ 502 if (parent_node && parent_node->perm == PERM_ROOT) { 503 if (!strcmp(name, "autorun.inf") 504 || !strcmp(name, ".android_secure") 505 || !strcmp(name, "android_secure")) { 506 return false; 507 } 508 } 509 510 /* No additional permissions enforcement */ 511 if (fuse->derive == DERIVE_NONE) { 512 return true; 513 } 514 515 /* Root or shell always have access */ 516 if (hdr->uid == 0 || hdr->uid == AID_SHELL) { 517 return true; 518 } 519 520 /* If asking to write, verify that caller either owns the 521 * parent or holds sdcard_rw. */ 522 if (mode & W_OK) { 523 if (parent_node && hdr->uid == parent_node->uid) { 524 return true; 525 } 526 527 return has_rw; 528 } 529 530 /* No extra permissions to enforce */ 531 return true; 532} 533 534static bool check_caller_access_to_node(struct fuse* fuse, 535 const struct fuse_in_header *hdr, const struct node* node, int mode, bool has_rw) { 536 return check_caller_access_to_name(fuse, hdr, node->parent, node->name, mode, has_rw); 537} 538 539struct node *create_node_locked(struct fuse* fuse, 540 struct node *parent, const char *name, const char* actual_name) 541{ 542 struct node *node; 543 size_t namelen = strlen(name); 544 545 node = calloc(1, sizeof(struct node)); 546 if (!node) { 547 return NULL; 548 } 549 node->name = malloc(namelen + 1); 550 if (!node->name) { 551 free(node); 552 return NULL; 553 } 554 memcpy(node->name, name, namelen + 1); 555 if (strcmp(name, actual_name)) { 556 node->actual_name = malloc(namelen + 1); 557 if (!node->actual_name) { 558 free(node->name); 559 free(node); 560 return NULL; 561 } 562 memcpy(node->actual_name, actual_name, namelen + 1); 563 } 564 node->namelen = namelen; 565 node->nid = ptr_to_id(node); 566 node->gen = fuse->next_generation++; 567 568 derive_permissions_locked(fuse, parent, node); 569 acquire_node_locked(node); 570 add_node_to_parent_locked(node, parent); 571 return node; 572} 573 574static int rename_node_locked(struct node *node, const char *name, 575 const char* actual_name) 576{ 577 size_t namelen = strlen(name); 578 int need_actual_name = strcmp(name, actual_name); 579 580 /* make the storage bigger without actually changing the name 581 * in case an error occurs part way */ 582 if (namelen > node->namelen) { 583 char* new_name = realloc(node->name, namelen + 1); 584 if (!new_name) { 585 return -ENOMEM; 586 } 587 node->name = new_name; 588 if (need_actual_name && node->actual_name) { 589 char* new_actual_name = realloc(node->actual_name, namelen + 1); 590 if (!new_actual_name) { 591 return -ENOMEM; 592 } 593 node->actual_name = new_actual_name; 594 } 595 } 596 597 /* update the name, taking care to allocate storage before overwriting the old name */ 598 if (need_actual_name) { 599 if (!node->actual_name) { 600 node->actual_name = malloc(namelen + 1); 601 if (!node->actual_name) { 602 return -ENOMEM; 603 } 604 } 605 memcpy(node->actual_name, actual_name, namelen + 1); 606 } else { 607 free(node->actual_name); 608 node->actual_name = NULL; 609 } 610 memcpy(node->name, name, namelen + 1); 611 node->namelen = namelen; 612 return 0; 613} 614 615static struct node *lookup_node_by_id_locked(struct fuse *fuse, __u64 nid) 616{ 617 if (nid == FUSE_ROOT_ID) { 618 return &fuse->root; 619 } else { 620 return id_to_ptr(nid); 621 } 622} 623 624static struct node* lookup_node_and_path_by_id_locked(struct fuse* fuse, __u64 nid, 625 char* buf, size_t bufsize) 626{ 627 struct node* node = lookup_node_by_id_locked(fuse, nid); 628 if (node && get_node_path_locked(node, buf, bufsize) < 0) { 629 node = NULL; 630 } 631 return node; 632} 633 634static struct node *lookup_child_by_name_locked(struct node *node, const char *name) 635{ 636 for (node = node->child; node; node = node->next) { 637 /* use exact string comparison, nodes that differ by case 638 * must be considered distinct even if they refer to the same 639 * underlying file as otherwise operations such as "mv x x" 640 * will not work because the source and target nodes are the same. */ 641 if (!strcmp(name, node->name)) { 642 return node; 643 } 644 } 645 return 0; 646} 647 648static struct node* acquire_or_create_child_locked( 649 struct fuse* fuse, struct node* parent, 650 const char* name, const char* actual_name) 651{ 652 struct node* child = lookup_child_by_name_locked(parent, name); 653 if (child) { 654 acquire_node_locked(child); 655 } else { 656 child = create_node_locked(fuse, parent, name, actual_name); 657 } 658 return child; 659} 660 661static void fuse_init(struct fuse *fuse, int fd, const char *source_path, 662 gid_t fs_gid, derive_t derive, bool split_perms) { 663 pthread_mutex_init(&fuse->lock, NULL); 664 665 fuse->fd = fd; 666 fuse->next_generation = 0; 667 fuse->derive = derive; 668 fuse->split_perms = split_perms; 669 670 memset(&fuse->root, 0, sizeof(fuse->root)); 671 fuse->root.nid = FUSE_ROOT_ID; /* 1 */ 672 fuse->root.refcount = 2; 673 fuse->root.namelen = strlen(source_path); 674 fuse->root.name = strdup(source_path); 675 fuse->root.userid = 0; 676 fuse->root.uid = AID_ROOT; 677 678 /* Set up root node for various modes of operation */ 679 switch (derive) { 680 case DERIVE_NONE: 681 /* Traditional behavior that treats entire device as being accessible 682 * to sdcard_rw, and no permissions are derived. */ 683 fuse->root.perm = PERM_ROOT; 684 fuse->root.mode = 0775; 685 fuse->root.gid = AID_SDCARD_RW; 686 break; 687 case DERIVE_LEGACY: 688 /* Legacy behavior used to support internal multiuser layout which 689 * places user_id at the top directory level, with the actual roots 690 * just below that. Shared OBB path is also at top level. */ 691 fuse->root.perm = PERM_LEGACY_PRE_ROOT; 692 fuse->root.mode = 0771; 693 fuse->root.gid = fs_gid; 694 fuse->package_to_appid = hashmapCreate(256, str_hash, str_equals); 695 fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); 696 snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path); 697 break; 698 case DERIVE_UNIFIED: 699 /* Unified multiuser layout which places secondary user_id under 700 * /Android/user and shared OBB path under /Android/obb. */ 701 fuse->root.perm = PERM_ROOT; 702 fuse->root.mode = 0771; 703 fuse->root.gid = fs_gid; 704 fuse->package_to_appid = hashmapCreate(256, str_hash, str_equals); 705 fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); 706 snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path); 707 break; 708 } 709} 710 711static void fuse_status(struct fuse *fuse, __u64 unique, int err) 712{ 713 struct fuse_out_header hdr; 714 hdr.len = sizeof(hdr); 715 hdr.error = err; 716 hdr.unique = unique; 717 write(fuse->fd, &hdr, sizeof(hdr)); 718} 719 720static void fuse_reply(struct fuse *fuse, __u64 unique, void *data, int len) 721{ 722 struct fuse_out_header hdr; 723 struct iovec vec[2]; 724 int res; 725 726 hdr.len = len + sizeof(hdr); 727 hdr.error = 0; 728 hdr.unique = unique; 729 730 vec[0].iov_base = &hdr; 731 vec[0].iov_len = sizeof(hdr); 732 vec[1].iov_base = data; 733 vec[1].iov_len = len; 734 735 res = writev(fuse->fd, vec, 2); 736 if (res < 0) { 737 ERROR("*** REPLY FAILED *** %d\n", errno); 738 } 739} 740 741static int fuse_reply_entry(struct fuse* fuse, __u64 unique, 742 struct node* parent, const char* name, const char* actual_name, 743 const char* path) 744{ 745 struct node* node; 746 struct fuse_entry_out out; 747 struct stat s; 748 749 if (lstat(path, &s) < 0) { 750 /* But wait! We'll automatically create a directory if its 751 * a valid package name under data or obb, since apps may not 752 * have enough permissions to create for themselves. */ 753 if (errno == ENOENT && (parent->perm == PERM_ANDROID_DATA 754 || parent->perm == PERM_ANDROID_OBB)) { 755 TRACE("automatically creating %s\n", path); 756 757 pthread_mutex_lock(&fuse->lock); 758 bool validPackage = hashmapContainsKey(fuse->package_to_appid, (char*) name); 759 pthread_mutex_unlock(&fuse->lock); 760 761 if (!validPackage) { 762 return -ENOENT; 763 } 764 if (mkdir(path, 0775) == -1) { 765 /* We might have raced with ourselves and already created */ 766 if (errno != EEXIST) { 767 ERROR("failed to mkdir(%s): %s\n", name, strerror(errno)); 768 return -ENOENT; 769 } 770 } 771 772 /* It should exist this time around! */ 773 if (lstat(path, &s) < 0) { 774 ERROR("failed to lstat(%s): %s\n", name, strerror(errno)); 775 return -errno; 776 } 777 } else { 778 return -errno; 779 } 780 } 781 782 pthread_mutex_lock(&fuse->lock); 783 node = acquire_or_create_child_locked(fuse, parent, name, actual_name); 784 if (!node) { 785 pthread_mutex_unlock(&fuse->lock); 786 return -ENOMEM; 787 } 788 memset(&out, 0, sizeof(out)); 789 attr_from_stat(&out.attr, &s, node); 790 out.attr_valid = 10; 791 out.entry_valid = 10; 792 out.nodeid = node->nid; 793 out.generation = node->gen; 794 pthread_mutex_unlock(&fuse->lock); 795 fuse_reply(fuse, unique, &out, sizeof(out)); 796 return NO_STATUS; 797} 798 799static int fuse_reply_attr(struct fuse* fuse, __u64 unique, const struct node* node, 800 const char* path) 801{ 802 struct fuse_attr_out out; 803 struct stat s; 804 805 if (lstat(path, &s) < 0) { 806 return -errno; 807 } 808 memset(&out, 0, sizeof(out)); 809 attr_from_stat(&out.attr, &s, node); 810 out.attr_valid = 10; 811 fuse_reply(fuse, unique, &out, sizeof(out)); 812 return NO_STATUS; 813} 814 815static int handle_lookup(struct fuse* fuse, struct fuse_handler* handler, 816 const struct fuse_in_header *hdr, const char* name) 817{ 818 struct node* parent_node; 819 char parent_path[PATH_MAX]; 820 char child_path[PATH_MAX]; 821 const char* actual_name; 822 823 pthread_mutex_lock(&fuse->lock); 824 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 825 parent_path, sizeof(parent_path)); 826 TRACE("[%d] LOOKUP %s @ %llx (%s)\n", handler->token, name, hdr->nodeid, 827 parent_node ? parent_node->name : "?"); 828 pthread_mutex_unlock(&fuse->lock); 829 830 if (!parent_node || !(actual_name = find_file_within(parent_path, name, 831 child_path, sizeof(child_path), 1))) { 832 return -ENOENT; 833 } 834 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, R_OK, false)) { 835 return -EACCES; 836 } 837 838 return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); 839} 840 841static int handle_forget(struct fuse* fuse, struct fuse_handler* handler, 842 const struct fuse_in_header *hdr, const struct fuse_forget_in *req) 843{ 844 struct node* node; 845 846 pthread_mutex_lock(&fuse->lock); 847 node = lookup_node_by_id_locked(fuse, hdr->nodeid); 848 TRACE("[%d] FORGET #%lld @ %llx (%s)\n", handler->token, req->nlookup, 849 hdr->nodeid, node ? node->name : "?"); 850 if (node) { 851 __u64 n = req->nlookup; 852 while (n--) { 853 release_node_locked(node); 854 } 855 } 856 pthread_mutex_unlock(&fuse->lock); 857 return NO_STATUS; /* no reply */ 858} 859 860static int handle_getattr(struct fuse* fuse, struct fuse_handler* handler, 861 const struct fuse_in_header *hdr, const struct fuse_getattr_in *req) 862{ 863 struct node* node; 864 char path[PATH_MAX]; 865 866 pthread_mutex_lock(&fuse->lock); 867 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 868 TRACE("[%d] GETATTR flags=%x fh=%llx @ %llx (%s)\n", handler->token, 869 req->getattr_flags, req->fh, hdr->nodeid, node ? node->name : "?"); 870 pthread_mutex_unlock(&fuse->lock); 871 872 if (!node) { 873 return -ENOENT; 874 } 875 if (!check_caller_access_to_node(fuse, hdr, node, R_OK, false)) { 876 return -EACCES; 877 } 878 879 return fuse_reply_attr(fuse, hdr->unique, node, path); 880} 881 882static int handle_setattr(struct fuse* fuse, struct fuse_handler* handler, 883 const struct fuse_in_header *hdr, const struct fuse_setattr_in *req) 884{ 885 bool has_rw; 886 struct node* node; 887 char path[PATH_MAX]; 888 struct timespec times[2]; 889 890 pthread_mutex_lock(&fuse->lock); 891 has_rw = get_caller_has_rw_locked(fuse, hdr); 892 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 893 TRACE("[%d] SETATTR fh=%llx valid=%x @ %llx (%s)\n", handler->token, 894 req->fh, req->valid, hdr->nodeid, node ? node->name : "?"); 895 pthread_mutex_unlock(&fuse->lock); 896 897 if (!node) { 898 return -ENOENT; 899 } 900 if (!check_caller_access_to_node(fuse, hdr, node, W_OK, has_rw)) { 901 return -EACCES; 902 } 903 904 /* XXX: incomplete implementation on purpose. 905 * chmod/chown should NEVER be implemented.*/ 906 907 if ((req->valid & FATTR_SIZE) && truncate(path, req->size) < 0) { 908 return -errno; 909 } 910 911 /* Handle changing atime and mtime. If FATTR_ATIME_and FATTR_ATIME_NOW 912 * are both set, then set it to the current time. Else, set it to the 913 * time specified in the request. Same goes for mtime. Use utimensat(2) 914 * as it allows ATIME and MTIME to be changed independently, and has 915 * nanosecond resolution which fuse also has. 916 */ 917 if (req->valid & (FATTR_ATIME | FATTR_MTIME)) { 918 times[0].tv_nsec = UTIME_OMIT; 919 times[1].tv_nsec = UTIME_OMIT; 920 if (req->valid & FATTR_ATIME) { 921 if (req->valid & FATTR_ATIME_NOW) { 922 times[0].tv_nsec = UTIME_NOW; 923 } else { 924 times[0].tv_sec = req->atime; 925 times[0].tv_nsec = req->atimensec; 926 } 927 } 928 if (req->valid & FATTR_MTIME) { 929 if (req->valid & FATTR_MTIME_NOW) { 930 times[1].tv_nsec = UTIME_NOW; 931 } else { 932 times[1].tv_sec = req->mtime; 933 times[1].tv_nsec = req->mtimensec; 934 } 935 } 936 TRACE("[%d] Calling utimensat on %s with atime %ld, mtime=%ld\n", 937 handler->token, path, times[0].tv_sec, times[1].tv_sec); 938 if (utimensat(-1, path, times, 0) < 0) { 939 return -errno; 940 } 941 } 942 return fuse_reply_attr(fuse, hdr->unique, node, path); 943} 944 945static int handle_mknod(struct fuse* fuse, struct fuse_handler* handler, 946 const struct fuse_in_header* hdr, const struct fuse_mknod_in* req, const char* name) 947{ 948 bool has_rw; 949 struct node* parent_node; 950 char parent_path[PATH_MAX]; 951 char child_path[PATH_MAX]; 952 const char* actual_name; 953 954 pthread_mutex_lock(&fuse->lock); 955 has_rw = get_caller_has_rw_locked(fuse, hdr); 956 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 957 parent_path, sizeof(parent_path)); 958 TRACE("[%d] MKNOD %s 0%o @ %llx (%s)\n", handler->token, 959 name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?"); 960 pthread_mutex_unlock(&fuse->lock); 961 962 if (!parent_node || !(actual_name = find_file_within(parent_path, name, 963 child_path, sizeof(child_path), 1))) { 964 return -ENOENT; 965 } 966 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) { 967 return -EACCES; 968 } 969 __u32 mode = (req->mode & (~0777)) | 0664; 970 if (mknod(child_path, mode, req->rdev) < 0) { 971 return -errno; 972 } 973 return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); 974} 975 976static int handle_mkdir(struct fuse* fuse, struct fuse_handler* handler, 977 const struct fuse_in_header* hdr, const struct fuse_mkdir_in* req, const char* name) 978{ 979 bool has_rw; 980 struct node* parent_node; 981 char parent_path[PATH_MAX]; 982 char child_path[PATH_MAX]; 983 const char* actual_name; 984 985 pthread_mutex_lock(&fuse->lock); 986 has_rw = get_caller_has_rw_locked(fuse, hdr); 987 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 988 parent_path, sizeof(parent_path)); 989 TRACE("[%d] MKDIR %s 0%o @ %llx (%s)\n", handler->token, 990 name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?"); 991 pthread_mutex_unlock(&fuse->lock); 992 993 if (!parent_node || !(actual_name = find_file_within(parent_path, name, 994 child_path, sizeof(child_path), 1))) { 995 return -ENOENT; 996 } 997 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) { 998 return -EACCES; 999 } 1000 __u32 mode = (req->mode & (~0777)) | 0775; 1001 if (mkdir(child_path, mode) < 0) { 1002 return -errno; 1003 } 1004 return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); 1005} 1006 1007static int handle_unlink(struct fuse* fuse, struct fuse_handler* handler, 1008 const struct fuse_in_header* hdr, const char* name) 1009{ 1010 bool has_rw; 1011 struct node* parent_node; 1012 char parent_path[PATH_MAX]; 1013 char child_path[PATH_MAX]; 1014 1015 pthread_mutex_lock(&fuse->lock); 1016 has_rw = get_caller_has_rw_locked(fuse, hdr); 1017 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1018 parent_path, sizeof(parent_path)); 1019 TRACE("[%d] UNLINK %s @ %llx (%s)\n", handler->token, 1020 name, hdr->nodeid, parent_node ? parent_node->name : "?"); 1021 pthread_mutex_unlock(&fuse->lock); 1022 1023 if (!parent_node || !find_file_within(parent_path, name, 1024 child_path, sizeof(child_path), 1)) { 1025 return -ENOENT; 1026 } 1027 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) { 1028 return -EACCES; 1029 } 1030 if (unlink(child_path) < 0) { 1031 return -errno; 1032 } 1033 return 0; 1034} 1035 1036static int handle_rmdir(struct fuse* fuse, struct fuse_handler* handler, 1037 const struct fuse_in_header* hdr, const char* name) 1038{ 1039 bool has_rw; 1040 struct node* parent_node; 1041 char parent_path[PATH_MAX]; 1042 char child_path[PATH_MAX]; 1043 1044 pthread_mutex_lock(&fuse->lock); 1045 has_rw = get_caller_has_rw_locked(fuse, hdr); 1046 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1047 parent_path, sizeof(parent_path)); 1048 TRACE("[%d] RMDIR %s @ %llx (%s)\n", handler->token, 1049 name, hdr->nodeid, parent_node ? parent_node->name : "?"); 1050 pthread_mutex_unlock(&fuse->lock); 1051 1052 if (!parent_node || !find_file_within(parent_path, name, 1053 child_path, sizeof(child_path), 1)) { 1054 return -ENOENT; 1055 } 1056 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) { 1057 return -EACCES; 1058 } 1059 if (rmdir(child_path) < 0) { 1060 return -errno; 1061 } 1062 return 0; 1063} 1064 1065static int handle_rename(struct fuse* fuse, struct fuse_handler* handler, 1066 const struct fuse_in_header* hdr, const struct fuse_rename_in* req, 1067 const char* old_name, const char* new_name) 1068{ 1069 bool has_rw; 1070 struct node* old_parent_node; 1071 struct node* new_parent_node; 1072 struct node* child_node; 1073 char old_parent_path[PATH_MAX]; 1074 char new_parent_path[PATH_MAX]; 1075 char old_child_path[PATH_MAX]; 1076 char new_child_path[PATH_MAX]; 1077 const char* new_actual_name; 1078 int res; 1079 1080 pthread_mutex_lock(&fuse->lock); 1081 has_rw = get_caller_has_rw_locked(fuse, hdr); 1082 old_parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1083 old_parent_path, sizeof(old_parent_path)); 1084 new_parent_node = lookup_node_and_path_by_id_locked(fuse, req->newdir, 1085 new_parent_path, sizeof(new_parent_path)); 1086 TRACE("[%d] RENAME %s->%s @ %llx (%s) -> %llx (%s)\n", handler->token, 1087 old_name, new_name, 1088 hdr->nodeid, old_parent_node ? old_parent_node->name : "?", 1089 req->newdir, new_parent_node ? new_parent_node->name : "?"); 1090 if (!old_parent_node || !new_parent_node) { 1091 res = -ENOENT; 1092 goto lookup_error; 1093 } 1094 if (!check_caller_access_to_name(fuse, hdr, old_parent_node, old_name, W_OK, has_rw)) { 1095 res = -EACCES; 1096 goto lookup_error; 1097 } 1098 if (!check_caller_access_to_name(fuse, hdr, new_parent_node, new_name, W_OK, has_rw)) { 1099 res = -EACCES; 1100 goto lookup_error; 1101 } 1102 child_node = lookup_child_by_name_locked(old_parent_node, old_name); 1103 if (!child_node || get_node_path_locked(child_node, 1104 old_child_path, sizeof(old_child_path)) < 0) { 1105 res = -ENOENT; 1106 goto lookup_error; 1107 } 1108 acquire_node_locked(child_node); 1109 pthread_mutex_unlock(&fuse->lock); 1110 1111 /* Special case for renaming a file where destination is same path 1112 * differing only by case. In this case we don't want to look for a case 1113 * insensitive match. This allows commands like "mv foo FOO" to work as expected. 1114 */ 1115 int search = old_parent_node != new_parent_node 1116 || strcasecmp(old_name, new_name); 1117 if (!(new_actual_name = find_file_within(new_parent_path, new_name, 1118 new_child_path, sizeof(new_child_path), search))) { 1119 res = -ENOENT; 1120 goto io_error; 1121 } 1122 1123 TRACE("[%d] RENAME %s->%s\n", handler->token, old_child_path, new_child_path); 1124 res = rename(old_child_path, new_child_path); 1125 if (res < 0) { 1126 res = -errno; 1127 goto io_error; 1128 } 1129 1130 pthread_mutex_lock(&fuse->lock); 1131 res = rename_node_locked(child_node, new_name, new_actual_name); 1132 if (!res) { 1133 remove_node_from_parent_locked(child_node); 1134 add_node_to_parent_locked(child_node, new_parent_node); 1135 } 1136 goto done; 1137 1138io_error: 1139 pthread_mutex_lock(&fuse->lock); 1140done: 1141 release_node_locked(child_node); 1142lookup_error: 1143 pthread_mutex_unlock(&fuse->lock); 1144 return res; 1145} 1146 1147static int open_flags_to_access_mode(int open_flags) { 1148 if ((open_flags & O_ACCMODE) == O_RDONLY) { 1149 return R_OK; 1150 } else if ((open_flags & O_ACCMODE) == O_WRONLY) { 1151 return W_OK; 1152 } else { 1153 /* Probably O_RDRW, but treat as default to be safe */ 1154 return R_OK | W_OK; 1155 } 1156} 1157 1158static int handle_open(struct fuse* fuse, struct fuse_handler* handler, 1159 const struct fuse_in_header* hdr, const struct fuse_open_in* req) 1160{ 1161 bool has_rw; 1162 struct node* node; 1163 char path[PATH_MAX]; 1164 struct fuse_open_out out; 1165 struct handle *h; 1166 1167 pthread_mutex_lock(&fuse->lock); 1168 has_rw = get_caller_has_rw_locked(fuse, hdr); 1169 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 1170 TRACE("[%d] OPEN 0%o @ %llx (%s)\n", handler->token, 1171 req->flags, hdr->nodeid, node ? node->name : "?"); 1172 pthread_mutex_unlock(&fuse->lock); 1173 1174 if (!node) { 1175 return -ENOENT; 1176 } 1177 if (!check_caller_access_to_node(fuse, hdr, node, 1178 open_flags_to_access_mode(req->flags), has_rw)) { 1179 return -EACCES; 1180 } 1181 h = malloc(sizeof(*h)); 1182 if (!h) { 1183 return -ENOMEM; 1184 } 1185 TRACE("[%d] OPEN %s\n", handler->token, path); 1186 h->fd = open(path, req->flags); 1187 if (h->fd < 0) { 1188 free(h); 1189 return -errno; 1190 } 1191 out.fh = ptr_to_id(h); 1192 out.open_flags = 0; 1193 out.padding = 0; 1194 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1195 return NO_STATUS; 1196} 1197 1198static int handle_read(struct fuse* fuse, struct fuse_handler* handler, 1199 const struct fuse_in_header* hdr, const struct fuse_read_in* req) 1200{ 1201 struct handle *h = id_to_ptr(req->fh); 1202 __u64 unique = hdr->unique; 1203 __u32 size = req->size; 1204 __u64 offset = req->offset; 1205 int res; 1206 1207 /* Don't access any other fields of hdr or req beyond this point, the read buffer 1208 * overlaps the request buffer and will clobber data in the request. This 1209 * saves us 128KB per request handler thread at the cost of this scary comment. */ 1210 1211 TRACE("[%d] READ %p(%d) %u@%llu\n", handler->token, 1212 h, h->fd, size, offset); 1213 if (size > sizeof(handler->read_buffer)) { 1214 return -EINVAL; 1215 } 1216 res = pread64(h->fd, handler->read_buffer, size, offset); 1217 if (res < 0) { 1218 return -errno; 1219 } 1220 fuse_reply(fuse, unique, handler->read_buffer, res); 1221 return NO_STATUS; 1222} 1223 1224static int handle_write(struct fuse* fuse, struct fuse_handler* handler, 1225 const struct fuse_in_header* hdr, const struct fuse_write_in* req, 1226 const void* buffer) 1227{ 1228 struct fuse_write_out out; 1229 struct handle *h = id_to_ptr(req->fh); 1230 int res; 1231 1232 TRACE("[%d] WRITE %p(%d) %u@%llu\n", handler->token, 1233 h, h->fd, req->size, req->offset); 1234 res = pwrite64(h->fd, buffer, req->size, req->offset); 1235 if (res < 0) { 1236 return -errno; 1237 } 1238 out.size = res; 1239 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1240 return NO_STATUS; 1241} 1242 1243static int handle_statfs(struct fuse* fuse, struct fuse_handler* handler, 1244 const struct fuse_in_header* hdr) 1245{ 1246 char path[PATH_MAX]; 1247 struct statfs stat; 1248 struct fuse_statfs_out out; 1249 int res; 1250 1251 pthread_mutex_lock(&fuse->lock); 1252 TRACE("[%d] STATFS\n", handler->token); 1253 res = get_node_path_locked(&fuse->root, path, sizeof(path)); 1254 pthread_mutex_unlock(&fuse->lock); 1255 if (res < 0) { 1256 return -ENOENT; 1257 } 1258 if (statfs(fuse->root.name, &stat) < 0) { 1259 return -errno; 1260 } 1261 memset(&out, 0, sizeof(out)); 1262 out.st.blocks = stat.f_blocks; 1263 out.st.bfree = stat.f_bfree; 1264 out.st.bavail = stat.f_bavail; 1265 out.st.files = stat.f_files; 1266 out.st.ffree = stat.f_ffree; 1267 out.st.bsize = stat.f_bsize; 1268 out.st.namelen = stat.f_namelen; 1269 out.st.frsize = stat.f_frsize; 1270 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1271 return NO_STATUS; 1272} 1273 1274static int handle_release(struct fuse* fuse, struct fuse_handler* handler, 1275 const struct fuse_in_header* hdr, const struct fuse_release_in* req) 1276{ 1277 struct handle *h = id_to_ptr(req->fh); 1278 1279 TRACE("[%d] RELEASE %p(%d)\n", handler->token, h, h->fd); 1280 close(h->fd); 1281 free(h); 1282 return 0; 1283} 1284 1285static int handle_fsync(struct fuse* fuse, struct fuse_handler* handler, 1286 const struct fuse_in_header* hdr, const struct fuse_fsync_in* req) 1287{ 1288 int is_data_sync = req->fsync_flags & 1; 1289 struct handle *h = id_to_ptr(req->fh); 1290 int res; 1291 1292 TRACE("[%d] FSYNC %p(%d) is_data_sync=%d\n", handler->token, 1293 h, h->fd, is_data_sync); 1294 res = is_data_sync ? fdatasync(h->fd) : fsync(h->fd); 1295 if (res < 0) { 1296 return -errno; 1297 } 1298 return 0; 1299} 1300 1301static int handle_flush(struct fuse* fuse, struct fuse_handler* handler, 1302 const struct fuse_in_header* hdr) 1303{ 1304 TRACE("[%d] FLUSH\n", handler->token); 1305 return 0; 1306} 1307 1308static int handle_opendir(struct fuse* fuse, struct fuse_handler* handler, 1309 const struct fuse_in_header* hdr, const struct fuse_open_in* req) 1310{ 1311 struct node* node; 1312 char path[PATH_MAX]; 1313 struct fuse_open_out out; 1314 struct dirhandle *h; 1315 1316 pthread_mutex_lock(&fuse->lock); 1317 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 1318 TRACE("[%d] OPENDIR @ %llx (%s)\n", handler->token, 1319 hdr->nodeid, node ? node->name : "?"); 1320 pthread_mutex_unlock(&fuse->lock); 1321 1322 if (!node) { 1323 return -ENOENT; 1324 } 1325 if (!check_caller_access_to_node(fuse, hdr, node, R_OK, false)) { 1326 return -EACCES; 1327 } 1328 h = malloc(sizeof(*h)); 1329 if (!h) { 1330 return -ENOMEM; 1331 } 1332 TRACE("[%d] OPENDIR %s\n", handler->token, path); 1333 h->d = opendir(path); 1334 if (!h->d) { 1335 free(h); 1336 return -errno; 1337 } 1338 out.fh = ptr_to_id(h); 1339 out.open_flags = 0; 1340 out.padding = 0; 1341 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1342 return NO_STATUS; 1343} 1344 1345static int handle_readdir(struct fuse* fuse, struct fuse_handler* handler, 1346 const struct fuse_in_header* hdr, const struct fuse_read_in* req) 1347{ 1348 char buffer[8192]; 1349 struct fuse_dirent *fde = (struct fuse_dirent*) buffer; 1350 struct dirent *de; 1351 struct dirhandle *h = id_to_ptr(req->fh); 1352 1353 TRACE("[%d] READDIR %p\n", handler->token, h); 1354 if (req->offset == 0) { 1355 /* rewinddir() might have been called above us, so rewind here too */ 1356 TRACE("[%d] calling rewinddir()\n", handler->token); 1357 rewinddir(h->d); 1358 } 1359 de = readdir(h->d); 1360 if (!de) { 1361 return 0; 1362 } 1363 fde->ino = FUSE_UNKNOWN_INO; 1364 /* increment the offset so we can detect when rewinddir() seeks back to the beginning */ 1365 fde->off = req->offset + 1; 1366 fde->type = de->d_type; 1367 fde->namelen = strlen(de->d_name); 1368 memcpy(fde->name, de->d_name, fde->namelen + 1); 1369 fuse_reply(fuse, hdr->unique, fde, 1370 FUSE_DIRENT_ALIGN(sizeof(struct fuse_dirent) + fde->namelen)); 1371 return NO_STATUS; 1372} 1373 1374static int handle_releasedir(struct fuse* fuse, struct fuse_handler* handler, 1375 const struct fuse_in_header* hdr, const struct fuse_release_in* req) 1376{ 1377 struct dirhandle *h = id_to_ptr(req->fh); 1378 1379 TRACE("[%d] RELEASEDIR %p\n", handler->token, h); 1380 closedir(h->d); 1381 free(h); 1382 return 0; 1383} 1384 1385static int handle_init(struct fuse* fuse, struct fuse_handler* handler, 1386 const struct fuse_in_header* hdr, const struct fuse_init_in* req) 1387{ 1388 struct fuse_init_out out; 1389 1390 TRACE("[%d] INIT ver=%d.%d maxread=%d flags=%x\n", 1391 handler->token, req->major, req->minor, req->max_readahead, req->flags); 1392 out.major = FUSE_KERNEL_VERSION; 1393 out.minor = FUSE_KERNEL_MINOR_VERSION; 1394 out.max_readahead = req->max_readahead; 1395 out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; 1396 out.max_background = 32; 1397 out.congestion_threshold = 32; 1398 out.max_write = MAX_WRITE; 1399 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1400 return NO_STATUS; 1401} 1402 1403static int handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler, 1404 const struct fuse_in_header *hdr, const void *data, size_t data_len) 1405{ 1406 switch (hdr->opcode) { 1407 case FUSE_LOOKUP: { /* bytez[] -> entry_out */ 1408 const char* name = data; 1409 return handle_lookup(fuse, handler, hdr, name); 1410 } 1411 1412 case FUSE_FORGET: { 1413 const struct fuse_forget_in *req = data; 1414 return handle_forget(fuse, handler, hdr, req); 1415 } 1416 1417 case FUSE_GETATTR: { /* getattr_in -> attr_out */ 1418 const struct fuse_getattr_in *req = data; 1419 return handle_getattr(fuse, handler, hdr, req); 1420 } 1421 1422 case FUSE_SETATTR: { /* setattr_in -> attr_out */ 1423 const struct fuse_setattr_in *req = data; 1424 return handle_setattr(fuse, handler, hdr, req); 1425 } 1426 1427// case FUSE_READLINK: 1428// case FUSE_SYMLINK: 1429 case FUSE_MKNOD: { /* mknod_in, bytez[] -> entry_out */ 1430 const struct fuse_mknod_in *req = data; 1431 const char *name = ((const char*) data) + sizeof(*req); 1432 return handle_mknod(fuse, handler, hdr, req, name); 1433 } 1434 1435 case FUSE_MKDIR: { /* mkdir_in, bytez[] -> entry_out */ 1436 const struct fuse_mkdir_in *req = data; 1437 const char *name = ((const char*) data) + sizeof(*req); 1438 return handle_mkdir(fuse, handler, hdr, req, name); 1439 } 1440 1441 case FUSE_UNLINK: { /* bytez[] -> */ 1442 const char* name = data; 1443 return handle_unlink(fuse, handler, hdr, name); 1444 } 1445 1446 case FUSE_RMDIR: { /* bytez[] -> */ 1447 const char* name = data; 1448 return handle_rmdir(fuse, handler, hdr, name); 1449 } 1450 1451 case FUSE_RENAME: { /* rename_in, oldname, newname -> */ 1452 const struct fuse_rename_in *req = data; 1453 const char *old_name = ((const char*) data) + sizeof(*req); 1454 const char *new_name = old_name + strlen(old_name) + 1; 1455 return handle_rename(fuse, handler, hdr, req, old_name, new_name); 1456 } 1457 1458// case FUSE_LINK: 1459 case FUSE_OPEN: { /* open_in -> open_out */ 1460 const struct fuse_open_in *req = data; 1461 return handle_open(fuse, handler, hdr, req); 1462 } 1463 1464 case FUSE_READ: { /* read_in -> byte[] */ 1465 const struct fuse_read_in *req = data; 1466 return handle_read(fuse, handler, hdr, req); 1467 } 1468 1469 case FUSE_WRITE: { /* write_in, byte[write_in.size] -> write_out */ 1470 const struct fuse_write_in *req = data; 1471 const void* buffer = (const __u8*)data + sizeof(*req); 1472 return handle_write(fuse, handler, hdr, req, buffer); 1473 } 1474 1475 case FUSE_STATFS: { /* getattr_in -> attr_out */ 1476 return handle_statfs(fuse, handler, hdr); 1477 } 1478 1479 case FUSE_RELEASE: { /* release_in -> */ 1480 const struct fuse_release_in *req = data; 1481 return handle_release(fuse, handler, hdr, req); 1482 } 1483 1484 case FUSE_FSYNC: { 1485 const struct fuse_fsync_in *req = data; 1486 return handle_fsync(fuse, handler, hdr, req); 1487 } 1488 1489// case FUSE_SETXATTR: 1490// case FUSE_GETXATTR: 1491// case FUSE_LISTXATTR: 1492// case FUSE_REMOVEXATTR: 1493 case FUSE_FLUSH: { 1494 return handle_flush(fuse, handler, hdr); 1495 } 1496 1497 case FUSE_OPENDIR: { /* open_in -> open_out */ 1498 const struct fuse_open_in *req = data; 1499 return handle_opendir(fuse, handler, hdr, req); 1500 } 1501 1502 case FUSE_READDIR: { 1503 const struct fuse_read_in *req = data; 1504 return handle_readdir(fuse, handler, hdr, req); 1505 } 1506 1507 case FUSE_RELEASEDIR: { /* release_in -> */ 1508 const struct fuse_release_in *req = data; 1509 return handle_releasedir(fuse, handler, hdr, req); 1510 } 1511 1512// case FUSE_FSYNCDIR: 1513 case FUSE_INIT: { /* init_in -> init_out */ 1514 const struct fuse_init_in *req = data; 1515 return handle_init(fuse, handler, hdr, req); 1516 } 1517 1518 default: { 1519 TRACE("[%d] NOTIMPL op=%d uniq=%llx nid=%llx\n", 1520 handler->token, hdr->opcode, hdr->unique, hdr->nodeid); 1521 return -ENOSYS; 1522 } 1523 } 1524} 1525 1526static void handle_fuse_requests(struct fuse_handler* handler) 1527{ 1528 struct fuse* fuse = handler->fuse; 1529 for (;;) { 1530 ssize_t len = read(fuse->fd, 1531 handler->request_buffer, sizeof(handler->request_buffer)); 1532 if (len < 0) { 1533 if (errno != EINTR) { 1534 ERROR("[%d] handle_fuse_requests: errno=%d\n", handler->token, errno); 1535 } 1536 continue; 1537 } 1538 1539 if ((size_t)len < sizeof(struct fuse_in_header)) { 1540 ERROR("[%d] request too short: len=%zu\n", handler->token, (size_t)len); 1541 continue; 1542 } 1543 1544 const struct fuse_in_header *hdr = (void*)handler->request_buffer; 1545 if (hdr->len != (size_t)len) { 1546 ERROR("[%d] malformed header: len=%zu, hdr->len=%u\n", 1547 handler->token, (size_t)len, hdr->len); 1548 continue; 1549 } 1550 1551 const void *data = handler->request_buffer + sizeof(struct fuse_in_header); 1552 size_t data_len = len - sizeof(struct fuse_in_header); 1553 __u64 unique = hdr->unique; 1554 int res = handle_fuse_request(fuse, handler, hdr, data, data_len); 1555 1556 /* We do not access the request again after this point because the underlying 1557 * buffer storage may have been reused while processing the request. */ 1558 1559 if (res != NO_STATUS) { 1560 if (res) { 1561 TRACE("[%d] ERROR %d\n", handler->token, res); 1562 } 1563 fuse_status(fuse, unique, res); 1564 } 1565 } 1566} 1567 1568static void* start_handler(void* data) 1569{ 1570 struct fuse_handler* handler = data; 1571 handle_fuse_requests(handler); 1572 return NULL; 1573} 1574 1575static bool remove_str_to_int(void *key, void *value, void *context) { 1576 Hashmap* map = context; 1577 hashmapRemove(map, key); 1578 free(key); 1579 return true; 1580} 1581 1582static bool remove_int_to_null(void *key, void *value, void *context) { 1583 Hashmap* map = context; 1584 hashmapRemove(map, key); 1585 return true; 1586} 1587 1588static int read_package_list(struct fuse *fuse) { 1589 pthread_mutex_lock(&fuse->lock); 1590 1591 hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid); 1592 hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw); 1593 1594 FILE* file = fopen(kPackagesListFile, "r"); 1595 if (!file) { 1596 ERROR("failed to open package list: %s\n", strerror(errno)); 1597 pthread_mutex_unlock(&fuse->lock); 1598 return -1; 1599 } 1600 1601 char buf[512]; 1602 while (fgets(buf, sizeof(buf), file) != NULL) { 1603 char package_name[512]; 1604 int appid; 1605 char gids[512]; 1606 1607 if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) { 1608 char* package_name_dup = strdup(package_name); 1609 hashmapPut(fuse->package_to_appid, package_name_dup, (void*) appid); 1610 1611 char* token = strtok(gids, ","); 1612 while (token != NULL) { 1613 if (strtoul(token, NULL, 10) == AID_SDCARD_RW) { 1614 hashmapPut(fuse->appid_with_rw, (void*) appid, (void*) 1); 1615 break; 1616 } 1617 token = strtok(NULL, ","); 1618 } 1619 } 1620 } 1621 1622 TRACE("read_package_list: found %d packages, %d with sdcard_rw\n", 1623 hashmapSize(fuse->package_to_appid), 1624 hashmapSize(fuse->appid_with_rw)); 1625 fclose(file); 1626 pthread_mutex_unlock(&fuse->lock); 1627 return 0; 1628} 1629 1630static void watch_package_list(struct fuse* fuse) { 1631 struct inotify_event *event; 1632 char event_buf[512]; 1633 1634 int nfd = inotify_init(); 1635 if (nfd < 0) { 1636 ERROR("inotify_init failed: %s\n", strerror(errno)); 1637 return; 1638 } 1639 1640 bool active = false; 1641 while (1) { 1642 if (!active) { 1643 int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF); 1644 if (res == -1) { 1645 if (errno == ENOENT || errno == EACCES) { 1646 /* Framework may not have created yet, sleep and retry */ 1647 ERROR("missing packages.list; retrying\n"); 1648 sleep(3); 1649 continue; 1650 } else { 1651 ERROR("inotify_add_watch failed: %s\n", strerror(errno)); 1652 return; 1653 } 1654 } 1655 1656 /* Watch above will tell us about any future changes, so 1657 * read the current state. */ 1658 if (read_package_list(fuse) == -1) { 1659 ERROR("read_package_list failed: %s\n", strerror(errno)); 1660 return; 1661 } 1662 active = true; 1663 } 1664 1665 int event_pos = 0; 1666 int res = read(nfd, event_buf, sizeof(event_buf)); 1667 if (res < (int) sizeof(*event)) { 1668 if (errno == EINTR) 1669 continue; 1670 ERROR("failed to read inotify event: %s\n", strerror(errno)); 1671 return; 1672 } 1673 1674 while (res >= (int) sizeof(*event)) { 1675 int event_size; 1676 event = (struct inotify_event *) (event_buf + event_pos); 1677 1678 TRACE("inotify event: %08x\n", event->mask); 1679 if ((event->mask & IN_IGNORED) == IN_IGNORED) { 1680 /* Previously watched file was deleted, probably due to move 1681 * that swapped in new data; re-arm the watch and read. */ 1682 active = false; 1683 } 1684 1685 event_size = sizeof(*event) + event->len; 1686 res -= event_size; 1687 event_pos += event_size; 1688 } 1689 } 1690} 1691 1692static int ignite_fuse(struct fuse* fuse, int num_threads) 1693{ 1694 struct fuse_handler* handlers; 1695 int i; 1696 1697 handlers = malloc(num_threads * sizeof(struct fuse_handler)); 1698 if (!handlers) { 1699 ERROR("cannot allocate storage for threads\n"); 1700 return -ENOMEM; 1701 } 1702 1703 for (i = 0; i < num_threads; i++) { 1704 handlers[i].fuse = fuse; 1705 handlers[i].token = i; 1706 } 1707 1708 /* When deriving permissions, this thread is used to process inotify events, 1709 * otherwise it becomes one of the FUSE handlers. */ 1710 i = (fuse->derive == DERIVE_NONE) ? 1 : 0; 1711 for (; i < num_threads; i++) { 1712 pthread_t thread; 1713 int res = pthread_create(&thread, NULL, start_handler, &handlers[i]); 1714 if (res) { 1715 ERROR("failed to start thread #%d, error=%d\n", i, res); 1716 goto quit; 1717 } 1718 } 1719 1720 if (fuse->derive == DERIVE_NONE) { 1721 handle_fuse_requests(&handlers[0]); 1722 } else { 1723 watch_package_list(fuse); 1724 } 1725 1726 ERROR("terminated prematurely\n"); 1727 1728 /* don't bother killing all of the other threads or freeing anything, 1729 * should never get here anyhow */ 1730quit: 1731 exit(1); 1732} 1733 1734static int usage() 1735{ 1736 ERROR("usage: sdcard [OPTIONS] <source_path> <dest_path>\n" 1737 " -u: specify UID to run as\n" 1738 " -g: specify GID to run as\n" 1739 " -G: specify default GID for files (default sdcard_r, requires -d or -l)\n" 1740 " -t: specify number of threads to use (default %d)\n" 1741 " -d: derive file permissions based on path\n" 1742 " -l: derive file permissions based on legacy internal layout\n" 1743 " -s: split derived permissions for pics, av\n" 1744 "\n", DEFAULT_NUM_THREADS); 1745 return 1; 1746} 1747 1748static int run(const char* source_path, const char* dest_path, uid_t uid, 1749 gid_t gid, gid_t fs_gid, int num_threads, derive_t derive, bool split_perms) { 1750 int fd; 1751 char opts[256]; 1752 int res; 1753 struct fuse fuse; 1754 1755 /* cleanup from previous instance, if necessary */ 1756 umount2(dest_path, 2); 1757 1758 fd = open("/dev/fuse", O_RDWR); 1759 if (fd < 0){ 1760 ERROR("cannot open fuse device: %s\n", strerror(errno)); 1761 return -1; 1762 } 1763 1764 snprintf(opts, sizeof(opts), 1765 "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", 1766 fd, uid, gid); 1767 1768 res = mount("/dev/fuse", dest_path, "fuse", MS_NOSUID | MS_NODEV, opts); 1769 if (res < 0) { 1770 ERROR("cannot mount fuse filesystem: %s\n", strerror(errno)); 1771 goto error; 1772 } 1773 1774 res = setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups); 1775 if (res < 0) { 1776 ERROR("cannot setgroups: %s\n", strerror(errno)); 1777 goto error; 1778 } 1779 1780 res = setgid(gid); 1781 if (res < 0) { 1782 ERROR("cannot setgid: %s\n", strerror(errno)); 1783 goto error; 1784 } 1785 1786 res = setuid(uid); 1787 if (res < 0) { 1788 ERROR("cannot setuid: %s\n", strerror(errno)); 1789 goto error; 1790 } 1791 1792 fuse_init(&fuse, fd, source_path, fs_gid, derive, split_perms); 1793 1794 umask(0); 1795 res = ignite_fuse(&fuse, num_threads); 1796 1797 /* we do not attempt to umount the file system here because we are no longer 1798 * running as the root user */ 1799 1800error: 1801 close(fd); 1802 return res; 1803} 1804 1805int main(int argc, char **argv) 1806{ 1807 int res; 1808 const char *source_path = NULL; 1809 const char *dest_path = NULL; 1810 uid_t uid = 0; 1811 gid_t gid = 0; 1812 gid_t fs_gid = AID_SDCARD_R; 1813 int num_threads = DEFAULT_NUM_THREADS; 1814 derive_t derive = DERIVE_NONE; 1815 bool split_perms = false; 1816 int i; 1817 struct rlimit rlim; 1818 1819 int opt; 1820 while ((opt = getopt(argc, argv, "u:g:G:t:dls")) != -1) { 1821 switch (opt) { 1822 case 'u': 1823 uid = strtoul(optarg, NULL, 10); 1824 break; 1825 case 'g': 1826 gid = strtoul(optarg, NULL, 10); 1827 break; 1828 case 'G': 1829 fs_gid = strtoul(optarg, NULL, 10); 1830 break; 1831 case 't': 1832 num_threads = strtoul(optarg, NULL, 10); 1833 break; 1834 case 'd': 1835 derive = DERIVE_UNIFIED; 1836 break; 1837 case 'l': 1838 derive = DERIVE_LEGACY; 1839 break; 1840 case 's': 1841 split_perms = true; 1842 break; 1843 case '?': 1844 default: 1845 return usage(); 1846 } 1847 } 1848 1849 for (i = optind; i < argc; i++) { 1850 char* arg = argv[i]; 1851 if (!source_path) { 1852 source_path = arg; 1853 } else if (!dest_path) { 1854 dest_path = arg; 1855 } else if (!uid) { 1856 uid = strtoul(arg, NULL, 10); 1857 } else if (!gid) { 1858 gid = strtoul(arg, NULL, 10); 1859 } else { 1860 ERROR("too many arguments\n"); 1861 return usage(); 1862 } 1863 } 1864 1865 if (!source_path) { 1866 ERROR("no source path specified\n"); 1867 return usage(); 1868 } 1869 if (!dest_path) { 1870 ERROR("no dest path specified\n"); 1871 return usage(); 1872 } 1873 if (!uid || !gid) { 1874 ERROR("uid and gid must be nonzero\n"); 1875 return usage(); 1876 } 1877 if (num_threads < 1) { 1878 ERROR("number of threads must be at least 1\n"); 1879 return usage(); 1880 } 1881 if (split_perms && derive == DERIVE_NONE) { 1882 ERROR("cannot split permissions without deriving\n"); 1883 return usage(); 1884 } 1885 1886 rlim.rlim_cur = 8192; 1887 rlim.rlim_max = 8192; 1888 if (setrlimit(RLIMIT_NOFILE, &rlim)) { 1889 ERROR("Error setting RLIMIT_NOFILE, errno = %d\n", errno); 1890 } 1891 1892 res = run(source_path, dest_path, uid, gid, fs_gid, num_threads, derive, split_perms); 1893 return res < 0 ? 1 : 0; 1894} 1895