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