• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 static char hardware[32];
34 static unsigned revision = 0;
35 
import_kernel_nv(char * name,int in_qemu)36 static 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 
ueventd_main(int argc,char ** argv)50 int 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 
73     INFO("starting ueventd\n");
74 
75     /* Respect hardware passed in through the kernel cmd line. Here we will look
76      * for androidboot.hardware param in kernel cmdline, and save its value in
77      * hardware[]. */
78     import_kernel_cmdline(0, import_kernel_nv);
79 
80     get_hardware_name(hardware, &revision);
81 
82     ueventd_parse_config_file("/ueventd.rc");
83 
84     snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
85     ueventd_parse_config_file(tmp);
86 
87     device_init();
88 
89     ufd.events = POLLIN;
90     ufd.fd = get_device_fd();
91 
92     while(1) {
93         ufd.revents = 0;
94         nr = poll(&ufd, 1, -1);
95         if (nr <= 0)
96             continue;
97         if (ufd.revents == POLLIN)
98                handle_device_fd();
99     }
100 }
101 
get_android_id(const char * id)102 static int get_android_id(const char *id)
103 {
104     unsigned int i;
105     for (i = 0; i < ARRAY_SIZE(android_ids); i++)
106         if (!strcmp(id, android_ids[i].name))
107             return android_ids[i].aid;
108     return -1;
109 }
110 
set_device_permission(int nargs,char ** args)111 void set_device_permission(int nargs, char **args)
112 {
113     char *name;
114     char *attr = 0;
115     mode_t perm;
116     uid_t uid;
117     gid_t gid;
118     int prefix = 0;
119     char *endptr;
120     int ret;
121     char *tmp = 0;
122 
123     if (nargs == 0)
124         return;
125 
126     if (args[0][0] == '#')
127         return;
128 
129     name = args[0];
130 
131     if (!strncmp(name,"/sys/", 5) && (nargs == 5)) {
132         INFO("/sys/ rule %s %s\n",args[0],args[1]);
133         attr = args[1];
134         args++;
135         nargs--;
136     }
137 
138     if (nargs != 4) {
139         ERROR("invalid line ueventd.rc line for '%s'\n", args[0]);
140         return;
141     }
142 
143     /* If path starts with mtd@ lookup the mount number. */
144     if (!strncmp(name, "mtd@", 4)) {
145         int n = mtd_name_to_number(name + 4);
146         if (n >= 0)
147             asprintf(&tmp, "/dev/mtd/mtd%d", n);
148         name = tmp;
149     } else {
150         int len = strlen(name);
151         if (name[len - 1] == '*') {
152             prefix = 1;
153             name[len - 1] = '\0';
154         }
155     }
156 
157     perm = strtol(args[1], &endptr, 8);
158     if (!endptr || *endptr != '\0') {
159         ERROR("invalid mode '%s'\n", args[1]);
160         free(tmp);
161         return;
162     }
163 
164     ret = get_android_id(args[2]);
165     if (ret < 0) {
166         ERROR("invalid uid '%s'\n", args[2]);
167         free(tmp);
168         return;
169     }
170     uid = ret;
171 
172     ret = get_android_id(args[3]);
173     if (ret < 0) {
174         ERROR("invalid gid '%s'\n", args[3]);
175         free(tmp);
176         return;
177     }
178     gid = ret;
179 
180     add_dev_perms(name, attr, perm, uid, gid, prefix);
181     free(tmp);
182 }
183