ueventd.c revision eb6ffc765b4a2919bbabd3132bf2bd68a4966415
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <poll.h> 18#include <fcntl.h> 19#include <string.h> 20#include <stdlib.h> 21#include <stdio.h> 22#include <ctype.h> 23#include <signal.h> 24 25#include <private/android_filesystem_config.h> 26 27#include "ueventd.h" 28#include "log.h" 29#include "util.h" 30#include "devices.h" 31#include "ueventd_parser.h" 32 33static char hardware[32]; 34static unsigned revision = 0; 35 36static void import_kernel_nv(char *name, int in_qemu) 37{ 38 if (*name != '\0') { 39 char *value = strchr(name, '='); 40 if (value != NULL) { 41 *value++ = 0; 42 if (!strcmp(name,"androidboot.hardware")) 43 { 44 strlcpy(hardware, value, sizeof(hardware)); 45 } 46 } 47 } 48} 49 50int ueventd_main(int argc, char **argv) 51{ 52 struct pollfd ufd; 53 int nr; 54 char tmp[32]; 55 56 /* 57 * init sets the umask to 077 for forked processes. We need to 58 * create files with exact permissions, without modification by 59 * the umask. 60 */ 61 umask(000); 62 63 /* Prevent fire-and-forget children from becoming zombies. 64 * If we should need to wait() for some children in the future 65 * (as opposed to none right now), double-forking here instead 66 * of ignoring SIGCHLD may be the better solution. 67 */ 68 signal(SIGCHLD, SIG_IGN); 69 70 open_devnull_stdio(); 71 klog_init(); 72#if LOG_UEVENTS 73 /* Ensure we're at a logging level that will show the events */ 74 if (klog_get_level() < KLOG_INFO_LEVEL) { 75 klog_set_level(KLOG_INFO_LEVEL); 76 } 77#endif 78 79 INFO("starting ueventd\n"); 80 81 /* Respect hardware passed in through the kernel cmd line. Here we will look 82 * for androidboot.hardware param in kernel cmdline, and save its value in 83 * hardware[]. */ 84 import_kernel_cmdline(0, import_kernel_nv); 85 86 get_hardware_name(hardware, &revision); 87 88 ueventd_parse_config_file("/ueventd.rc"); 89 90 snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware); 91 ueventd_parse_config_file(tmp); 92 93 device_init(); 94 95 ufd.events = POLLIN; 96 ufd.fd = get_device_fd(); 97 98 while(1) { 99 ufd.revents = 0; 100 nr = poll(&ufd, 1, -1); 101 if (nr <= 0) 102 continue; 103 if (ufd.revents & POLLIN) 104 handle_device_fd(); 105 } 106} 107 108static int get_android_id(const char *id) 109{ 110 unsigned int i; 111 for (i = 0; i < ARRAY_SIZE(android_ids); i++) 112 if (!strcmp(id, android_ids[i].name)) 113 return android_ids[i].aid; 114 return -1; 115} 116 117void set_device_permission(int nargs, char **args) 118{ 119 char *name; 120 char *attr = 0; 121 mode_t perm; 122 uid_t uid; 123 gid_t gid; 124 int prefix = 0; 125 char *endptr; 126 int ret; 127 char *tmp = 0; 128 129 if (nargs == 0) 130 return; 131 132 if (args[0][0] == '#') 133 return; 134 135 name = args[0]; 136 137 if (!strncmp(name,"/sys/", 5) && (nargs == 5)) { 138 INFO("/sys/ rule %s %s\n",args[0],args[1]); 139 attr = args[1]; 140 args++; 141 nargs--; 142 } 143 144 if (nargs != 4) { 145 ERROR("invalid line ueventd.rc line for '%s'\n", args[0]); 146 return; 147 } 148 149 /* If path starts with mtd@ lookup the mount number. */ 150 if (!strncmp(name, "mtd@", 4)) { 151 int n = mtd_name_to_number(name + 4); 152 if (n >= 0) 153 asprintf(&tmp, "/dev/mtd/mtd%d", n); 154 name = tmp; 155 } else { 156 int len = strlen(name); 157 if (name[len - 1] == '*') { 158 prefix = 1; 159 name[len - 1] = '\0'; 160 } 161 } 162 163 perm = strtol(args[1], &endptr, 8); 164 if (!endptr || *endptr != '\0') { 165 ERROR("invalid mode '%s'\n", args[1]); 166 free(tmp); 167 return; 168 } 169 170 ret = get_android_id(args[2]); 171 if (ret < 0) { 172 ERROR("invalid uid '%s'\n", args[2]); 173 free(tmp); 174 return; 175 } 176 uid = ret; 177 178 ret = get_android_id(args[3]); 179 if (ret < 0) { 180 ERROR("invalid gid '%s'\n", args[3]); 181 free(tmp); 182 return; 183 } 184 gid = ret; 185 186 add_dev_perms(name, attr, perm, uid, gid, prefix); 187 free(tmp); 188} 189