devices.cpp revision d4ff8d83d3fcc23c07d928f8d463a54aa584e739
1/* 2 * Copyright (C) 2007-2014 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 <dirent.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <fnmatch.h> 21#include <libgen.h> 22#include <linux/netlink.h> 23#include <stddef.h> 24#include <stdio.h> 25#include <stdlib.h> 26#include <string.h> 27#include <sys/sendfile.h> 28#include <sys/socket.h> 29#include <sys/time.h> 30#include <sys/types.h> 31#include <sys/un.h> 32#include <sys/wait.h> 33#include <unistd.h> 34 35#include <memory> 36#include <thread> 37 38#include <android-base/file.h> 39#include <android-base/logging.h> 40#include <android-base/stringprintf.h> 41#include <android-base/unique_fd.h> 42#include <cutils/list.h> 43#include <cutils/uevent.h> 44#include <private/android_filesystem_config.h> 45#include <selinux/android.h> 46#include <selinux/avc.h> 47#include <selinux/label.h> 48#include <selinux/selinux.h> 49 50#include "devices.h" 51#include "ueventd_parser.h" 52#include "util.h" 53 54#define SYSFS_PREFIX "/sys" 55static const char *firmware_dirs[] = { "/etc/firmware", 56 "/vendor/firmware", 57 "/firmware/image" }; 58 59extern struct selabel_handle *sehandle; 60 61static android::base::unique_fd device_fd; 62 63struct perms_ { 64 char *name; 65 char *attr; 66 mode_t perm; 67 unsigned int uid; 68 unsigned int gid; 69 unsigned short prefix; 70 unsigned short wildcard; 71}; 72 73struct perm_node { 74 struct perms_ dp; 75 struct listnode plist; 76}; 77 78struct platform_node { 79 char *name; 80 char *path; 81 int path_len; 82 struct listnode list; 83}; 84 85static list_declare(sys_perms); 86static list_declare(dev_perms); 87static list_declare(platform_names); 88 89int add_dev_perms(const char *name, const char *attr, 90 mode_t perm, unsigned int uid, unsigned int gid, 91 unsigned short prefix, 92 unsigned short wildcard) { 93 struct perm_node *node = (perm_node*) calloc(1, sizeof(*node)); 94 if (!node) 95 return -ENOMEM; 96 97 node->dp.name = strdup(name); 98 if (!node->dp.name) { 99 free(node); 100 return -ENOMEM; 101 } 102 103 if (attr) { 104 node->dp.attr = strdup(attr); 105 if (!node->dp.attr) { 106 free(node->dp.name); 107 free(node); 108 return -ENOMEM; 109 } 110 } 111 112 node->dp.perm = perm; 113 node->dp.uid = uid; 114 node->dp.gid = gid; 115 node->dp.prefix = prefix; 116 node->dp.wildcard = wildcard; 117 118 if (attr) 119 list_add_tail(&sys_perms, &node->plist); 120 else 121 list_add_tail(&dev_perms, &node->plist); 122 123 return 0; 124} 125 126static bool perm_path_matches(const char *path, struct perms_ *dp) 127{ 128 if (dp->prefix) { 129 if (strncmp(path, dp->name, strlen(dp->name)) == 0) 130 return true; 131 } else if (dp->wildcard) { 132 if (fnmatch(dp->name, path, FNM_PATHNAME) == 0) 133 return true; 134 } else { 135 if (strcmp(path, dp->name) == 0) 136 return true; 137 } 138 139 return false; 140} 141 142static bool match_subsystem(perms_* dp, const char* pattern, 143 const char* path, const char* subsystem) { 144 if (!pattern || !subsystem || strstr(dp->name, subsystem) == NULL) { 145 return false; 146 } 147 148 std::string subsys_path = android::base::StringPrintf(pattern, subsystem, basename(path)); 149 return perm_path_matches(subsys_path.c_str(), dp); 150} 151 152static void fixup_sys_perms(const char* upath, const char* subsystem) { 153 // upaths omit the "/sys" that paths in this list 154 // contain, so we prepend it... 155 std::string path = std::string(SYSFS_PREFIX) + upath; 156 157 listnode* node; 158 list_for_each(node, &sys_perms) { 159 perms_* dp = &(node_to_item(node, perm_node, plist))->dp; 160 if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem)) { 161 ; // matched 162 } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(), subsystem)) { 163 ; // matched 164 } else if (!perm_path_matches(path.c_str(), dp)) { 165 continue; 166 } 167 168 std::string attr_file = path + "/" + dp->attr; 169 LOG(INFO) << "fixup " << attr_file 170 << " " << dp->uid << " " << dp->gid << " " << std::oct << dp->perm; 171 chown(attr_file.c_str(), dp->uid, dp->gid); 172 chmod(attr_file.c_str(), dp->perm); 173 } 174 175 if (access(path.c_str(), F_OK) == 0) { 176 LOG(VERBOSE) << "restorecon_recursive: " << path; 177 restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE); 178 } 179} 180 181static mode_t get_device_perm(const char *path, const char **links, 182 unsigned *uid, unsigned *gid) 183{ 184 struct listnode *node; 185 struct perm_node *perm_node; 186 struct perms_ *dp; 187 188 /* search the perms list in reverse so that ueventd.$hardware can 189 * override ueventd.rc 190 */ 191 list_for_each_reverse(node, &dev_perms) { 192 bool match = false; 193 194 perm_node = node_to_item(node, struct perm_node, plist); 195 dp = &perm_node->dp; 196 197 if (perm_path_matches(path, dp)) { 198 match = true; 199 } else { 200 if (links) { 201 int i; 202 for (i = 0; links[i]; i++) { 203 if (perm_path_matches(links[i], dp)) { 204 match = true; 205 break; 206 } 207 } 208 } 209 } 210 211 if (match) { 212 *uid = dp->uid; 213 *gid = dp->gid; 214 return dp->perm; 215 } 216 } 217 /* Default if nothing found. */ 218 *uid = 0; 219 *gid = 0; 220 return 0600; 221} 222 223static void make_device(const char *path, 224 const char */*upath*/, 225 int block, int major, int minor, 226 const char **links) 227{ 228 unsigned uid; 229 unsigned gid; 230 mode_t mode; 231 dev_t dev; 232 char *secontext = NULL; 233 234 mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR); 235 236 if (sehandle) { 237 if (selabel_lookup_best_match(sehandle, &secontext, path, links, mode)) { 238 PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label"; 239 return; 240 } 241 setfscreatecon(secontext); 242 } 243 244 dev = makedev(major, minor); 245 /* Temporarily change egid to avoid race condition setting the gid of the 246 * device node. Unforunately changing the euid would prevent creation of 247 * some device nodes, so the uid has to be set with chown() and is still 248 * racy. Fixing the gid race at least fixed the issue with system_server 249 * opening dynamic input devices under the AID_INPUT gid. */ 250 if (setegid(gid)) { 251 PLOG(ERROR) << "setegid(" << gid << ") for " << path << " device failed"; 252 goto out; 253 } 254 /* If the node already exists update its SELinux label to handle cases when 255 * it was created with the wrong context during coldboot procedure. */ 256 if (mknod(path, mode, dev) && (errno == EEXIST) && secontext) { 257 258 char* fcon = nullptr; 259 int rc = lgetfilecon(path, &fcon); 260 if (rc < 0) { 261 PLOG(ERROR) << "Cannot get SELinux label on '" << path << "' device"; 262 goto out; 263 } 264 265 bool different = strcmp(fcon, secontext) != 0; 266 freecon(fcon); 267 268 if (different && lsetfilecon(path, secontext)) { 269 PLOG(ERROR) << "Cannot set '" << secontext << "' SELinux label on '" << path << "' device"; 270 } 271 } 272 273out: 274 chown(path, uid, -1); 275 if (setegid(AID_ROOT)) { 276 PLOG(FATAL) << "setegid(AID_ROOT) failed"; 277 } 278 279 if (secontext) { 280 freecon(secontext); 281 setfscreatecon(NULL); 282 } 283} 284 285void add_platform_device(const char* path) { 286 int path_len = strlen(path); 287 struct platform_node *bus; 288 const char *name = path; 289 290 if (!strncmp(path, "/devices/", 9)) { 291 name += 9; 292 if (!strncmp(name, "platform/", 9)) 293 name += 9; 294 } 295 296 LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")"; 297 298 bus = (platform_node*) calloc(1, sizeof(struct platform_node)); 299 bus->path = strdup(path); 300 bus->path_len = path_len; 301 bus->name = bus->path + (name - path); 302 list_add_tail(&platform_names, &bus->list); 303} 304 305/* 306 * given a path that may start with a platform device, find the length of the 307 * platform device prefix. If it doesn't start with a platform device, return 308 * 0. 309 */ 310static struct platform_node *find_platform_device(const char *path) 311{ 312 int path_len = strlen(path); 313 struct listnode *node; 314 struct platform_node *bus; 315 316 list_for_each_reverse(node, &platform_names) { 317 bus = node_to_item(node, struct platform_node, list); 318 if ((bus->path_len < path_len) && 319 (path[bus->path_len] == '/') && 320 !strncmp(path, bus->path, bus->path_len)) 321 return bus; 322 } 323 324 return NULL; 325} 326 327void remove_platform_device(const char* path) { 328 struct listnode *node; 329 struct platform_node *bus; 330 331 list_for_each_reverse(node, &platform_names) { 332 bus = node_to_item(node, struct platform_node, list); 333 if (!strcmp(path, bus->path)) { 334 LOG(INFO) << "removing platform device " << bus->name; 335 free(bus->path); 336 list_remove(node); 337 free(bus); 338 return; 339 } 340 } 341} 342 343static void destroy_platform_devices() { 344 struct listnode* node; 345 struct listnode* n; 346 struct platform_node* bus; 347 348 list_for_each_safe(node, n, &platform_names) { 349 list_remove(node); 350 bus = node_to_item(node, struct platform_node, list); 351 free(bus->path); 352 free(bus); 353 } 354} 355 356/* Given a path that may start with a PCI device, populate the supplied buffer 357 * with the PCI domain/bus number and the peripheral ID and return 0. 358 * If it doesn't start with a PCI device, or there is some error, return -1 */ 359static int find_pci_device_prefix(const char *path, char *buf, ssize_t buf_sz) 360{ 361 const char *start, *end; 362 363 if (strncmp(path, "/devices/pci", 12)) 364 return -1; 365 366 /* Beginning of the prefix is the initial "pci" after "/devices/" */ 367 start = path + 9; 368 369 /* End of the prefix is two path '/' later, capturing the domain/bus number 370 * and the peripheral ID. Example: pci0000:00/0000:00:1f.2 */ 371 end = strchr(start, '/'); 372 if (!end) 373 return -1; 374 end = strchr(end + 1, '/'); 375 if (!end) 376 return -1; 377 378 /* Make sure we have enough room for the string plus null terminator */ 379 if (end - start + 1 > buf_sz) 380 return -1; 381 382 strncpy(buf, start, end - start); 383 buf[end - start] = '\0'; 384 return 0; 385} 386 387/* Given a path that may start with a virtual block device, populate 388 * the supplied buffer with the virtual block device ID and return 0. 389 * If it doesn't start with a virtual block device, or there is some 390 * error, return -1 */ 391static int find_vbd_device_prefix(const char *path, char *buf, ssize_t buf_sz) 392{ 393 const char *start, *end; 394 395 /* Beginning of the prefix is the initial "vbd-" after "/devices/" */ 396 if (strncmp(path, "/devices/vbd-", 13)) 397 return -1; 398 399 /* End of the prefix is one path '/' later, capturing the 400 virtual block device ID. Example: 768 */ 401 start = path + 13; 402 end = strchr(start, '/'); 403 if (!end) 404 return -1; 405 406 /* Make sure we have enough room for the string plus null terminator */ 407 if (end - start + 1 > buf_sz) 408 return -1; 409 410 strncpy(buf, start, end - start); 411 buf[end - start] = '\0'; 412 return 0; 413} 414 415static void parse_event(const char *msg, struct uevent *uevent) 416{ 417 uevent->action = ""; 418 uevent->path = ""; 419 uevent->subsystem = ""; 420 uevent->firmware = ""; 421 uevent->major = -1; 422 uevent->minor = -1; 423 uevent->partition_name = NULL; 424 uevent->partition_num = -1; 425 uevent->device_name = NULL; 426 427 /* currently ignoring SEQNUM */ 428 while(*msg) { 429 if(!strncmp(msg, "ACTION=", 7)) { 430 msg += 7; 431 uevent->action = msg; 432 } else if(!strncmp(msg, "DEVPATH=", 8)) { 433 msg += 8; 434 uevent->path = msg; 435 } else if(!strncmp(msg, "SUBSYSTEM=", 10)) { 436 msg += 10; 437 uevent->subsystem = msg; 438 } else if(!strncmp(msg, "FIRMWARE=", 9)) { 439 msg += 9; 440 uevent->firmware = msg; 441 } else if(!strncmp(msg, "MAJOR=", 6)) { 442 msg += 6; 443 uevent->major = atoi(msg); 444 } else if(!strncmp(msg, "MINOR=", 6)) { 445 msg += 6; 446 uevent->minor = atoi(msg); 447 } else if(!strncmp(msg, "PARTN=", 6)) { 448 msg += 6; 449 uevent->partition_num = atoi(msg); 450 } else if(!strncmp(msg, "PARTNAME=", 9)) { 451 msg += 9; 452 uevent->partition_name = msg; 453 } else if(!strncmp(msg, "DEVNAME=", 8)) { 454 msg += 8; 455 uevent->device_name = msg; 456 } 457 458 /* advance to after the next \0 */ 459 while(*msg++) 460 ; 461 } 462 463 if (LOG_UEVENTS) { 464 LOG(INFO) << android::base::StringPrintf("event { '%s', '%s', '%s', '%s', %d, %d }", 465 uevent->action, uevent->path, uevent->subsystem, 466 uevent->firmware, uevent->major, uevent->minor); 467 } 468} 469 470char** get_character_device_symlinks(struct uevent* uevent) { 471 const char *parent; 472 const char *slash; 473 char **links; 474 int link_num = 0; 475 int width; 476 struct platform_node *pdev; 477 478 pdev = find_platform_device(uevent->path); 479 if (!pdev) 480 return NULL; 481 482 links = (char**) malloc(sizeof(char *) * 2); 483 if (!links) 484 return NULL; 485 memset(links, 0, sizeof(char *) * 2); 486 487 /* skip "/devices/platform/<driver>" */ 488 parent = strchr(uevent->path + pdev->path_len, '/'); 489 if (!parent) 490 goto err; 491 492 if (!strncmp(parent, "/usb", 4)) { 493 /* skip root hub name and device. use device interface */ 494 while (*++parent && *parent != '/'); 495 if (*parent) 496 while (*++parent && *parent != '/'); 497 if (!*parent) 498 goto err; 499 slash = strchr(++parent, '/'); 500 if (!slash) 501 goto err; 502 width = slash - parent; 503 if (width <= 0) 504 goto err; 505 506 if (asprintf(&links[link_num], "/dev/usb/%s%.*s", uevent->subsystem, width, parent) > 0) 507 link_num++; 508 else 509 links[link_num] = NULL; 510 mkdir("/dev/usb", 0755); 511 } 512 else { 513 goto err; 514 } 515 516 return links; 517err: 518 free(links); 519 return NULL; 520} 521 522// replaces any unacceptable characters with '_', the 523// length of the resulting string is equal to the input string 524void sanitize_partition_name(char* s) { 525 const char* accept = 526 "abcdefghijklmnopqrstuvwxyz" 527 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 528 "0123456789" 529 "_-."; 530 531 if (!s) return; 532 533 while (*s) { 534 s += strspn(s, accept); 535 if (*s) *s++ = '_'; 536 } 537} 538 539char** get_block_device_symlinks(struct uevent* uevent) { 540 const char *device; 541 struct platform_node *pdev; 542 const char *slash; 543 const char *type; 544 char buf[256]; 545 char link_path[256]; 546 int link_num = 0; 547 char *p; 548 549 pdev = find_platform_device(uevent->path); 550 if (pdev) { 551 device = pdev->name; 552 type = "platform"; 553 } else if (!find_pci_device_prefix(uevent->path, buf, sizeof(buf))) { 554 device = buf; 555 type = "pci"; 556 } else if (!find_vbd_device_prefix(uevent->path, buf, sizeof(buf))) { 557 device = buf; 558 type = "vbd"; 559 } else { 560 return NULL; 561 } 562 563 char **links = (char**) malloc(sizeof(char *) * 4); 564 if (!links) 565 return NULL; 566 memset(links, 0, sizeof(char *) * 4); 567 568 LOG(VERBOSE) << "found " << type << " device " << device; 569 570 snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device); 571 572 if (uevent->partition_name) { 573 p = strdup(uevent->partition_name); 574 sanitize_partition_name(p); 575 if (strcmp(uevent->partition_name, p)) { 576 LOG(VERBOSE) << "Linking partition '" << uevent->partition_name << "' as '" << p << "'"; 577 } 578 if (asprintf(&links[link_num], "%s/by-name/%s", link_path, p) > 0) 579 link_num++; 580 else 581 links[link_num] = NULL; 582 free(p); 583 } 584 585 if (uevent->partition_num >= 0) { 586 if (asprintf(&links[link_num], "%s/by-num/p%d", link_path, uevent->partition_num) > 0) 587 link_num++; 588 else 589 links[link_num] = NULL; 590 } 591 592 slash = strrchr(uevent->path, '/'); 593 if (asprintf(&links[link_num], "%s/%s", link_path, slash + 1) > 0) 594 link_num++; 595 else 596 links[link_num] = NULL; 597 598 return links; 599} 600 601static void make_link_init(const char* oldpath, const char* newpath) { 602 const char* slash = strrchr(newpath, '/'); 603 if (!slash) return; 604 605 if (mkdir_recursive(dirname(newpath), 0755)) { 606 PLOG(ERROR) << "Failed to create directory " << dirname(newpath); 607 } 608 609 if (symlink(oldpath, newpath) && errno != EEXIST) { 610 PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath; 611 } 612} 613 614static void remove_link(const char* oldpath, const char* newpath) { 615 std::string path; 616 if (android::base::Readlink(newpath, &path) && path == oldpath) unlink(newpath); 617} 618 619static void handle_device(const char *action, const char *devpath, 620 const char *path, int block, int major, int minor, char **links) 621{ 622 if(!strcmp(action, "add")) { 623 make_device(devpath, path, block, major, minor, (const char **)links); 624 if (links) { 625 for (int i = 0; links[i]; i++) { 626 make_link_init(devpath, links[i]); 627 } 628 } 629 } 630 631 if(!strcmp(action, "remove")) { 632 if (links) { 633 for (int i = 0; links[i]; i++) { 634 remove_link(devpath, links[i]); 635 } 636 } 637 unlink(devpath); 638 } 639 640 if (links) { 641 for (int i = 0; links[i]; i++) { 642 free(links[i]); 643 } 644 free(links); 645 } 646} 647 648static void handle_platform_device_event(struct uevent *uevent) 649{ 650 const char *path = uevent->path; 651 652 if (!strcmp(uevent->action, "add")) 653 add_platform_device(path); 654 else if (!strcmp(uevent->action, "remove")) 655 remove_platform_device(path); 656} 657 658static const char *parse_device_name(struct uevent *uevent, unsigned int len) 659{ 660 const char *name; 661 662 /* if it's not a /dev device, nothing else to do */ 663 if((uevent->major < 0) || (uevent->minor < 0)) 664 return NULL; 665 666 /* do we have a name? */ 667 name = strrchr(uevent->path, '/'); 668 if(!name) 669 return NULL; 670 name++; 671 672 /* too-long names would overrun our buffer */ 673 if(strlen(name) > len) { 674 LOG(ERROR) << "DEVPATH=" << name << " exceeds " << len << "-character limit on filename; ignoring event"; 675 return NULL; 676 } 677 678 return name; 679} 680 681#define DEVPATH_LEN 96 682#define MAX_DEV_NAME 64 683 684static void handle_block_device_event(struct uevent *uevent) 685{ 686 const char *base = "/dev/block/"; 687 const char *name; 688 char devpath[DEVPATH_LEN]; 689 char **links = NULL; 690 691 name = parse_device_name(uevent, MAX_DEV_NAME); 692 if (!name) 693 return; 694 695 snprintf(devpath, sizeof(devpath), "%s%s", base, name); 696 make_dir(base, 0755); 697 698 if (!strncmp(uevent->path, "/devices/", 9)) 699 links = get_block_device_symlinks(uevent); 700 701 handle_device(uevent->action, devpath, uevent->path, 1, 702 uevent->major, uevent->minor, links); 703} 704 705static bool assemble_devpath(char *devpath, const char *dirname, 706 const char *devname) 707{ 708 int s = snprintf(devpath, DEVPATH_LEN, "%s/%s", dirname, devname); 709 if (s < 0) { 710 PLOG(ERROR) << "failed to assemble device path; ignoring event"; 711 return false; 712 } else if (s >= DEVPATH_LEN) { 713 LOG(ERROR) << dirname << "/" << devname 714 << " exceeds " << DEVPATH_LEN << "-character limit on path; ignoring event"; 715 return false; 716 } 717 return true; 718} 719 720static void mkdir_recursive_for_devpath(const char *devpath) 721{ 722 char dir[DEVPATH_LEN]; 723 char *slash; 724 725 strcpy(dir, devpath); 726 slash = strrchr(dir, '/'); 727 *slash = '\0'; 728 mkdir_recursive(dir, 0755); 729} 730 731static void handle_generic_device_event(struct uevent *uevent) 732{ 733 const char *base; 734 const char *name; 735 char devpath[DEVPATH_LEN] = {0}; 736 char **links = NULL; 737 738 name = parse_device_name(uevent, MAX_DEV_NAME); 739 if (!name) 740 return; 741 742 struct ueventd_subsystem *subsystem = 743 ueventd_subsystem_find_by_name(uevent->subsystem); 744 745 if (subsystem) { 746 const char *devname; 747 748 switch (subsystem->devname_src) { 749 case DEVNAME_UEVENT_DEVNAME: 750 devname = uevent->device_name; 751 break; 752 753 case DEVNAME_UEVENT_DEVPATH: 754 devname = name; 755 break; 756 757 default: 758 LOG(ERROR) << uevent->subsystem << " subsystem's devpath option is not set; ignoring event"; 759 return; 760 } 761 762 if (!assemble_devpath(devpath, subsystem->dirname, devname)) 763 return; 764 mkdir_recursive_for_devpath(devpath); 765 } else if (!strncmp(uevent->subsystem, "usb", 3)) { 766 if (!strcmp(uevent->subsystem, "usb")) { 767 if (uevent->device_name) { 768 if (!assemble_devpath(devpath, "/dev", uevent->device_name)) 769 return; 770 mkdir_recursive_for_devpath(devpath); 771 } 772 else { 773 /* This imitates the file system that would be created 774 * if we were using devfs instead. 775 * Minors are broken up into groups of 128, starting at "001" 776 */ 777 int bus_id = uevent->minor / 128 + 1; 778 int device_id = uevent->minor % 128 + 1; 779 /* build directories */ 780 make_dir("/dev/bus", 0755); 781 make_dir("/dev/bus/usb", 0755); 782 snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id); 783 make_dir(devpath, 0755); 784 snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id); 785 } 786 } else { 787 /* ignore other USB events */ 788 return; 789 } 790 } else if (!strncmp(uevent->subsystem, "graphics", 8)) { 791 base = "/dev/graphics/"; 792 make_dir(base, 0755); 793 } else if (!strncmp(uevent->subsystem, "drm", 3)) { 794 base = "/dev/dri/"; 795 make_dir(base, 0755); 796 } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) { 797 base = "/dev/oncrpc/"; 798 make_dir(base, 0755); 799 } else if (!strncmp(uevent->subsystem, "adsp", 4)) { 800 base = "/dev/adsp/"; 801 make_dir(base, 0755); 802 } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) { 803 base = "/dev/msm_camera/"; 804 make_dir(base, 0755); 805 } else if(!strncmp(uevent->subsystem, "input", 5)) { 806 base = "/dev/input/"; 807 make_dir(base, 0755); 808 } else if(!strncmp(uevent->subsystem, "mtd", 3)) { 809 base = "/dev/mtd/"; 810 make_dir(base, 0755); 811 } else if(!strncmp(uevent->subsystem, "sound", 5)) { 812 base = "/dev/snd/"; 813 make_dir(base, 0755); 814 } else 815 base = "/dev/"; 816 links = get_character_device_symlinks(uevent); 817 818 if (!devpath[0]) 819 snprintf(devpath, sizeof(devpath), "%s%s", base, name); 820 821 handle_device(uevent->action, devpath, uevent->path, 0, 822 uevent->major, uevent->minor, links); 823} 824 825static void handle_device_event(struct uevent *uevent) 826{ 827 if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online")) 828 fixup_sys_perms(uevent->path, uevent->subsystem); 829 830 if (!strncmp(uevent->subsystem, "block", 5)) { 831 handle_block_device_event(uevent); 832 } else if (!strncmp(uevent->subsystem, "platform", 8)) { 833 handle_platform_device_event(uevent); 834 } else { 835 handle_generic_device_event(uevent); 836 } 837} 838 839static void load_firmware(uevent* uevent, const std::string& root, 840 int fw_fd, size_t fw_size, 841 int loading_fd, int data_fd) { 842 // Start transfer. 843 android::base::WriteFully(loading_fd, "1", 1); 844 845 // Copy the firmware. 846 int rc = sendfile(data_fd, fw_fd, nullptr, fw_size); 847 if (rc == -1) { 848 PLOG(ERROR) << "firmware: sendfile failed { '" << root << "', '" << uevent->firmware << "' }"; 849 } 850 851 // Tell the firmware whether to abort or commit. 852 const char* response = (rc != -1) ? "0" : "-1"; 853 android::base::WriteFully(loading_fd, response, strlen(response)); 854} 855 856static int is_booting() { 857 return access("/dev/.booting", F_OK) == 0; 858} 859 860static void process_firmware_event(uevent* uevent) { 861 int booting = is_booting(); 862 863 LOG(INFO) << "firmware: loading '" << uevent->firmware << "' for '" << uevent->path << "'"; 864 865 std::string root = android::base::StringPrintf("/sys%s", uevent->path); 866 std::string loading = root + "/loading"; 867 std::string data = root + "/data"; 868 869 android::base::unique_fd loading_fd(open(loading.c_str(), O_WRONLY|O_CLOEXEC)); 870 if (loading_fd == -1) { 871 PLOG(ERROR) << "couldn't open firmware loading fd for " << uevent->firmware; 872 return; 873 } 874 875 android::base::unique_fd data_fd(open(data.c_str(), O_WRONLY|O_CLOEXEC)); 876 if (data_fd == -1) { 877 PLOG(ERROR) << "couldn't open firmware data fd for " << uevent->firmware; 878 return; 879 } 880 881try_loading_again: 882 for (size_t i = 0; i < arraysize(firmware_dirs); i++) { 883 std::string file = android::base::StringPrintf("%s/%s", firmware_dirs[i], uevent->firmware); 884 android::base::unique_fd fw_fd(open(file.c_str(), O_RDONLY|O_CLOEXEC)); 885 struct stat sb; 886 if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) { 887 load_firmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd); 888 return; 889 } 890 } 891 892 if (booting) { 893 // If we're not fully booted, we may be missing 894 // filesystems needed for firmware, wait and retry. 895 std::this_thread::sleep_for(100ms); 896 booting = is_booting(); 897 goto try_loading_again; 898 } 899 900 LOG(ERROR) << "firmware: could not find firmware for " << uevent->firmware; 901 902 // Write "-1" as our response to the kernel's firmware request, since we have nothing for it. 903 write(loading_fd, "-1", 2); 904} 905 906static void handle_firmware_event(uevent* uevent) { 907 if (strcmp(uevent->subsystem, "firmware")) return; 908 if (strcmp(uevent->action, "add")) return; 909 910 // Loading the firmware in a child means we can do that in parallel... 911 // (We ignore SIGCHLD rather than wait for our children.) 912 pid_t pid = fork(); 913 if (pid == 0) { 914 Timer t; 915 process_firmware_event(uevent); 916 LOG(INFO) << "loading " << uevent->path << " took " << t; 917 _exit(EXIT_SUCCESS); 918 } else if (pid == -1) { 919 PLOG(ERROR) << "could not fork to process firmware event for " << uevent->firmware; 920 } 921} 922 923static bool inline should_stop_coldboot(coldboot_action_t act) 924{ 925 return (act == COLDBOOT_STOP || act == COLDBOOT_FINISH); 926} 927 928#define UEVENT_MSG_LEN 2048 929 930static inline coldboot_action_t handle_device_fd_with( 931 std::function<coldboot_action_t(uevent* uevent)> handle_uevent) 932{ 933 char msg[UEVENT_MSG_LEN+2]; 934 int n; 935 while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) { 936 if(n >= UEVENT_MSG_LEN) /* overflow -- discard */ 937 continue; 938 939 msg[n] = '\0'; 940 msg[n+1] = '\0'; 941 942 struct uevent uevent; 943 parse_event(msg, &uevent); 944 coldboot_action_t act = handle_uevent(&uevent); 945 if (should_stop_coldboot(act)) 946 return act; 947 } 948 949 return COLDBOOT_CONTINUE; 950} 951 952coldboot_action_t handle_device_fd(coldboot_callback fn) 953{ 954 coldboot_action_t ret = handle_device_fd_with( 955 [&](uevent* uevent) -> coldboot_action_t { 956 if (selinux_status_updated() > 0) { 957 struct selabel_handle *sehandle2; 958 sehandle2 = selinux_android_file_context_handle(); 959 if (sehandle2) { 960 selabel_close(sehandle); 961 sehandle = sehandle2; 962 } 963 } 964 965 // default is to always create the devices 966 coldboot_action_t act = COLDBOOT_CREATE; 967 if (fn) { 968 act = fn(uevent); 969 } 970 971 if (act == COLDBOOT_CREATE || act == COLDBOOT_STOP) { 972 handle_device_event(uevent); 973 handle_firmware_event(uevent); 974 } 975 976 return act; 977 }); 978 979 return ret; 980} 981 982/* Coldboot walks parts of the /sys tree and pokes the uevent files 983** to cause the kernel to regenerate device add events that happened 984** before init's device manager was started 985** 986** We drain any pending events from the netlink socket every time 987** we poke another uevent file to make sure we don't overrun the 988** socket's buffer. 989*/ 990 991static coldboot_action_t do_coldboot(DIR *d, coldboot_callback fn) 992{ 993 struct dirent *de; 994 int dfd, fd; 995 coldboot_action_t act = COLDBOOT_CONTINUE; 996 997 dfd = dirfd(d); 998 999 fd = openat(dfd, "uevent", O_WRONLY); 1000 if (fd >= 0) { 1001 write(fd, "add\n", 4); 1002 close(fd); 1003 act = handle_device_fd(fn); 1004 if (should_stop_coldboot(act)) 1005 return act; 1006 } 1007 1008 while (!should_stop_coldboot(act) && (de = readdir(d))) { 1009 DIR *d2; 1010 1011 if(de->d_type != DT_DIR || de->d_name[0] == '.') 1012 continue; 1013 1014 fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 1015 if(fd < 0) 1016 continue; 1017 1018 d2 = fdopendir(fd); 1019 if(d2 == 0) 1020 close(fd); 1021 else { 1022 act = do_coldboot(d2, fn); 1023 closedir(d2); 1024 } 1025 } 1026 1027 // default is always to continue looking for uevents 1028 return act; 1029} 1030 1031static coldboot_action_t coldboot(const char *path, coldboot_callback fn) 1032{ 1033 std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path), closedir); 1034 if (d) { 1035 return do_coldboot(d.get(), fn); 1036 } 1037 1038 return COLDBOOT_CONTINUE; 1039} 1040 1041void device_init(const char* path, coldboot_callback fn) { 1042 if (!sehandle) { 1043 sehandle = selinux_android_file_context_handle(); 1044 } 1045 // open uevent socket and selinux status only if it hasn't been 1046 // done before 1047 if (device_fd == -1) { 1048 /* is 256K enough? udev uses 16MB! */ 1049 device_fd.reset(uevent_open_socket(256 * 1024, true)); 1050 if (device_fd == -1) { 1051 return; 1052 } 1053 fcntl(device_fd, F_SETFL, O_NONBLOCK); 1054 selinux_status_open(true); 1055 } 1056 1057 if (access(COLDBOOT_DONE, F_OK) == 0) { 1058 LOG(VERBOSE) << "Skipping coldboot, already done!"; 1059 return; 1060 } 1061 1062 Timer t; 1063 coldboot_action_t act; 1064 if (!path) { 1065 act = coldboot("/sys/class", fn); 1066 if (!should_stop_coldboot(act)) { 1067 act = coldboot("/sys/block", fn); 1068 if (!should_stop_coldboot(act)) { 1069 act = coldboot("/sys/devices", fn); 1070 } 1071 } 1072 } else { 1073 act = coldboot(path, fn); 1074 } 1075 1076 // If we have a callback, then do as it says. If no, then the default is 1077 // to always create COLDBOOT_DONE file. 1078 if (!fn || (act == COLDBOOT_FINISH)) { 1079 close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000)); 1080 } 1081 1082 LOG(INFO) << "Coldboot took " << t; 1083} 1084 1085void device_close() { 1086 destroy_platform_devices(); 1087 device_fd.reset(); 1088 selinux_status_close(); 1089} 1090 1091int get_device_fd() { 1092 return device_fd; 1093} 1094