1 /*
2 ** Copyright 2008, 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 #define LOG_TAG "installd"
17
18 #include <fcntl.h>
19 #include <selinux/android.h>
20 #include <selinux/avc.h>
21 #include <sys/capability.h>
22 #include <sys/fsuid.h>
23 #include <sys/prctl.h>
24 #include <sys/stat.h>
25
26 #include <android-base/logging.h>
27 #include <cutils/fs.h>
28 #include <cutils/properties.h>
29 #include <log/log.h> // TODO: Move everything to base::logging.
30 #include <private/android_filesystem_config.h>
31
32 #include "InstalldNativeService.h"
33 #include "globals.h"
34 #include "installd_constants.h"
35 #include "installd_deps.h" // Need to fill in requirements of commands.
36 #include "utils.h"
37
38 namespace android {
39 namespace installd {
40
41 // Check that installd-deps sizes match cutils sizes.
42 static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
43 static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
44
45 ////////////////////////
46 // Plug-in functions. //
47 ////////////////////////
48
get_property(const char * key,char * value,const char * default_value)49 int get_property(const char *key, char *value, const char *default_value) {
50 return property_get(key, value, default_value);
51 }
52
53 // Compute the output path of
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)54 bool calculate_oat_file_path(char path[PKG_PATH_MAX],
55 const char *oat_dir,
56 const char *apk_path,
57 const char *instruction_set) {
58 const char *file_name_start;
59 const char *file_name_end;
60
61 file_name_start = strrchr(apk_path, '/');
62 if (file_name_start == NULL) {
63 SLOGE("apk_path '%s' has no '/'s in it\n", apk_path);
64 return false;
65 }
66 file_name_end = strrchr(apk_path, '.');
67 if (file_name_end < file_name_start) {
68 SLOGE("apk_path '%s' has no extension\n", apk_path);
69 return false;
70 }
71
72 // Calculate file_name
73 int file_name_len = file_name_end - file_name_start - 1;
74 char file_name[file_name_len + 1];
75 memcpy(file_name, file_name_start + 1, file_name_len);
76 file_name[file_name_len] = '\0';
77
78 // <apk_parent_dir>/oat/<isa>/<file_name>.odex
79 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
80 return true;
81 }
82
83 /*
84 * Computes the odex file for the given apk_path and instruction_set.
85 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
86 *
87 * Returns false if it failed to determine the odex file path.
88 */
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)89 bool calculate_odex_file_path(char path[PKG_PATH_MAX],
90 const char *apk_path,
91 const char *instruction_set) {
92 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
93 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
94 SLOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
95 return false;
96 }
97
98 strcpy(path, apk_path);
99 char *end = strrchr(path, '/');
100 if (end == NULL) {
101 SLOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
102 return false;
103 }
104 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
105
106 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
107 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
108 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
109 end = strrchr(path, '.');
110 if (end == NULL) {
111 SLOGE("apk_path '%s' has no extension.\n", apk_path);
112 return false;
113 }
114 strcpy(end + 1, "odex");
115 return true;
116 }
117
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)118 bool create_cache_path(char path[PKG_PATH_MAX],
119 const char *src,
120 const char *instruction_set) {
121 /* demand that we are an absolute path */
122 if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
123 return false;
124 }
125
126 size_t srclen = strlen(src);
127
128 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
129 return false;
130 }
131
132 size_t dstlen =
133 android_data_dir.len +
134 strlen(DALVIK_CACHE) +
135 1 +
136 strlen(instruction_set) +
137 srclen +
138 strlen(DALVIK_CACHE_POSTFIX) + 2;
139
140 if (dstlen > PKG_PATH_MAX) {
141 return false;
142 }
143
144 sprintf(path,"%s%s/%s/%s",
145 android_data_dir.path,
146 DALVIK_CACHE,
147 instruction_set,
148 src + 1 /* skip the leading / */);
149
150 char* tmp =
151 path +
152 android_data_dir.len +
153 strlen(DALVIK_CACHE) +
154 1 +
155 strlen(instruction_set) + 1;
156
157 for(; *tmp; tmp++) {
158 if (*tmp == '/') {
159 *tmp = '@';
160 }
161 }
162
163 strcat(path, DALVIK_CACHE_POSTFIX);
164 return true;
165 }
166
initialize_globals()167 static bool initialize_globals() {
168 const char* data_path = getenv("ANDROID_DATA");
169 if (data_path == nullptr) {
170 SLOGE("Could not find ANDROID_DATA");
171 return false;
172 }
173 const char* root_path = getenv("ANDROID_ROOT");
174 if (root_path == nullptr) {
175 SLOGE("Could not find ANDROID_ROOT");
176 return false;
177 }
178
179 return init_globals_from_data_and_root(data_path, root_path);
180 }
181
initialize_directories()182 static int initialize_directories() {
183 int res = -1;
184
185 // Read current filesystem layout version to handle upgrade paths
186 char version_path[PATH_MAX];
187 snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
188
189 int oldVersion;
190 if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
191 oldVersion = 0;
192 }
193 int version = oldVersion;
194
195 if (version < 2) {
196 SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
197 version = 2;
198 }
199
200 if (ensure_config_user_dirs(0) == -1) {
201 SLOGE("Failed to setup misc for user 0");
202 goto fail;
203 }
204
205 if (version == 2) {
206 SLOGD("Upgrading to /data/misc/user directories");
207
208 char misc_dir[PATH_MAX];
209 snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
210
211 char keychain_added_dir[PATH_MAX];
212 snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
213
214 char keychain_removed_dir[PATH_MAX];
215 snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
216
217 DIR *dir;
218 struct dirent *dirent;
219 dir = opendir("/data/user");
220 if (dir != NULL) {
221 while ((dirent = readdir(dir))) {
222 const char *name = dirent->d_name;
223
224 // skip "." and ".."
225 if (name[0] == '.') {
226 if (name[1] == 0) continue;
227 if ((name[1] == '.') && (name[2] == 0)) continue;
228 }
229
230 uint32_t user_id = atoi(name);
231
232 // /data/misc/user/<user_id>
233 if (ensure_config_user_dirs(user_id) == -1) {
234 goto fail;
235 }
236
237 char misc_added_dir[PATH_MAX];
238 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
239
240 char misc_removed_dir[PATH_MAX];
241 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
242
243 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
244 gid_t gid = uid;
245 if (access(keychain_added_dir, F_OK) == 0) {
246 if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
247 SLOGE("Some files failed to copy");
248 }
249 }
250 if (access(keychain_removed_dir, F_OK) == 0) {
251 if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
252 SLOGE("Some files failed to copy");
253 }
254 }
255 }
256 closedir(dir);
257
258 if (access(keychain_added_dir, F_OK) == 0) {
259 delete_dir_contents(keychain_added_dir, 1, 0);
260 }
261 if (access(keychain_removed_dir, F_OK) == 0) {
262 delete_dir_contents(keychain_removed_dir, 1, 0);
263 }
264 }
265
266 version = 3;
267 }
268
269 // Persist layout version if changed
270 if (version != oldVersion) {
271 if (fs_write_atomic_int(version_path, version) == -1) {
272 SLOGE("Failed to save version to %s: %s", version_path, strerror(errno));
273 goto fail;
274 }
275 }
276
277 // Success!
278 res = 0;
279
280 fail:
281 return res;
282 }
283
log_callback(int type,const char * fmt,...)284 static int log_callback(int type, const char *fmt, ...) {
285 va_list ap;
286 int priority;
287
288 switch (type) {
289 case SELINUX_WARNING:
290 priority = ANDROID_LOG_WARN;
291 break;
292 case SELINUX_INFO:
293 priority = ANDROID_LOG_INFO;
294 break;
295 default:
296 priority = ANDROID_LOG_ERROR;
297 break;
298 }
299 va_start(ap, fmt);
300 LOG_PRI_VA(priority, "SELinux", fmt, ap);
301 va_end(ap);
302 return 0;
303 }
304
installd_main(const int argc ATTRIBUTE_UNUSED,char * argv[])305 static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
306 int ret;
307 int selinux_enabled = (is_selinux_enabled() > 0);
308
309 setenv("ANDROID_LOG_TAGS", "*:v", 1);
310 android::base::InitLogging(argv);
311
312 SLOGI("installd firing up");
313
314 union selinux_callback cb;
315 cb.func_log = log_callback;
316 selinux_set_callback(SELINUX_CB_LOG, cb);
317
318 if (!initialize_globals()) {
319 SLOGE("Could not initialize globals; exiting.\n");
320 exit(1);
321 }
322
323 if (initialize_directories() < 0) {
324 SLOGE("Could not create directories; exiting.\n");
325 exit(1);
326 }
327
328 if (selinux_enabled && selinux_status_open(true) < 0) {
329 SLOGE("Could not open selinux status; exiting.\n");
330 exit(1);
331 }
332
333 if ((ret = InstalldNativeService::start()) != android::OK) {
334 SLOGE("Unable to start InstalldNativeService: %d", ret);
335 exit(1);
336 }
337
338 IPCThreadState::self()->joinThreadPool();
339
340 LOG(INFO) << "installd shutting down";
341
342 return 0;
343 }
344
345 } // namespace installd
346 } // namespace android
347
main(const int argc,char * argv[])348 int main(const int argc, char *argv[]) {
349 return android::installd::installd_main(argc, argv);
350 }
351