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