From bc57d4ce925a62f14c28c55e0ff28af1114f12be Mon Sep 17 00:00:00 2001 From: Brian Swetland Date: Tue, 26 Oct 2010 15:09:43 -0700 Subject: init: support owner/permission setting for sysfs attributes of devices This should be much nicer than peppering init.rc with chown/chmod directives. Also, remove some dead code and obsolete comments. Change-Id: I10895f10a9cf2f1226c8d12976cd3db3743da9ec --- init/devices.c | 77 ++++++++++++++++++++++++++++++++------------------- init/devices.h | 3 +- init/ueventd.c | 13 +++++++-- init/ueventd_parser.h | 2 +- 4 files changed, 62 insertions(+), 33 deletions(-) (limited to 'init') diff --git a/init/devices.c b/init/devices.c index 8e12a97..e73efdf 100644 --- a/init/devices.c +++ b/init/devices.c @@ -84,6 +84,7 @@ static int open_uevent_socket(void) struct perms_ { char *name; + char *attr; mode_t perm; unsigned int uid; unsigned int gid; @@ -94,56 +95,69 @@ struct perm_node { struct perms_ dp; struct listnode plist; }; + +static list_declare(sys_perms); static list_declare(dev_perms); -/* - * Permission override when in emulator mode, must be parsed before - * system properties is initalized. - */ -int add_dev_perms(const char *name, mode_t perm, unsigned int uid, - unsigned int gid, unsigned short prefix) { - int size; - char *tmp = 0; - struct perm_node *node = malloc(sizeof (struct perm_node)); +int add_dev_perms(const char *name, const char *attr, + mode_t perm, unsigned int uid, unsigned int gid, + unsigned short prefix) { + struct perm_node *node = calloc(1, sizeof(*node)); if (!node) return -ENOMEM; - size = strlen(name) + 1; - if ((node->dp.name = malloc(size)) == NULL) + node->dp.name = strdup(name); + if (!node->dp.name) return -ENOMEM; - memcpy(node->dp.name, name, size); + if (attr) { + node->dp.attr = strdup(attr); + if (!node->dp.attr) + return -ENOMEM; + } + node->dp.perm = perm; node->dp.uid = uid; node->dp.gid = gid; node->dp.prefix = prefix; - list_add_tail(&dev_perms, &node->plist); + if (attr) + list_add_tail(&sys_perms, &node->plist); + else + list_add_tail(&dev_perms, &node->plist); + return 0; } -static int get_device_perm_inner(struct perms_ *perms, const char *path, - unsigned *uid, unsigned *gid, mode_t *perm) +void fixup_sys_perms(const char *upath) { - int i; - for(i = 0; perms[i].name; i++) { + char buf[512]; + struct listnode *node; + struct perms_ *dp; - if(perms[i].prefix) { - if(strncmp(path, perms[i].name, strlen(perms[i].name))) + /* upaths omit the "/sys" that paths in this list + * contain, so we add 4 when comparing... + */ + list_for_each(node, &sys_perms) { + dp = &(node_to_item(node, struct perm_node, plist))->dp; + if (dp->prefix) { + if (strncmp(upath, dp->name + 4, strlen(dp->name + 4))) continue; } else { - if(strcmp(path, perms[i].name)) + if (strcmp(upath, dp->name + 4)) continue; } - *uid = perms[i].uid; - *gid = perms[i].gid; - *perm = perms[i].perm; - return 0; + + if ((strlen(upath) + strlen(dp->attr) + 6) > sizeof(buf)) + return; + + sprintf(buf,"/sys%s/%s", upath, dp->attr); + INFO("fixup %s %d %d 0%o\n", buf, dp->uid, dp->gid, dp->perm); + chown(buf, dp->uid, dp->gid); + chmod(buf, dp->perm); } - return -1; } -/* First checks for emulator specific permissions specified in /proc/cmdline. */ static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid) { mode_t perm; @@ -175,7 +189,9 @@ static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid) return 0600; } -static void make_device(const char *path, int block, int major, int minor) +static void make_device(const char *path, + const char *upath, + int block, int major, int minor) { unsigned uid; unsigned gid; @@ -334,7 +350,10 @@ static void handle_device_event(struct uevent *uevent) int block; int i; - /* if it's not a /dev device, nothing to do */ + if (!strcmp(uevent->action,"add")) + fixup_sys_perms(uevent->path); + + /* if it's not a /dev device, nothing else to do */ if((uevent->major < 0) || (uevent->minor < 0)) return; @@ -411,7 +430,7 @@ static void handle_device_event(struct uevent *uevent) snprintf(devpath, sizeof(devpath), "%s%s", base, name); if(!strcmp(uevent->action, "add")) { - make_device(devpath, block, uevent->major, uevent->minor); + make_device(devpath, uevent->path, block, uevent->major, uevent->minor); if (links) { for (i = 0; links[i]; i++) make_link(devpath, links[i]); diff --git a/init/devices.h b/init/devices.h index 8593a1b..a84fa58 100644 --- a/init/devices.h +++ b/init/devices.h @@ -21,7 +21,8 @@ extern void handle_device_fd(); extern void device_init(void); -extern int add_dev_perms(const char *name, mode_t perm, unsigned int uid, +extern int add_dev_perms(const char *name, const char *attr, + mode_t perm, unsigned int uid, unsigned int gid, unsigned short prefix); int get_device_fd(); #endif /* _INIT_DEVICES_H */ diff --git a/init/ueventd.c b/init/ueventd.c index d51ffde..0e97be7 100644 --- a/init/ueventd.c +++ b/init/ueventd.c @@ -76,6 +76,7 @@ static int get_android_id(const char *id) void set_device_permission(int nargs, char **args) { char *name; + char *attr = 0; mode_t perm; uid_t uid; gid_t gid; @@ -90,12 +91,20 @@ void set_device_permission(int nargs, char **args) if (args[0][0] == '#') return; + name = args[0]; + + if (!strncmp(name,"/sys/", 5) && (nargs == 5)) { + INFO("/sys/ rule %s %s\n",args[0],args[1]); + attr = args[1]; + args++; + nargs--; + } + if (nargs != 4) { ERROR("invalid line ueventd.rc line for '%s'\n", args[0]); return; } - name = args[0]; /* If path starts with mtd@ lookup the mount number. */ if (!strncmp(name, "mtd@", 4)) { int n = mtd_name_to_number(name + 4); @@ -133,6 +142,6 @@ void set_device_permission(int nargs, char **args) } gid = ret; - add_dev_perms(name, perm, uid, gid, prefix); + add_dev_perms(name, attr, perm, uid, gid, prefix); free(tmp); } diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h index 48f9bb8..3684285 100644 --- a/init/ueventd_parser.h +++ b/init/ueventd_parser.h @@ -17,7 +17,7 @@ #ifndef _INIT_UEVENTD_PARSER_H_ #define _INIT_UEVENTD_PARSER_H_ -#define UEVENTD_PARSER_MAXARGS 4 +#define UEVENTD_PARSER_MAXARGS 5 int ueventd_parse_config_file(const char *fn); void set_device_permission(int nargs, char **args); -- cgit v1.1