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 #include <selinux/selinux.h> 25 26 #include <private/android_filesystem_config.h> 27 28 #include "ueventd.h" 29 #include "log.h" 30 #include "util.h" 31 #include "devices.h" 32 #include "ueventd_parser.h" 33 34 static char hardware[32]; 35 static unsigned revision = 0; 36 37 static void import_kernel_nv(char *name, int in_qemu) 38 { 39 if (*name != '\0') { 40 char *value = strchr(name, '='); 41 if (value != NULL) { 42 *value++ = 0; 43 if (!strcmp(name,"androidboot.hardware")) 44 { 45 strlcpy(hardware, value, sizeof(hardware)); 46 } 47 } 48 } 49 } 50 51 int ueventd_main(int argc, char **argv) 52 { 53 struct pollfd ufd; 54 int nr; 55 char tmp[32]; 56 57 /* 58 * init sets the umask to 077 for forked processes. We need to 59 * create files with exact permissions, without modification by 60 * the umask. 61 */ 62 umask(000); 63 64 /* Prevent fire-and-forget children from becoming zombies. 65 * If we should need to wait() for some children in the future 66 * (as opposed to none right now), double-forking here instead 67 * of ignoring SIGCHLD may be the better solution. 68 */ 69 signal(SIGCHLD, SIG_IGN); 70 71 open_devnull_stdio(); 72 klog_init(); 73 #if LOG_UEVENTS 74 /* Ensure we're at a logging level that will show the events */ 75 if (klog_get_level() < KLOG_INFO_LEVEL) { 76 klog_set_level(KLOG_INFO_LEVEL); 77 } 78 #endif 79 80 union selinux_callback cb; 81 cb.func_log = log_callback; 82 selinux_set_callback(SELINUX_CB_LOG, cb); 83 84 INFO("starting ueventd\n"); 85 86 /* Respect hardware passed in through the kernel cmd line. Here we will look 87 * for androidboot.hardware param in kernel cmdline, and save its value in 88 * hardware[]. */ 89 import_kernel_cmdline(0, import_kernel_nv); 90 91 get_hardware_name(hardware, &revision); 92 93 ueventd_parse_config_file("/ueventd.rc"); 94 95 snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware); 96 ueventd_parse_config_file(tmp); 97 98 device_init(); 99 100 ufd.events = POLLIN; 101 ufd.fd = get_device_fd(); 102 103 while(1) { 104 ufd.revents = 0; 105 nr = poll(&ufd, 1, -1); 106 if (nr <= 0) 107 continue; 108 if (ufd.revents & POLLIN) 109 handle_device_fd(); 110 } 111 } 112 113 static int get_android_id(const char *id) 114 { 115 unsigned int i; 116 for (i = 0; i < ARRAY_SIZE(android_ids); i++) 117 if (!strcmp(id, android_ids[i].name)) 118 return android_ids[i].aid; 119 return -1; 120 } 121 122 void set_device_permission(int nargs, char **args) 123 { 124 char *name; 125 char *attr = 0; 126 mode_t perm; 127 uid_t uid; 128 gid_t gid; 129 int prefix = 0; 130 int wildcard = 0; 131 char *endptr; 132 int ret; 133 char *tmp = 0; 134 135 if (nargs == 0) 136 return; 137 138 if (args[0][0] == '#') 139 return; 140 141 name = args[0]; 142 143 if (!strncmp(name,"/sys/", 5) && (nargs == 5)) { 144 INFO("/sys/ rule %s %s\n",args[0],args[1]); 145 attr = args[1]; 146 args++; 147 nargs--; 148 } 149 150 if (nargs != 4) { 151 ERROR("invalid line ueventd.rc line for '%s'\n", args[0]); 152 return; 153 } 154 155 /* If path starts with mtd@ lookup the mount number. */ 156 if (!strncmp(name, "mtd@", 4)) { 157 int n = mtd_name_to_number(name + 4); 158 if (n >= 0) 159 asprintf(&tmp, "/dev/mtd/mtd%d", n); 160 name = tmp; 161 } else { 162 int len = strlen(name); 163 char *wildcard_chr = strchr(name, '*'); 164 if ((name[len - 1] == '*') && 165 (wildcard_chr == (name + len - 1))) { 166 prefix = 1; 167 name[len - 1] = '\0'; 168 } else if (wildcard_chr) { 169 wildcard = 1; 170 } 171 } 172 173 perm = strtol(args[1], &endptr, 8); 174 if (!endptr || *endptr != '\0') { 175 ERROR("invalid mode '%s'\n", args[1]); 176 free(tmp); 177 return; 178 } 179 180 ret = get_android_id(args[2]); 181 if (ret < 0) { 182 ERROR("invalid uid '%s'\n", args[2]); 183 free(tmp); 184 return; 185 } 186 uid = ret; 187 188 ret = get_android_id(args[3]); 189 if (ret < 0) { 190 ERROR("invalid gid '%s'\n", args[3]); 191 free(tmp); 192 return; 193 } 194 gid = ret; 195 196 add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard); 197 free(tmp); 198 } 199