init: Add ueventd.rc parsing to ueventd

Change-Id: Iea53050d6c10e8cabf563e5d80e84eaf78873695
This commit is contained in:
Colin Cross 2010-04-20 14:32:50 -07:00
parent f83d0b9af5
commit 44b65d047c
10 changed files with 315 additions and 158 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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 @@ 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);
}

76
init/ueventd_parser.c Normal file
View File

@ -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);
}

25
init/ueventd_parser.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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)/, \

View File

76
rootdir/ueventd.rc Normal file
View File

@ -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