From f6e009ee2650d8812942aa7f5761e86402346739 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Thu, 21 Nov 2013 13:26:48 -0800 Subject: init: handle ueventd path truncation better Log an error before discarding problematic events, and add a missing truncation check to the usb subsystem's unique codepath Change-Id: I0d05aa287ffc63b46d1752d2a7409d35dc8caca7 Signed-off-by: Greg Hackmann --- init/devices.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'init/devices.c') diff --git a/init/devices.c b/init/devices.c index af88c5f..2551ca8 100644 --- a/init/devices.c +++ b/init/devices.c @@ -530,8 +530,11 @@ static const char *parse_device_name(struct uevent *uevent, unsigned int len) name++; /* too-long names would overrun our buffer */ - if(strlen(name) > len) + if(strlen(name) > len) { + ERROR("DEVPATH=%s exceeds %u-character limit on filename; ignoring event\n", + name, len); return NULL; + } return name; } @@ -576,7 +579,18 @@ static void handle_generic_device_event(struct uevent *uevent) * see drivers/base/core.c */ char *p = devpath; - snprintf(devpath, sizeof(devpath), "/dev/%s", uevent->device_name); + int s = snprintf(devpath, sizeof(devpath), "/dev/%s", + uevent->device_name); + if (s < 0) { + ERROR("failed to assemble device path (%s); ignoring event\n", + strerror(errno)); + return; + } else if ((size_t)s >= sizeof(devpath)) { + ERROR("/dev/%s exceeds %u-character limit on path; ignoring event\n", + uevent->device_name, sizeof(devpath)); + return; + } + /* skip leading /dev/ */ p += 5; /* build directories */ -- cgit v1.1 From 3312aa8379d877044def52f3b3be5c912a5e61a2 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Mon, 18 Nov 2013 15:24:40 -0800 Subject: init: add subsystem rules to ueventd.rc By default ueventd creates device nodes under /dev based on the ueventd DEVPATH. Several subsystems have special rules which are hardcoded in devices.c. Moving forward these special rules should go in ueventd.rc. Special rules have the syntax: subsystem devname (uevent_devname|uevent_devpath) [dirname ] Devices matching SUBSYSTEM= will be populated under . dirname is optional and defaults to /dev. If dirname is provided, must start with "/". If devname is uevent_devname, ueventd will create the device node as /DEVNAME. DEVNAME may include intermediate subdirectories, which ueventd will automatically create. If devname is uevent_devpath, ueventd will use the legacy behavior of computing DEVPATH_BASE=basepath(DEVPATH), and creating the device node as /DEVPATH_BASE. The new parsing code is based on init_parser.c, with small tweaks to handle commands which don't fall under a section header. Change-Id: I3bd1b59d7e62dfc9d289cf6ae889e237fb5bd7c5 Signed-off-by: Greg Hackmann --- init/devices.c | 87 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 29 deletions(-) (limited to 'init/devices.c') diff --git a/init/devices.c b/init/devices.c index 2551ca8..f7df453 100644 --- a/init/devices.c +++ b/init/devices.c @@ -44,6 +44,7 @@ #include #include "devices.h" +#include "ueventd_parser.h" #include "util.h" #include "log.h" @@ -560,48 +561,76 @@ static void handle_block_device_event(struct uevent *uevent) uevent->major, uevent->minor, links); } +#define DEVPATH_LEN 96 + +static bool assemble_devpath(char *devpath, const char *dirname, + const char *devname) +{ + int s = snprintf(devpath, DEVPATH_LEN, "%s/%s", dirname, devname); + if (s < 0) { + ERROR("failed to assemble device path (%s); ignoring event\n", + strerror(errno)); + return false; + } else if (s >= DEVPATH_LEN) { + ERROR("%s/%s exceeds %u-character limit on path; ignoring event\n", + dirname, devname, DEVPATH_LEN); + return false; + } + return true; +} + +static void mkdir_recursive_for_devpath(const char *devpath) +{ + char dir[DEVPATH_LEN]; + char *slash; + + strcpy(dir, devpath); + slash = strrchr(dir, '/'); + *slash = '\0'; + mkdir_recursive(dir, 0755); +} + static void handle_generic_device_event(struct uevent *uevent) { char *base; const char *name; - char devpath[96] = {0}; + char devpath[DEVPATH_LEN] = {0}; char **links = NULL; name = parse_device_name(uevent, 64); if (!name) return; - if (!strncmp(uevent->subsystem, "usb", 3)) { + struct ueventd_subsystem *subsystem = + ueventd_subsystem_find_by_name(uevent->subsystem); + + if (subsystem) { + const char *devname; + + switch (subsystem->devname_src) { + case DEVNAME_UEVENT_DEVNAME: + devname = uevent->device_name; + break; + + case DEVNAME_UEVENT_DEVPATH: + devname = name; + break; + + default: + ERROR("%s subsystem's devpath option is not set; ignoring event\n", + uevent->subsystem); + return; + } + + if (!assemble_devpath(devpath, subsystem->dirname, devname)) + return; + mkdir_recursive_for_devpath(devpath); + } else if (!strncmp(uevent->subsystem, "usb", 3)) { if (!strcmp(uevent->subsystem, "usb")) { if (uevent->device_name) { - /* - * create device node provided by kernel if present - * see drivers/base/core.c - */ - char *p = devpath; - int s = snprintf(devpath, sizeof(devpath), "/dev/%s", - uevent->device_name); - if (s < 0) { - ERROR("failed to assemble device path (%s); ignoring event\n", - strerror(errno)); - return; - } else if ((size_t)s >= sizeof(devpath)) { - ERROR("/dev/%s exceeds %u-character limit on path; ignoring event\n", - uevent->device_name, sizeof(devpath)); + if (!assemble_devpath(devpath, "/dev", uevent->device_name)) return; - } - - /* skip leading /dev/ */ - p += 5; - /* build directories */ - while (*p) { - if (*p == '/') { - *p = 0; - make_dir(devpath, 0755); - *p = '/'; - } - p++; - } + mkdir_recursive_for_devpath(devpath); } else { /* This imitates the file system that would be created -- cgit v1.1