init: Add ueventd.rc parsing to ueventd
Change-Id: Iea53050d6c10e8cabf563e5d80e84eaf78873695
diff --git a/init/Android.mk b/init/Android.mk
index 9259fb0..9d8ca9c 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -14,7 +14,8 @@
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 3e1c524..fa96f7c 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 @@
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 @@
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 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 04cb0d3..0a7b28c 100644
--- a/init/list.h
+++ b/init/list.h
@@ -35,6 +35,9 @@
#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 5a2222a..d51ffde 100644
--- a/init/ueventd.c
+++ b/init/ueventd.c
@@ -15,22 +15,40 @@
*/
#include <poll.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <private/android_filesystem_config.h>
#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 @@
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 0000000..0dd8b4d
--- /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 <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+
+#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 0000000..48f9bb8
--- /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 5fcd2ec..2e47369 100644
--- a/init/util.h
+++ b/init/util.h
@@ -20,6 +20,8 @@
#include <sys/stat.h>
#include <sys/types.h>
+#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 ed13060..329be7f 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -40,6 +40,12 @@
$(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) : $(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 0000000..e69de29
--- /dev/null
+++ b/rootdir/etc/ueventd.goldfish.rc
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
new file mode 100644
index 0000000..46f640f
--- /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