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