sdcard.c revision 977a9f3b1a05e6168e8245a1e2061225b68b2b41
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/* Kernel has already enforced everything we returned through 490 * derive_permissions_locked(), so this is used to lock down access 491 * even further, such as enforcing that apps hold sdcard_rw. */ 492static bool check_caller_access_to_name(struct fuse* fuse, 493 const struct fuse_in_header *hdr, const struct node* parent_node, 494 const char* name, int mode) { 495 /* Always block security-sensitive files at root */ 496 if (parent_node && parent_node->perm == PERM_ROOT) { 497 if (!strcmp(name, "autorun.inf") 498 || !strcmp(name, ".android_secure") 499 || !strcmp(name, "android_secure")) { 500 return false; 501 } 502 } 503 504 /* No additional permissions enforcement */ 505 if (fuse->derive == DERIVE_NONE) { 506 return true; 507 } 508 509 /* Root or shell always have access */ 510 if (hdr->uid == 0 || hdr->uid == AID_SHELL) { 511 return true; 512 } 513 514 /* If asking to write, verify that caller either owns the 515 * parent or holds sdcard_rw. */ 516 if (mode & W_OK) { 517 if (parent_node && hdr->uid == parent_node->uid) { 518 return true; 519 } 520 521 appid_t appid = multiuser_get_app_id(hdr->uid); 522 523 pthread_mutex_lock(&fuse->lock); 524 bool hasRw = hashmapContainsKey(fuse->appid_with_rw, (void*) appid); 525 pthread_mutex_unlock(&fuse->lock); 526 527 return hasRw; 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) { 536 return check_caller_access_to_name(fuse, hdr, node->parent, node->name, mode); 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)) { 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)) { 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 struct node* node; 886 char path[PATH_MAX]; 887 struct timespec times[2]; 888 889 pthread_mutex_lock(&fuse->lock); 890 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 891 TRACE("[%d] SETATTR fh=%llx valid=%x @ %llx (%s)\n", handler->token, 892 req->fh, req->valid, hdr->nodeid, node ? node->name : "?"); 893 pthread_mutex_unlock(&fuse->lock); 894 895 if (!node) { 896 return -ENOENT; 897 } 898 if (!check_caller_access_to_node(fuse, hdr, node, W_OK)) { 899 return -EACCES; 900 } 901 902 /* XXX: incomplete implementation on purpose. 903 * chmod/chown should NEVER be implemented.*/ 904 905 if ((req->valid & FATTR_SIZE) && truncate(path, req->size) < 0) { 906 return -errno; 907 } 908 909 /* Handle changing atime and mtime. If FATTR_ATIME_and FATTR_ATIME_NOW 910 * are both set, then set it to the current time. Else, set it to the 911 * time specified in the request. Same goes for mtime. Use utimensat(2) 912 * as it allows ATIME and MTIME to be changed independently, and has 913 * nanosecond resolution which fuse also has. 914 */ 915 if (req->valid & (FATTR_ATIME | FATTR_MTIME)) { 916 times[0].tv_nsec = UTIME_OMIT; 917 times[1].tv_nsec = UTIME_OMIT; 918 if (req->valid & FATTR_ATIME) { 919 if (req->valid & FATTR_ATIME_NOW) { 920 times[0].tv_nsec = UTIME_NOW; 921 } else { 922 times[0].tv_sec = req->atime; 923 times[0].tv_nsec = req->atimensec; 924 } 925 } 926 if (req->valid & FATTR_MTIME) { 927 if (req->valid & FATTR_MTIME_NOW) { 928 times[1].tv_nsec = UTIME_NOW; 929 } else { 930 times[1].tv_sec = req->mtime; 931 times[1].tv_nsec = req->mtimensec; 932 } 933 } 934 TRACE("[%d] Calling utimensat on %s with atime %ld, mtime=%ld\n", 935 handler->token, path, times[0].tv_sec, times[1].tv_sec); 936 if (utimensat(-1, path, times, 0) < 0) { 937 return -errno; 938 } 939 } 940 return fuse_reply_attr(fuse, hdr->unique, node, path); 941} 942 943static int handle_mknod(struct fuse* fuse, struct fuse_handler* handler, 944 const struct fuse_in_header* hdr, const struct fuse_mknod_in* req, const char* name) 945{ 946 struct node* parent_node; 947 char parent_path[PATH_MAX]; 948 char child_path[PATH_MAX]; 949 const char* actual_name; 950 951 pthread_mutex_lock(&fuse->lock); 952 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 953 parent_path, sizeof(parent_path)); 954 TRACE("[%d] MKNOD %s 0%o @ %llx (%s)\n", handler->token, 955 name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?"); 956 pthread_mutex_unlock(&fuse->lock); 957 958 if (!parent_node || !(actual_name = find_file_within(parent_path, name, 959 child_path, sizeof(child_path), 1))) { 960 return -ENOENT; 961 } 962 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) { 963 return -EACCES; 964 } 965 __u32 mode = (req->mode & (~0777)) | 0664; 966 if (mknod(child_path, mode, req->rdev) < 0) { 967 return -errno; 968 } 969 return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); 970} 971 972static int handle_mkdir(struct fuse* fuse, struct fuse_handler* handler, 973 const struct fuse_in_header* hdr, const struct fuse_mkdir_in* req, const char* name) 974{ 975 struct node* parent_node; 976 char parent_path[PATH_MAX]; 977 char child_path[PATH_MAX]; 978 const char* actual_name; 979 980 pthread_mutex_lock(&fuse->lock); 981 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 982 parent_path, sizeof(parent_path)); 983 TRACE("[%d] MKDIR %s 0%o @ %llx (%s)\n", handler->token, 984 name, req->mode, hdr->nodeid, parent_node ? parent_node->name : "?"); 985 pthread_mutex_unlock(&fuse->lock); 986 987 if (!parent_node || !(actual_name = find_file_within(parent_path, name, 988 child_path, sizeof(child_path), 1))) { 989 return -ENOENT; 990 } 991 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) { 992 return -EACCES; 993 } 994 __u32 mode = (req->mode & (~0777)) | 0775; 995 if (mkdir(child_path, mode) < 0) { 996 return -errno; 997 } 998 return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path); 999} 1000 1001static int handle_unlink(struct fuse* fuse, struct fuse_handler* handler, 1002 const struct fuse_in_header* hdr, const char* name) 1003{ 1004 struct node* parent_node; 1005 char parent_path[PATH_MAX]; 1006 char child_path[PATH_MAX]; 1007 1008 pthread_mutex_lock(&fuse->lock); 1009 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1010 parent_path, sizeof(parent_path)); 1011 TRACE("[%d] UNLINK %s @ %llx (%s)\n", handler->token, 1012 name, hdr->nodeid, parent_node ? parent_node->name : "?"); 1013 pthread_mutex_unlock(&fuse->lock); 1014 1015 if (!parent_node || !find_file_within(parent_path, name, 1016 child_path, sizeof(child_path), 1)) { 1017 return -ENOENT; 1018 } 1019 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) { 1020 return -EACCES; 1021 } 1022 if (unlink(child_path) < 0) { 1023 return -errno; 1024 } 1025 return 0; 1026} 1027 1028static int handle_rmdir(struct fuse* fuse, struct fuse_handler* handler, 1029 const struct fuse_in_header* hdr, const char* name) 1030{ 1031 struct node* parent_node; 1032 char parent_path[PATH_MAX]; 1033 char child_path[PATH_MAX]; 1034 1035 pthread_mutex_lock(&fuse->lock); 1036 parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1037 parent_path, sizeof(parent_path)); 1038 TRACE("[%d] RMDIR %s @ %llx (%s)\n", handler->token, 1039 name, hdr->nodeid, parent_node ? parent_node->name : "?"); 1040 pthread_mutex_unlock(&fuse->lock); 1041 1042 if (!parent_node || !find_file_within(parent_path, name, 1043 child_path, sizeof(child_path), 1)) { 1044 return -ENOENT; 1045 } 1046 if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) { 1047 return -EACCES; 1048 } 1049 if (rmdir(child_path) < 0) { 1050 return -errno; 1051 } 1052 return 0; 1053} 1054 1055static int handle_rename(struct fuse* fuse, struct fuse_handler* handler, 1056 const struct fuse_in_header* hdr, const struct fuse_rename_in* req, 1057 const char* old_name, const char* new_name) 1058{ 1059 struct node* old_parent_node; 1060 struct node* new_parent_node; 1061 struct node* child_node; 1062 char old_parent_path[PATH_MAX]; 1063 char new_parent_path[PATH_MAX]; 1064 char old_child_path[PATH_MAX]; 1065 char new_child_path[PATH_MAX]; 1066 const char* new_actual_name; 1067 int res; 1068 1069 pthread_mutex_lock(&fuse->lock); 1070 old_parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, 1071 old_parent_path, sizeof(old_parent_path)); 1072 new_parent_node = lookup_node_and_path_by_id_locked(fuse, req->newdir, 1073 new_parent_path, sizeof(new_parent_path)); 1074 TRACE("[%d] RENAME %s->%s @ %llx (%s) -> %llx (%s)\n", handler->token, 1075 old_name, new_name, 1076 hdr->nodeid, old_parent_node ? old_parent_node->name : "?", 1077 req->newdir, new_parent_node ? new_parent_node->name : "?"); 1078 if (!old_parent_node || !new_parent_node) { 1079 res = -ENOENT; 1080 goto lookup_error; 1081 } 1082 if (!check_caller_access_to_name(fuse, hdr, old_parent_node, old_name, W_OK)) { 1083 res = -EACCES; 1084 goto lookup_error; 1085 } 1086 if (!check_caller_access_to_name(fuse, hdr, new_parent_node, new_name, W_OK)) { 1087 res = -EACCES; 1088 goto lookup_error; 1089 } 1090 child_node = lookup_child_by_name_locked(old_parent_node, old_name); 1091 if (!child_node || get_node_path_locked(child_node, 1092 old_child_path, sizeof(old_child_path)) < 0) { 1093 res = -ENOENT; 1094 goto lookup_error; 1095 } 1096 acquire_node_locked(child_node); 1097 pthread_mutex_unlock(&fuse->lock); 1098 1099 /* Special case for renaming a file where destination is same path 1100 * differing only by case. In this case we don't want to look for a case 1101 * insensitive match. This allows commands like "mv foo FOO" to work as expected. 1102 */ 1103 int search = old_parent_node != new_parent_node 1104 || strcasecmp(old_name, new_name); 1105 if (!(new_actual_name = find_file_within(new_parent_path, new_name, 1106 new_child_path, sizeof(new_child_path), search))) { 1107 res = -ENOENT; 1108 goto io_error; 1109 } 1110 1111 TRACE("[%d] RENAME %s->%s\n", handler->token, old_child_path, new_child_path); 1112 res = rename(old_child_path, new_child_path); 1113 if (res < 0) { 1114 res = -errno; 1115 goto io_error; 1116 } 1117 1118 pthread_mutex_lock(&fuse->lock); 1119 res = rename_node_locked(child_node, new_name, new_actual_name); 1120 if (!res) { 1121 remove_node_from_parent_locked(child_node); 1122 add_node_to_parent_locked(child_node, new_parent_node); 1123 } 1124 goto done; 1125 1126io_error: 1127 pthread_mutex_lock(&fuse->lock); 1128done: 1129 release_node_locked(child_node); 1130lookup_error: 1131 pthread_mutex_unlock(&fuse->lock); 1132 return res; 1133} 1134 1135static int open_flags_to_access_mode(int open_flags) { 1136 if ((open_flags & O_ACCMODE) == O_RDONLY) { 1137 return R_OK; 1138 } else if ((open_flags & O_ACCMODE) == O_WRONLY) { 1139 return W_OK; 1140 } else { 1141 /* Probably O_RDRW, but treat as default to be safe */ 1142 return R_OK | W_OK; 1143 } 1144} 1145 1146static int handle_open(struct fuse* fuse, struct fuse_handler* handler, 1147 const struct fuse_in_header* hdr, const struct fuse_open_in* req) 1148{ 1149 struct node* node; 1150 char path[PATH_MAX]; 1151 struct fuse_open_out out; 1152 struct handle *h; 1153 1154 pthread_mutex_lock(&fuse->lock); 1155 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 1156 TRACE("[%d] OPEN 0%o @ %llx (%s)\n", handler->token, 1157 req->flags, hdr->nodeid, node ? node->name : "?"); 1158 pthread_mutex_unlock(&fuse->lock); 1159 1160 if (!node) { 1161 return -ENOENT; 1162 } 1163 if (!check_caller_access_to_node(fuse, hdr, node, open_flags_to_access_mode(req->flags))) { 1164 return -EACCES; 1165 } 1166 h = malloc(sizeof(*h)); 1167 if (!h) { 1168 return -ENOMEM; 1169 } 1170 TRACE("[%d] OPEN %s\n", handler->token, path); 1171 h->fd = open(path, req->flags); 1172 if (h->fd < 0) { 1173 free(h); 1174 return -errno; 1175 } 1176 out.fh = ptr_to_id(h); 1177 out.open_flags = 0; 1178 out.padding = 0; 1179 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1180 return NO_STATUS; 1181} 1182 1183static int handle_read(struct fuse* fuse, struct fuse_handler* handler, 1184 const struct fuse_in_header* hdr, const struct fuse_read_in* req) 1185{ 1186 struct handle *h = id_to_ptr(req->fh); 1187 __u64 unique = hdr->unique; 1188 __u32 size = req->size; 1189 __u64 offset = req->offset; 1190 int res; 1191 1192 /* Don't access any other fields of hdr or req beyond this point, the read buffer 1193 * overlaps the request buffer and will clobber data in the request. This 1194 * saves us 128KB per request handler thread at the cost of this scary comment. */ 1195 1196 TRACE("[%d] READ %p(%d) %u@%llu\n", handler->token, 1197 h, h->fd, size, offset); 1198 if (size > sizeof(handler->read_buffer)) { 1199 return -EINVAL; 1200 } 1201 res = pread64(h->fd, handler->read_buffer, size, offset); 1202 if (res < 0) { 1203 return -errno; 1204 } 1205 fuse_reply(fuse, unique, handler->read_buffer, res); 1206 return NO_STATUS; 1207} 1208 1209static int handle_write(struct fuse* fuse, struct fuse_handler* handler, 1210 const struct fuse_in_header* hdr, const struct fuse_write_in* req, 1211 const void* buffer) 1212{ 1213 struct fuse_write_out out; 1214 struct handle *h = id_to_ptr(req->fh); 1215 int res; 1216 1217 TRACE("[%d] WRITE %p(%d) %u@%llu\n", handler->token, 1218 h, h->fd, req->size, req->offset); 1219 res = pwrite64(h->fd, buffer, req->size, req->offset); 1220 if (res < 0) { 1221 return -errno; 1222 } 1223 out.size = res; 1224 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1225 return NO_STATUS; 1226} 1227 1228static int handle_statfs(struct fuse* fuse, struct fuse_handler* handler, 1229 const struct fuse_in_header* hdr) 1230{ 1231 char path[PATH_MAX]; 1232 struct statfs stat; 1233 struct fuse_statfs_out out; 1234 int res; 1235 1236 pthread_mutex_lock(&fuse->lock); 1237 TRACE("[%d] STATFS\n", handler->token); 1238 res = get_node_path_locked(&fuse->root, path, sizeof(path)); 1239 pthread_mutex_unlock(&fuse->lock); 1240 if (res < 0) { 1241 return -ENOENT; 1242 } 1243 if (statfs(fuse->root.name, &stat) < 0) { 1244 return -errno; 1245 } 1246 memset(&out, 0, sizeof(out)); 1247 out.st.blocks = stat.f_blocks; 1248 out.st.bfree = stat.f_bfree; 1249 out.st.bavail = stat.f_bavail; 1250 out.st.files = stat.f_files; 1251 out.st.ffree = stat.f_ffree; 1252 out.st.bsize = stat.f_bsize; 1253 out.st.namelen = stat.f_namelen; 1254 out.st.frsize = stat.f_frsize; 1255 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1256 return NO_STATUS; 1257} 1258 1259static int handle_release(struct fuse* fuse, struct fuse_handler* handler, 1260 const struct fuse_in_header* hdr, const struct fuse_release_in* req) 1261{ 1262 struct handle *h = id_to_ptr(req->fh); 1263 1264 TRACE("[%d] RELEASE %p(%d)\n", handler->token, h, h->fd); 1265 close(h->fd); 1266 free(h); 1267 return 0; 1268} 1269 1270static int handle_fsync(struct fuse* fuse, struct fuse_handler* handler, 1271 const struct fuse_in_header* hdr, const struct fuse_fsync_in* req) 1272{ 1273 int is_data_sync = req->fsync_flags & 1; 1274 struct handle *h = id_to_ptr(req->fh); 1275 int res; 1276 1277 TRACE("[%d] FSYNC %p(%d) is_data_sync=%d\n", handler->token, 1278 h, h->fd, is_data_sync); 1279 res = is_data_sync ? fdatasync(h->fd) : fsync(h->fd); 1280 if (res < 0) { 1281 return -errno; 1282 } 1283 return 0; 1284} 1285 1286static int handle_flush(struct fuse* fuse, struct fuse_handler* handler, 1287 const struct fuse_in_header* hdr) 1288{ 1289 TRACE("[%d] FLUSH\n", handler->token); 1290 return 0; 1291} 1292 1293static int handle_opendir(struct fuse* fuse, struct fuse_handler* handler, 1294 const struct fuse_in_header* hdr, const struct fuse_open_in* req) 1295{ 1296 struct node* node; 1297 char path[PATH_MAX]; 1298 struct fuse_open_out out; 1299 struct dirhandle *h; 1300 1301 pthread_mutex_lock(&fuse->lock); 1302 node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path)); 1303 TRACE("[%d] OPENDIR @ %llx (%s)\n", handler->token, 1304 hdr->nodeid, node ? node->name : "?"); 1305 pthread_mutex_unlock(&fuse->lock); 1306 1307 if (!node) { 1308 return -ENOENT; 1309 } 1310 if (!check_caller_access_to_node(fuse, hdr, node, R_OK)) { 1311 return -EACCES; 1312 } 1313 h = malloc(sizeof(*h)); 1314 if (!h) { 1315 return -ENOMEM; 1316 } 1317 TRACE("[%d] OPENDIR %s\n", handler->token, path); 1318 h->d = opendir(path); 1319 if (!h->d) { 1320 free(h); 1321 return -errno; 1322 } 1323 out.fh = ptr_to_id(h); 1324 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1325 return NO_STATUS; 1326} 1327 1328static int handle_readdir(struct fuse* fuse, struct fuse_handler* handler, 1329 const struct fuse_in_header* hdr, const struct fuse_read_in* req) 1330{ 1331 char buffer[8192]; 1332 struct fuse_dirent *fde = (struct fuse_dirent*) buffer; 1333 struct dirent *de; 1334 struct dirhandle *h = id_to_ptr(req->fh); 1335 1336 TRACE("[%d] READDIR %p\n", handler->token, h); 1337 if (req->offset == 0) { 1338 /* rewinddir() might have been called above us, so rewind here too */ 1339 TRACE("[%d] calling rewinddir()\n", handler->token); 1340 rewinddir(h->d); 1341 } 1342 de = readdir(h->d); 1343 if (!de) { 1344 return 0; 1345 } 1346 fde->ino = FUSE_UNKNOWN_INO; 1347 /* increment the offset so we can detect when rewinddir() seeks back to the beginning */ 1348 fde->off = req->offset + 1; 1349 fde->type = de->d_type; 1350 fde->namelen = strlen(de->d_name); 1351 memcpy(fde->name, de->d_name, fde->namelen + 1); 1352 fuse_reply(fuse, hdr->unique, fde, 1353 FUSE_DIRENT_ALIGN(sizeof(struct fuse_dirent) + fde->namelen)); 1354 return NO_STATUS; 1355} 1356 1357static int handle_releasedir(struct fuse* fuse, struct fuse_handler* handler, 1358 const struct fuse_in_header* hdr, const struct fuse_release_in* req) 1359{ 1360 struct dirhandle *h = id_to_ptr(req->fh); 1361 1362 TRACE("[%d] RELEASEDIR %p\n", handler->token, h); 1363 closedir(h->d); 1364 free(h); 1365 return 0; 1366} 1367 1368static int handle_init(struct fuse* fuse, struct fuse_handler* handler, 1369 const struct fuse_in_header* hdr, const struct fuse_init_in* req) 1370{ 1371 struct fuse_init_out out; 1372 1373 TRACE("[%d] INIT ver=%d.%d maxread=%d flags=%x\n", 1374 handler->token, req->major, req->minor, req->max_readahead, req->flags); 1375 out.major = FUSE_KERNEL_VERSION; 1376 out.minor = FUSE_KERNEL_MINOR_VERSION; 1377 out.max_readahead = req->max_readahead; 1378 out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; 1379 out.max_background = 32; 1380 out.congestion_threshold = 32; 1381 out.max_write = MAX_WRITE; 1382 fuse_reply(fuse, hdr->unique, &out, sizeof(out)); 1383 return NO_STATUS; 1384} 1385 1386static int handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler, 1387 const struct fuse_in_header *hdr, const void *data, size_t data_len) 1388{ 1389 switch (hdr->opcode) { 1390 case FUSE_LOOKUP: { /* bytez[] -> entry_out */ 1391 const char* name = data; 1392 return handle_lookup(fuse, handler, hdr, name); 1393 } 1394 1395 case FUSE_FORGET: { 1396 const struct fuse_forget_in *req = data; 1397 return handle_forget(fuse, handler, hdr, req); 1398 } 1399 1400 case FUSE_GETATTR: { /* getattr_in -> attr_out */ 1401 const struct fuse_getattr_in *req = data; 1402 return handle_getattr(fuse, handler, hdr, req); 1403 } 1404 1405 case FUSE_SETATTR: { /* setattr_in -> attr_out */ 1406 const struct fuse_setattr_in *req = data; 1407 return handle_setattr(fuse, handler, hdr, req); 1408 } 1409 1410// case FUSE_READLINK: 1411// case FUSE_SYMLINK: 1412 case FUSE_MKNOD: { /* mknod_in, bytez[] -> entry_out */ 1413 const struct fuse_mknod_in *req = data; 1414 const char *name = ((const char*) data) + sizeof(*req); 1415 return handle_mknod(fuse, handler, hdr, req, name); 1416 } 1417 1418 case FUSE_MKDIR: { /* mkdir_in, bytez[] -> entry_out */ 1419 const struct fuse_mkdir_in *req = data; 1420 const char *name = ((const char*) data) + sizeof(*req); 1421 return handle_mkdir(fuse, handler, hdr, req, name); 1422 } 1423 1424 case FUSE_UNLINK: { /* bytez[] -> */ 1425 const char* name = data; 1426 return handle_unlink(fuse, handler, hdr, name); 1427 } 1428 1429 case FUSE_RMDIR: { /* bytez[] -> */ 1430 const char* name = data; 1431 return handle_rmdir(fuse, handler, hdr, name); 1432 } 1433 1434 case FUSE_RENAME: { /* rename_in, oldname, newname -> */ 1435 const struct fuse_rename_in *req = data; 1436 const char *old_name = ((const char*) data) + sizeof(*req); 1437 const char *new_name = old_name + strlen(old_name) + 1; 1438 return handle_rename(fuse, handler, hdr, req, old_name, new_name); 1439 } 1440 1441// case FUSE_LINK: 1442 case FUSE_OPEN: { /* open_in -> open_out */ 1443 const struct fuse_open_in *req = data; 1444 return handle_open(fuse, handler, hdr, req); 1445 } 1446 1447 case FUSE_READ: { /* read_in -> byte[] */ 1448 const struct fuse_read_in *req = data; 1449 return handle_read(fuse, handler, hdr, req); 1450 } 1451 1452 case FUSE_WRITE: { /* write_in, byte[write_in.size] -> write_out */ 1453 const struct fuse_write_in *req = data; 1454 const void* buffer = (const __u8*)data + sizeof(*req); 1455 return handle_write(fuse, handler, hdr, req, buffer); 1456 } 1457 1458 case FUSE_STATFS: { /* getattr_in -> attr_out */ 1459 return handle_statfs(fuse, handler, hdr); 1460 } 1461 1462 case FUSE_RELEASE: { /* release_in -> */ 1463 const struct fuse_release_in *req = data; 1464 return handle_release(fuse, handler, hdr, req); 1465 } 1466 1467 case FUSE_FSYNC: { 1468 const struct fuse_fsync_in *req = data; 1469 return handle_fsync(fuse, handler, hdr, req); 1470 } 1471 1472// case FUSE_SETXATTR: 1473// case FUSE_GETXATTR: 1474// case FUSE_LISTXATTR: 1475// case FUSE_REMOVEXATTR: 1476 case FUSE_FLUSH: { 1477 return handle_flush(fuse, handler, hdr); 1478 } 1479 1480 case FUSE_OPENDIR: { /* open_in -> open_out */ 1481 const struct fuse_open_in *req = data; 1482 return handle_opendir(fuse, handler, hdr, req); 1483 } 1484 1485 case FUSE_READDIR: { 1486 const struct fuse_read_in *req = data; 1487 return handle_readdir(fuse, handler, hdr, req); 1488 } 1489 1490 case FUSE_RELEASEDIR: { /* release_in -> */ 1491 const struct fuse_release_in *req = data; 1492 return handle_releasedir(fuse, handler, hdr, req); 1493 } 1494 1495// case FUSE_FSYNCDIR: 1496 case FUSE_INIT: { /* init_in -> init_out */ 1497 const struct fuse_init_in *req = data; 1498 return handle_init(fuse, handler, hdr, req); 1499 } 1500 1501 default: { 1502 TRACE("[%d] NOTIMPL op=%d uniq=%llx nid=%llx\n", 1503 handler->token, hdr->opcode, hdr->unique, hdr->nodeid); 1504 return -ENOSYS; 1505 } 1506 } 1507} 1508 1509static void handle_fuse_requests(struct fuse_handler* handler) 1510{ 1511 struct fuse* fuse = handler->fuse; 1512 for (;;) { 1513 ssize_t len = read(fuse->fd, 1514 handler->request_buffer, sizeof(handler->request_buffer)); 1515 if (len < 0) { 1516 if (errno != EINTR) { 1517 ERROR("[%d] handle_fuse_requests: errno=%d\n", handler->token, errno); 1518 } 1519 continue; 1520 } 1521 1522 if ((size_t)len < sizeof(struct fuse_in_header)) { 1523 ERROR("[%d] request too short: len=%zu\n", handler->token, (size_t)len); 1524 continue; 1525 } 1526 1527 const struct fuse_in_header *hdr = (void*)handler->request_buffer; 1528 if (hdr->len != (size_t)len) { 1529 ERROR("[%d] malformed header: len=%zu, hdr->len=%u\n", 1530 handler->token, (size_t)len, hdr->len); 1531 continue; 1532 } 1533 1534 const void *data = handler->request_buffer + sizeof(struct fuse_in_header); 1535 size_t data_len = len - sizeof(struct fuse_in_header); 1536 __u64 unique = hdr->unique; 1537 int res = handle_fuse_request(fuse, handler, hdr, data, data_len); 1538 1539 /* We do not access the request again after this point because the underlying 1540 * buffer storage may have been reused while processing the request. */ 1541 1542 if (res != NO_STATUS) { 1543 if (res) { 1544 TRACE("[%d] ERROR %d\n", handler->token, res); 1545 } 1546 fuse_status(fuse, unique, res); 1547 } 1548 } 1549} 1550 1551static void* start_handler(void* data) 1552{ 1553 struct fuse_handler* handler = data; 1554 handle_fuse_requests(handler); 1555 return NULL; 1556} 1557 1558static bool remove_str_to_int(void *key, void *value, void *context) { 1559 Hashmap* map = context; 1560 hashmapRemove(map, key); 1561 free(key); 1562 return true; 1563} 1564 1565static bool remove_int_to_null(void *key, void *value, void *context) { 1566 Hashmap* map = context; 1567 hashmapRemove(map, key); 1568 return true; 1569} 1570 1571static int read_package_list(struct fuse *fuse) { 1572 pthread_mutex_lock(&fuse->lock); 1573 1574 hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid); 1575 hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw); 1576 1577 FILE* file = fopen(kPackagesListFile, "r"); 1578 if (!file) { 1579 ERROR("failed to open package list: %s\n", strerror(errno)); 1580 pthread_mutex_unlock(&fuse->lock); 1581 return -1; 1582 } 1583 1584 char buf[512]; 1585 while (fgets(buf, sizeof(buf), file) != NULL) { 1586 char package_name[512]; 1587 int appid; 1588 char gids[512]; 1589 1590 if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) { 1591 char* package_name_dup = strdup(package_name); 1592 hashmapPut(fuse->package_to_appid, package_name_dup, (void*) appid); 1593 1594 char* token = strtok(gids, ","); 1595 while (token != NULL) { 1596 if (strtoul(token, NULL, 10) == AID_SDCARD_RW) { 1597 hashmapPut(fuse->appid_with_rw, (void*) appid, (void*) 1); 1598 break; 1599 } 1600 token = strtok(NULL, ","); 1601 } 1602 } 1603 } 1604 1605 TRACE("read_package_list: found %d packages, %d with sdcard_rw\n", 1606 hashmapSize(fuse->package_to_appid), 1607 hashmapSize(fuse->appid_with_rw)); 1608 fclose(file); 1609 pthread_mutex_unlock(&fuse->lock); 1610 return 0; 1611} 1612 1613static void watch_package_list(struct fuse* fuse) { 1614 struct inotify_event *event; 1615 char event_buf[512]; 1616 1617 int nfd = inotify_init(); 1618 if (nfd < 0) { 1619 ERROR("inotify_init failed: %s\n", strerror(errno)); 1620 return; 1621 } 1622 1623 bool active = false; 1624 while (1) { 1625 if (!active) { 1626 int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF); 1627 if (res == -1) { 1628 if (errno == ENOENT || errno == EACCES) { 1629 /* Framework may not have created yet, sleep and retry */ 1630 ERROR("missing packages.list; retrying\n"); 1631 sleep(3); 1632 continue; 1633 } else { 1634 ERROR("inotify_add_watch failed: %s\n", strerror(errno)); 1635 return; 1636 } 1637 } 1638 1639 /* Watch above will tell us about any future changes, so 1640 * read the current state. */ 1641 if (read_package_list(fuse) == -1) { 1642 ERROR("read_package_list failed: %s\n", strerror(errno)); 1643 return; 1644 } 1645 active = true; 1646 } 1647 1648 int event_pos = 0; 1649 int res = read(nfd, event_buf, sizeof(event_buf)); 1650 if (res < (int) sizeof(*event)) { 1651 if (errno == EINTR) 1652 continue; 1653 ERROR("failed to read inotify event: %s\n", strerror(errno)); 1654 return; 1655 } 1656 1657 while (res >= (int) sizeof(*event)) { 1658 int event_size; 1659 event = (struct inotify_event *) (event_buf + event_pos); 1660 1661 TRACE("inotify event: %08x\n", event->mask); 1662 if ((event->mask & IN_IGNORED) == IN_IGNORED) { 1663 /* Previously watched file was deleted, probably due to move 1664 * that swapped in new data; re-arm the watch and read. */ 1665 active = false; 1666 } 1667 1668 event_size = sizeof(*event) + event->len; 1669 res -= event_size; 1670 event_pos += event_size; 1671 } 1672 } 1673} 1674 1675static int ignite_fuse(struct fuse* fuse, int num_threads) 1676{ 1677 struct fuse_handler* handlers; 1678 int i; 1679 1680 handlers = malloc(num_threads * sizeof(struct fuse_handler)); 1681 if (!handlers) { 1682 ERROR("cannot allocate storage for threads\n"); 1683 return -ENOMEM; 1684 } 1685 1686 for (i = 0; i < num_threads; i++) { 1687 handlers[i].fuse = fuse; 1688 handlers[i].token = i; 1689 } 1690 1691 /* When deriving permissions, this thread is used to process inotify events, 1692 * otherwise it becomes one of the FUSE handlers. */ 1693 i = (fuse->derive == DERIVE_NONE) ? 1 : 0; 1694 for (; i < num_threads; i++) { 1695 pthread_t thread; 1696 int res = pthread_create(&thread, NULL, start_handler, &handlers[i]); 1697 if (res) { 1698 ERROR("failed to start thread #%d, error=%d\n", i, res); 1699 goto quit; 1700 } 1701 } 1702 1703 if (fuse->derive == DERIVE_NONE) { 1704 handle_fuse_requests(&handlers[0]); 1705 } else { 1706 watch_package_list(fuse); 1707 } 1708 1709 ERROR("terminated prematurely\n"); 1710 1711 /* don't bother killing all of the other threads or freeing anything, 1712 * should never get here anyhow */ 1713quit: 1714 exit(1); 1715} 1716 1717static int usage() 1718{ 1719 ERROR("usage: sdcard [OPTIONS] <source_path> <dest_path>\n" 1720 " -u: specify UID to run as\n" 1721 " -g: specify GID to run as\n" 1722 " -G: specify default GID for files (default sdcard_r, requires -d or -l)\n" 1723 " -t: specify number of threads to use (default %d)\n" 1724 " -d: derive file permissions based on path\n" 1725 " -l: derive file permissions based on legacy internal layout\n" 1726 " -s: split derived permissions for pics, av\n" 1727 "\n", DEFAULT_NUM_THREADS); 1728 return 1; 1729} 1730 1731static int run(const char* source_path, const char* dest_path, uid_t uid, 1732 gid_t gid, gid_t fs_gid, int num_threads, derive_t derive, bool split_perms) { 1733 int fd; 1734 char opts[256]; 1735 int res; 1736 struct fuse fuse; 1737 1738 /* cleanup from previous instance, if necessary */ 1739 umount2(dest_path, 2); 1740 1741 fd = open("/dev/fuse", O_RDWR); 1742 if (fd < 0){ 1743 ERROR("cannot open fuse device: %s\n", strerror(errno)); 1744 return -1; 1745 } 1746 1747 snprintf(opts, sizeof(opts), 1748 "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", 1749 fd, uid, gid); 1750 1751 res = mount("/dev/fuse", dest_path, "fuse", MS_NOSUID | MS_NODEV, opts); 1752 if (res < 0) { 1753 ERROR("cannot mount fuse filesystem: %s\n", strerror(errno)); 1754 goto error; 1755 } 1756 1757 res = setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups); 1758 if (res < 0) { 1759 ERROR("cannot setgroups: %s\n", strerror(errno)); 1760 goto error; 1761 } 1762 1763 res = setgid(gid); 1764 if (res < 0) { 1765 ERROR("cannot setgid: %s\n", strerror(errno)); 1766 goto error; 1767 } 1768 1769 res = setuid(uid); 1770 if (res < 0) { 1771 ERROR("cannot setuid: %s\n", strerror(errno)); 1772 goto error; 1773 } 1774 1775 fuse_init(&fuse, fd, source_path, fs_gid, derive, split_perms); 1776 1777 umask(0); 1778 res = ignite_fuse(&fuse, num_threads); 1779 1780 /* we do not attempt to umount the file system here because we are no longer 1781 * running as the root user */ 1782 1783error: 1784 close(fd); 1785 return res; 1786} 1787 1788int main(int argc, char **argv) 1789{ 1790 int res; 1791 const char *source_path = NULL; 1792 const char *dest_path = NULL; 1793 uid_t uid = 0; 1794 gid_t gid = 0; 1795 gid_t fs_gid = AID_SDCARD_R; 1796 int num_threads = DEFAULT_NUM_THREADS; 1797 derive_t derive = DERIVE_NONE; 1798 bool split_perms = false; 1799 int i; 1800 struct rlimit rlim; 1801 1802 int opt; 1803 while ((opt = getopt(argc, argv, "u:g:G:t:dls")) != -1) { 1804 switch (opt) { 1805 case 'u': 1806 uid = strtoul(optarg, NULL, 10); 1807 break; 1808 case 'g': 1809 gid = strtoul(optarg, NULL, 10); 1810 break; 1811 case 'G': 1812 fs_gid = strtoul(optarg, NULL, 10); 1813 break; 1814 case 't': 1815 num_threads = strtoul(optarg, NULL, 10); 1816 break; 1817 case 'd': 1818 derive = DERIVE_UNIFIED; 1819 break; 1820 case 'l': 1821 derive = DERIVE_LEGACY; 1822 break; 1823 case 's': 1824 split_perms = true; 1825 break; 1826 case '?': 1827 default: 1828 return usage(); 1829 } 1830 } 1831 1832 for (i = optind; i < argc; i++) { 1833 char* arg = argv[i]; 1834 if (!source_path) { 1835 source_path = arg; 1836 } else if (!dest_path) { 1837 dest_path = arg; 1838 } else if (!uid) { 1839 uid = strtoul(arg, NULL, 10); 1840 } else if (!gid) { 1841 gid = strtoul(arg, NULL, 10); 1842 } else { 1843 ERROR("too many arguments\n"); 1844 return usage(); 1845 } 1846 } 1847 1848 if (!source_path) { 1849 ERROR("no source path specified\n"); 1850 return usage(); 1851 } 1852 if (!dest_path) { 1853 ERROR("no dest path specified\n"); 1854 return usage(); 1855 } 1856 if (!uid || !gid) { 1857 ERROR("uid and gid must be nonzero\n"); 1858 return usage(); 1859 } 1860 if (num_threads < 1) { 1861 ERROR("number of threads must be at least 1\n"); 1862 return usage(); 1863 } 1864 if (split_perms && derive == DERIVE_NONE) { 1865 ERROR("cannot split permissions without deriving\n"); 1866 return usage(); 1867 } 1868 1869 rlim.rlim_cur = 8192; 1870 rlim.rlim_max = 8192; 1871 if (setrlimit(RLIMIT_NOFILE, &rlim)) { 1872 ERROR("Error setting RLIMIT_NOFILE, errno = %d\n", errno); 1873 } 1874 1875 res = run(source_path, dest_path, uid, gid, fs_gid, num_threads, derive, split_perms); 1876 return res < 0 ? 1 : 0; 1877} 1878