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