diff --git a/init/Android.mk b/init/Android.mk index 9259fb02c..9d8ca9c3b 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -14,7 +14,8 @@ LOCAL_SRC_FILES:= \ keychords.c \ signal_handler.c \ init_parser.c \ - ueventd.c + ueventd.c \ + ueventd_parser.c ifeq ($(strip $(INIT_BOOTCHART)),true) LOCAL_SRC_FILES += bootchart.c diff --git a/init/devices.c b/init/devices.c index 3e1c524fe..fa96f7c7f 100644 --- a/init/devices.c +++ b/init/devices.c @@ -37,10 +37,8 @@ #include "log.h" #include "list.h" -#define CMDLINE_PREFIX "/dev" #define SYSFS_PREFIX "/sys" #define FIRMWARE_DIR "/etc/firmware" -#define MAX_QEMU_PERM 6 static int device_fd = -1; @@ -87,102 +85,21 @@ struct perms_ { unsigned int gid; unsigned short prefix; }; -static struct perms_ devperms[] = { - { "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/full", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/random", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 }, - { "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 }, - /* logger should be world writable (for logging) but not readable */ - { "/dev/log/", 0662, AID_ROOT, AID_LOG, 1 }, - - /* the msm hw3d client device node is world writable/readable. */ - { "/dev/msm_hw3dc", 0666, AID_ROOT, AID_ROOT, 0 }, - - /* gpu driver for adreno200 is globally accessible */ - { "/dev/kgsl", 0666, AID_ROOT, AID_ROOT, 0 }, - - /* these should not be world writable */ - { "/dev/diag", 0660, AID_RADIO, AID_RADIO, 0 }, - { "/dev/diag_arm9", 0660, AID_RADIO, AID_RADIO, 0 }, - { "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 }, - { "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 }, - { "/dev/ttyMSM0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 }, - { "/dev/ttyHS0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 }, - { "/dev/uinput", 0660, AID_SYSTEM, AID_BLUETOOTH, 0 }, - { "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 }, - { "/dev/tty0", 0660, AID_ROOT, AID_SYSTEM, 0 }, - { "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 }, - { "/dev/msm_hw3dm", 0660, AID_SYSTEM, AID_GRAPHICS, 0 }, - { "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 }, - { "/dev/eac", 0660, AID_ROOT, AID_AUDIO, 0 }, - { "/dev/cam", 0660, AID_ROOT, AID_CAMERA, 0 }, - { "/dev/pmem", 0660, AID_SYSTEM, AID_GRAPHICS, 0 }, - { "/dev/pmem_adsp", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 }, - { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 }, - { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/snd/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 }, - { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 }, - { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/akm8973_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/akm8973_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/bma150", 0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/cm3602", 0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 }, - { "/dev/lightsensor", 0640, AID_SYSTEM, AID_SYSTEM, 0 }, - { "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/audience_a1026", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/tpa2018d1", 0660, AID_SYSTEM, AID_AUDIO, 1 }, - { "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/msm_audio_ctl", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/vdec", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/q6venc", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/snd/dsp", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/snd/dsp1", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/snd/mixer", 0660, AID_SYSTEM, AID_AUDIO, 0 }, - { "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 }, - { "/dev/qemu_trace", 0666, AID_SYSTEM, AID_SYSTEM, 0 }, - { "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 }, - { "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 }, - { "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 }, - { "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 }, - /* CDMA radio interface MUX */ - { "/dev/ts0710mux", 0640, AID_RADIO, AID_RADIO, 1 }, - { "/dev/ppp", 0660, AID_RADIO, AID_VPN, 0 }, - { "/dev/tun", 0640, AID_VPN, AID_VPN, 0 }, - { NULL, 0, 0, 0, 0 }, -}; - -/* devperms_partners list and perm_node are for hardware specific /dev entries */ struct perm_node { struct perms_ dp; struct listnode plist; }; -list_declare(devperms_partners); +static list_declare(dev_perms); /* * Permission override when in emulator mode, must be parsed before * system properties is initalized. */ -static int qemu_perm_count; -static struct perms_ qemu_perms[MAX_QEMU_PERM + 1]; - -int add_devperms_partners(const char *name, mode_t perm, unsigned int uid, - unsigned int gid, unsigned short prefix) { +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)); if (!node) return -ENOMEM; @@ -197,51 +114,10 @@ int add_devperms_partners(const char *name, mode_t perm, unsigned int uid, node->dp.gid = gid; node->dp.prefix = prefix; - list_add_tail(&devperms_partners, &node->plist); + list_add_tail(&dev_perms, &node->plist); return 0; } -void qemu_init(void) { - qemu_perm_count = 0; - memset(&qemu_perms, 0, sizeof(qemu_perms)); -} - -static int qemu_perm(const char* name, mode_t perm, unsigned int uid, - unsigned int gid, unsigned short prefix) -{ - char *buf; - if (qemu_perm_count == MAX_QEMU_PERM) - return -ENOSPC; - - buf = malloc(strlen(name) + 1); - if (!buf) - return -errno; - - strlcpy(buf, name, strlen(name) + 1); - qemu_perms[qemu_perm_count].name = buf; - qemu_perms[qemu_perm_count].perm = perm; - qemu_perms[qemu_perm_count].uid = uid; - qemu_perms[qemu_perm_count].gid = gid; - qemu_perms[qemu_perm_count].prefix = prefix; - - qemu_perm_count++; - return 0; -} - -/* Permission overrides for emulator that are parsed from /proc/cmdline. */ -void qemu_cmdline(const char* name, const char *value) -{ - char *buf; - if (!strcmp(name, "android.ril")) { - /* cmd line params currently assume /dev/ prefix */ - if (asprintf(&buf, CMDLINE_PREFIX"/%s", value) == -1) { - return; - } - INFO("nani- buf:: %s\n", buf); - qemu_perm(buf, 0660, AID_RADIO, AID_ROOT, 0); - } -} - static int get_device_perm_inner(struct perms_ *perms, const char *path, unsigned *uid, unsigned *gid, mode_t *perm) { @@ -267,38 +143,32 @@ static int get_device_perm_inner(struct perms_ *perms, const char *path, static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid) { mode_t perm; + struct listnode *node; + struct perm_node *perm_node; + struct perms_ *dp; - if (get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) { - return perm; - } else if (get_device_perm_inner(devperms, path, uid, gid, &perm) == 0) { - return perm; - } else { - struct listnode *node; - struct perm_node *perm_node; - struct perms_ *dp; + /* search the perms list in reverse so that ueventd.$hardware can + * override ueventd.rc + */ + list_for_each_reverse(node, &dev_perms) { + perm_node = node_to_item(node, struct perm_node, plist); + dp = &perm_node->dp; - /* Check partners list. */ - list_for_each(node, &devperms_partners) { - perm_node = node_to_item(node, struct perm_node, plist); - dp = &perm_node->dp; - - if (dp->prefix) { - if (strncmp(path, dp->name, strlen(dp->name))) - continue; - } else { - if (strcmp(path, dp->name)) - continue; - } - /* Found perm in partner list. */ - *uid = dp->uid; - *gid = dp->gid; - return dp->perm; + if (dp->prefix) { + if (strncmp(path, dp->name, strlen(dp->name))) + continue; + } else { + if (strcmp(path, dp->name)) + continue; } - /* Default if nothing found. */ - *uid = 0; - *gid = 0; - return 0600; + *uid = dp->uid; + *gid = dp->gid; + return dp->perm; } + /* Default if nothing found. */ + *uid = 0; + *gid = 0; + return 0600; } static void make_device(const char *path, int block, int major, int minor) diff --git a/init/list.h b/init/list.h index 04cb0d370..0a7b28c8d 100644 --- a/init/list.h +++ b/init/list.h @@ -35,6 +35,9 @@ struct listnode #define list_for_each(node, list) \ for (node = (list)->next; node != (list); node = node->next) +#define list_for_each_reverse(node, list) \ + for (node = (list)->prev; node != (list); node = node->prev) + void list_init(struct listnode *list); void list_add_tail(struct listnode *list, struct listnode *item); void list_remove(struct listnode *item); diff --git a/init/ueventd.c b/init/ueventd.c index 5a2222aad..d51ffde0e 100644 --- a/init/ueventd.c +++ b/init/ueventd.c @@ -15,22 +15,40 @@ */ #include +#include +#include +#include +#include +#include +#include #include "ueventd.h" #include "log.h" #include "util.h" #include "devices.h" +#include "ueventd_parser.h" + +static char hardware[32]; +static unsigned revision = 0; int ueventd_main(int argc, char **argv) { struct pollfd ufd; int nr; + char tmp[32]; open_devnull_stdio(); log_init(); INFO("starting ueventd\n"); + get_hardware_name(hardware, &revision); + + ueventd_parse_config_file("/ueventd.rc"); + + snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware); + ueventd_parse_config_file(tmp); + device_init(); ufd.events = POLLIN; @@ -45,3 +63,76 @@ int ueventd_main(int argc, char **argv) handle_device_fd(); } } + +static int get_android_id(const char *id) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(android_ids); i++) + if (!strcmp(id, android_ids[i].name)) + return android_ids[i].aid; + return 0; +} + +void set_device_permission(int nargs, char **args) +{ + char *name; + mode_t perm; + uid_t uid; + gid_t gid; + int prefix = 0; + char *endptr; + int ret; + char *tmp = 0; + + if (nargs == 0) + return; + + if (args[0][0] == '#') + return; + + 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); + if (n >= 0) + asprintf(&tmp, "/dev/mtd/mtd%d", n); + name = tmp; + } else { + int len = strlen(name); + if (name[len - 1] == '*') { + prefix = 1; + name[len - 1] = '\0'; + } + } + + perm = strtol(args[1], &endptr, 8); + if (!endptr || *endptr != '\0') { + ERROR("invalid mode '%s'\n", args[1]); + free(tmp); + return; + } + + ret = get_android_id(args[2]); + if (ret < 0) { + ERROR("invalid uid '%s'\n", args[2]); + free(tmp); + return; + } + uid = ret; + + ret = get_android_id(args[3]); + if (ret < 0) { + ERROR("invalid gid '%s'\n", args[3]); + free(tmp); + return; + } + gid = ret; + + add_dev_perms(name, perm, uid, gid, prefix); + free(tmp); +} diff --git a/init/ueventd_parser.c b/init/ueventd_parser.c new file mode 100644 index 000000000..0dd8b4ddd --- /dev/null +++ b/init/ueventd_parser.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "ueventd_parser.h" +#include "parser.h" +#include "log.h" +#include "list.h" +#include "util.h" + +static void parse_line_device(struct parse_state *state, int nargs, char **args); + +static void parse_config(const char *fn, char *s) +{ + struct parse_state state; + char *args[UEVENTD_PARSER_MAXARGS]; + int nargs; + nargs = 0; + state.filename = fn; + state.line = 1; + state.ptr = s; + state.nexttoken = 0; + state.parse_line = parse_line_device; + for (;;) { + int token = next_token(&state); + switch (token) { + case T_EOF: + state.parse_line(&state, 0, 0); + return; + case T_NEWLINE: + if (nargs) { + state.parse_line(&state, nargs, args); + nargs = 0; + } + break; + case T_TEXT: + if (nargs < UEVENTD_PARSER_MAXARGS) { + args[nargs++] = state.text; + } + break; + } + } +} + +int ueventd_parse_config_file(const char *fn) +{ + char *data; + data = read_file(fn, 0); + if (!data) return -1; + + parse_config(fn, data); + DUMP(); + return 0; +} + +static void parse_line_device(struct parse_state* state, int nargs, char **args) +{ + set_device_permission(nargs, args); +} diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h new file mode 100644 index 000000000..48f9bb8c9 --- /dev/null +++ b/init/ueventd_parser.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _INIT_UEVENTD_PARSER_H_ +#define _INIT_UEVENTD_PARSER_H_ + +#define UEVENTD_PARSER_MAXARGS 4 + +int ueventd_parse_config_file(const char *fn); +void set_device_permission(int nargs, char **args); + +#endif diff --git a/init/util.h b/init/util.h index 5fcd2ec33..2e473698f 100644 --- a/init/util.h +++ b/init/util.h @@ -20,6 +20,8 @@ #include #include +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + static const char *coldboot_done = "/dev/.coldboot_done"; int mtd_name_to_number(const char *name); diff --git a/rootdir/Android.mk b/rootdir/Android.mk index ed13060d4..329be7f94 100644 --- a/rootdir/Android.mk +++ b/rootdir/Android.mk @@ -40,6 +40,12 @@ ALL_PREBUILT += $(file) $(INSTALLED_RAMDISK_TARGET): $(file) endif +file := $(TARGET_ROOT_OUT)/ueventd.rc +$(file) : $(LOCAL_PATH)/ueventd.rc | $(ACP) + $(transform-prebuilt-to-target) +ALL_PREBUILT += $(file) +$(INSTALLED_RAMDISK_TARGET): $(file) + # Just like /system/etc/init.goldfish.sh, the /init.godlfish.rc is here # to allow -user builds to properly run the dex pre-optimization pass in # the emulator. @@ -47,6 +53,13 @@ file := $(TARGET_ROOT_OUT)/init.goldfish.rc $(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP) $(transform-prebuilt-to-target) ALL_PREBUILT += $(file) +$(INSTALLED_RAMDISK_TARGET): $(file) + +file := $(TARGET_ROOT_OUT)/ueventd.goldfish.rc +$(file) : $(LOCAL_PATH)/etc/ueventd.goldfish.rc | $(ACP) + $(transform-prebuilt-to-target) +ALL_PREBUILT += $(file) +$(INSTALLED_RAMDISK_TARGET): $(file) # create some directories (some are mount points) DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \ diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc new file mode 100644 index 000000000..e69de29bb diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc new file mode 100644 index 000000000..46f640f18 --- /dev/null +++ b/rootdir/ueventd.rc @@ -0,0 +1,76 @@ +/dev/null 0666 root root +/dev/zero 0666 root root +/dev/full 0666 root root +/dev/ptmx 0666 root root +/dev/tty 0666 root root +/dev/random 0666 root root +/dev/urandom 0666 root root +/dev/ashmem 0666 root root +/dev/binder 0666 root root + +# logger should be world writable (for logging) but not readable +/dev/log/* 0662 root log + +# the msm hw3d client device node is world writable/readable. +/dev/msm_hw3dc 0666 root root + +# gpu driver for adreno200 is globally accessible +/dev/kgsl 0666 root root + +# these should not be world writable +/dev/diag 0660 radio radio +/dev/diag_arm9 0660 radio radio +/dev/android_adb 0660 adb adb +/dev/android_adb_enable 0660 adb adb +/dev/ttyMSM0 0600 bluetooth bluetooth +/dev/ttyHS0 0600 bluetooth bluetooth +/dev/uinput 0660 system bluetooth +/dev/alarm 0664 system radio +/dev/tty0 0660 root system +/dev/graphics/* 0660 root graphics +/dev/msm_hw3dm 0660 system graphics +/dev/input/* 0660 root input +/dev/eac 0660 root audio +/dev/cam 0660 root camera +/dev/pmem 0660 system graphics +/dev/pmem_adsp* 0660 system audio +/dev/pmem_camera* 0660 system camera +/dev/oncrpc/* 0660 root system +/dev/adsp/* 0660 system audio +/dev/snd/* 0660 system audio +/dev/mt9t013 0660 system system +/dev/msm_camera/* 0660 system system +/dev/akm8976_daemon 0640 compass system +/dev/akm8976_aot 0640 compass system +/dev/akm8973_daemon 0640 compass system +/dev/akm8973_aot 0640 compass system +/dev/bma150 0640 compass system +/dev/cm3602 0640 compass system +/dev/akm8976_pffd 0640 compass system +/dev/lightsensor 0640 system system +/dev/msm_pcm_out* 0660 system audio +/dev/msm_pcm_in* 0660 system audio +/dev/msm_pcm_ctl* 0660 system audio +/dev/msm_snd* 0660 system audio +/dev/msm_mp3* 0660 system audio +/dev/audience_a1026* 0660 system audio +/dev/tpa2018d1* 0660 system audio +/dev/msm_audpre 0660 system audio +/dev/msm_audio_ctl 0660 system audio +/dev/htc-acoustic 0660 system audio +/dev/vdec 0660 system audio +/dev/q6venc 0660 system audio +/dev/snd/dsp 0660 system audio +/dev/snd/dsp1 0660 system audio +/dev/snd/mixer 0660 system audio +/dev/smd0 0640 radio radio +/dev/qemu_trace 0666 system system +/dev/qmi 0640 radio radio +/dev/qmi0 0640 radio radio +/dev/qmi1 0640 radio radio +/dev/qmi2 0640 radio radio + +# CDMA radio interface MUX +/dev/ts0710mux* 0640 radio radio +/dev/ppp 0660 radio vpn +/dev/tun 0640 vpn vpn