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 <ctype.h> 18 #include <fcntl.h> 19 #include <poll.h> 20 #include <signal.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include <android-base/stringprintf.h> 26 #include <private/android_filesystem_config.h> 27 #include <selinux/selinux.h> 28 29 #include "ueventd.h" 30 #include "log.h" 31 #include "util.h" 32 #include "devices.h" 33 #include "ueventd_parser.h" 34 #include "property_service.h" 35 36 int ueventd_main(int argc, char **argv) 37 { 38 /* 39 * init sets the umask to 077 for forked processes. We need to 40 * create files with exact permissions, without modification by 41 * the umask. 42 */ 43 umask(000); 44 45 /* Prevent fire-and-forget children from becoming zombies. 46 * If we should need to wait() for some children in the future 47 * (as opposed to none right now), double-forking here instead 48 * of ignoring SIGCHLD may be the better solution. 49 */ 50 signal(SIGCHLD, SIG_IGN); 51 52 open_devnull_stdio(); 53 klog_init(); 54 klog_set_level(KLOG_NOTICE_LEVEL); 55 56 NOTICE("ueventd started!\n"); 57 58 selinux_callback cb; 59 cb.func_log = selinux_klog_callback; 60 selinux_set_callback(SELINUX_CB_LOG, cb); 61 62 std::string hardware = property_get("ro.hardware"); 63 64 ueventd_parse_config_file("/ueventd.rc"); 65 ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware.c_str()).c_str()); 66 67 device_init(); 68 69 pollfd ufd; 70 ufd.events = POLLIN; 71 ufd.fd = get_device_fd(); 72 73 while (true) { 74 ufd.revents = 0; 75 int nr = poll(&ufd, 1, -1); 76 if (nr <= 0) { 77 continue; 78 } 79 if (ufd.revents & POLLIN) { 80 handle_device_fd(); 81 } 82 } 83 84 return 0; 85 } 86 87 static int get_android_id(const char *id) 88 { 89 unsigned int i; 90 for (i = 0; i < ARRAY_SIZE(android_ids); i++) 91 if (!strcmp(id, android_ids[i].name)) 92 return android_ids[i].aid; 93 return -1; 94 } 95 96 void set_device_permission(int nargs, char **args) 97 { 98 char *name; 99 char *attr = 0; 100 mode_t perm; 101 uid_t uid; 102 gid_t gid; 103 int prefix = 0; 104 int wildcard = 0; 105 char *endptr; 106 int ret; 107 char *tmp = 0; 108 109 if (nargs == 0) 110 return; 111 112 if (args[0][0] == '#') 113 return; 114 115 name = args[0]; 116 117 if (!strncmp(name,"/sys/", 5) && (nargs == 5)) { 118 INFO("/sys/ rule %s %s\n",args[0],args[1]); 119 attr = args[1]; 120 args++; 121 nargs--; 122 } 123 124 if (nargs != 4) { 125 ERROR("invalid line ueventd.rc line for '%s'\n", args[0]); 126 return; 127 } 128 129 /* If path starts with mtd@ lookup the mount number. */ 130 if (!strncmp(name, "mtd@", 4)) { 131 int n = mtd_name_to_number(name + 4); 132 if (n >= 0) 133 asprintf(&tmp, "/dev/mtd/mtd%d", n); 134 name = tmp; 135 } else { 136 int len = strlen(name); 137 char *wildcard_chr = strchr(name, '*'); 138 if ((name[len - 1] == '*') && 139 (wildcard_chr == (name + len - 1))) { 140 prefix = 1; 141 name[len - 1] = '\0'; 142 } else if (wildcard_chr) { 143 wildcard = 1; 144 } 145 } 146 147 perm = strtol(args[1], &endptr, 8); 148 if (!endptr || *endptr != '\0') { 149 ERROR("invalid mode '%s'\n", args[1]); 150 free(tmp); 151 return; 152 } 153 154 ret = get_android_id(args[2]); 155 if (ret < 0) { 156 ERROR("invalid uid '%s'\n", args[2]); 157 free(tmp); 158 return; 159 } 160 uid = ret; 161 162 ret = get_android_id(args[3]); 163 if (ret < 0) { 164 ERROR("invalid gid '%s'\n", args[3]); 165 free(tmp); 166 return; 167 } 168 gid = ret; 169 170 add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard); 171 free(tmp); 172 } 173