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