blob: 332bc5e17581f3083ce1563abfc5a9c7759b2594 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/*
2** Copyright 2008, The Android Open Source Project
3**
Jeff Sharkey19803802015-04-07 12:44:51 -07004** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -07007**
Jeff Sharkey19803802015-04-07 12:44:51 -07008** http://www.apache.org/licenses/LICENSE-2.0
Mike Lockwood94afecf2012-10-24 10:45:23 -07009**
Jeff Sharkey19803802015-04-07 12:44:51 -070010** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -070014** limitations under the License.
15*/
16
Andreas Gampe02d0de52015-11-11 20:43:16 -080017#include <fcntl.h>
Stephen Smalleybd558d62013-04-16 12:16:50 -040018#include <selinux/android.h>
19#include <selinux/avc.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080020#include <sys/capability.h>
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -070021#include <sys/fsuid.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080022#include <sys/prctl.h>
23#include <sys/socket.h>
24#include <sys/stat.h>
25
26#include <android-base/logging.h>
27#include <cutils/fs.h>
28#include <cutils/log.h> // TODO: Move everything to base::logging.
29#include <cutils/properties.h>
30#include <cutils/sockets.h>
31#include <private/android_filesystem_config.h>
32
Jeff Sharkey90874002016-12-05 11:18:55 -070033#include <InstalldNativeService.h>
34
Andreas Gampe02d0de52015-11-11 20:43:16 -080035#include <commands.h>
36#include <globals.h>
37#include <installd_constants.h>
38#include <installd_deps.h> // Need to fill in requirements of commands.
39#include <utils.h>
40
41#ifndef LOG_TAG
42#define LOG_TAG "installd"
43#endif
44#define SOCKET_PATH "installd"
Mike Lockwood94afecf2012-10-24 10:45:23 -070045
Mike Lockwood94afecf2012-10-24 10:45:23 -070046#define BUFFER_MAX 1024 /* input buffer for commands */
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -080047#define TOKEN_MAX 16 /* max number of arguments in buffer */
Mike Lockwood94afecf2012-10-24 10:45:23 -070048#define REPLY_MAX 256 /* largest reply allowed */
49
Andreas Gampe02d0de52015-11-11 20:43:16 -080050namespace android {
51namespace installd {
52
53// Check that installd-deps sizes match cutils sizes.
54static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
55static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
56
57////////////////////////
58// Plug-in functions. //
59////////////////////////
60
61int get_property(const char *key, char *value, const char *default_value) {
62 return property_get(key, value, default_value);
63}
64
65// Compute the output path of
66bool calculate_oat_file_path(char path[PKG_PATH_MAX],
67 const char *oat_dir,
68 const char *apk_path,
69 const char *instruction_set) {
Dan Austin63235022016-03-28 15:09:02 -070070 const char *file_name_start;
71 const char *file_name_end;
Andreas Gampe02d0de52015-11-11 20:43:16 -080072
73 file_name_start = strrchr(apk_path, '/');
74 if (file_name_start == NULL) {
75 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
76 return false;
77 }
78 file_name_end = strrchr(apk_path, '.');
79 if (file_name_end < file_name_start) {
80 ALOGE("apk_path '%s' has no extension\n", apk_path);
81 return false;
82 }
83
84 // Calculate file_name
85 int file_name_len = file_name_end - file_name_start - 1;
86 char file_name[file_name_len + 1];
87 memcpy(file_name, file_name_start + 1, file_name_len);
88 file_name[file_name_len] = '\0';
89
90 // <apk_parent_dir>/oat/<isa>/<file_name>.odex
91 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
92 return true;
93}
94
95/*
96 * Computes the odex file for the given apk_path and instruction_set.
97 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
98 *
99 * Returns false if it failed to determine the odex file path.
100 */
101bool calculate_odex_file_path(char path[PKG_PATH_MAX],
102 const char *apk_path,
103 const char *instruction_set) {
104 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
105 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
106 ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
107 return false;
108 }
109
110 strcpy(path, apk_path);
111 char *end = strrchr(path, '/');
112 if (end == NULL) {
113 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
114 return false;
115 }
116 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
117
118 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
119 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
120 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
121 end = strrchr(path, '.');
122 if (end == NULL) {
123 ALOGE("apk_path '%s' has no extension.\n", apk_path);
124 return false;
125 }
126 strcpy(end + 1, "odex");
127 return true;
128}
129
130bool create_cache_path(char path[PKG_PATH_MAX],
131 const char *src,
132 const char *instruction_set) {
Greg Kaiser00087b72016-03-14 13:29:10 -0700133 /* demand that we are an absolute path */
134 if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
Andreas Gampe02d0de52015-11-11 20:43:16 -0800135 return false;
136 }
137
Greg Kaiser00087b72016-03-14 13:29:10 -0700138 size_t srclen = strlen(src);
139
Andreas Gampe02d0de52015-11-11 20:43:16 -0800140 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
141 return false;
142 }
143
144 size_t dstlen =
145 android_data_dir.len +
146 strlen(DALVIK_CACHE) +
147 1 +
148 strlen(instruction_set) +
149 srclen +
150 strlen(DALVIK_CACHE_POSTFIX) + 2;
151
152 if (dstlen > PKG_PATH_MAX) {
153 return false;
154 }
155
David Brazdil249c1792016-09-06 15:35:28 +0100156 sprintf(path,"%s%s/%s/%s",
Andreas Gampe02d0de52015-11-11 20:43:16 -0800157 android_data_dir.path,
158 DALVIK_CACHE,
159 instruction_set,
David Brazdil249c1792016-09-06 15:35:28 +0100160 src + 1 /* skip the leading / */);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800161
162 char* tmp =
163 path +
164 android_data_dir.len +
165 strlen(DALVIK_CACHE) +
166 1 +
167 strlen(instruction_set) + 1;
168
169 for(; *tmp; tmp++) {
170 if (*tmp == '/') {
171 *tmp = '@';
172 }
173 }
174
David Brazdil249c1792016-09-06 15:35:28 +0100175 strcat(path, DALVIK_CACHE_POSTFIX);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800176 return true;
177}
178
179
Jeff Sharkey6fe28a02015-04-09 13:10:03 -0700180static char* parse_null(char* arg) {
181 if (strcmp(arg, "!") == 0) {
182 return nullptr;
183 } else {
184 return arg;
185 }
186}
187
Andreas Gampe02d0de52015-11-11 20:43:16 -0800188static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700189{
190 return 0;
191}
192
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700193static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
194 /* const char *uuid, const char *pkgname, userid_t userid, int flags,
Janis Danisevskiseecb2d22016-01-12 14:45:55 +0000195 appid_t appid, const char* seinfo, int target_sdk_version */
196 return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]),
197 atoi(arg[4]), arg[5], atoi(arg[6]));
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700198}
199
200static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
201 /* const char* uuid, const char* pkgName, userid_t userid, int flags,
202 appid_t appid, const char* seinfo */
203 return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]);
204}
205
Jeff Sharkeycc6281c2016-02-06 19:46:09 -0700206static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
207 /* const char *uuid, const char *pkgname, userid_t userid, int flags */
208 return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
209}
210
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700211static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600212 /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
213 return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700214}
215
216static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600217 /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
218 return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700219}
220
Andreas Gampe01ad5982016-03-09 16:27:29 -0800221// We use otapreopt_chroot to get into the chroot.
222static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot";
Andreas Gampe73dae112015-11-19 14:12:14 -0800223
Andreas Gampe548bdb92016-06-02 17:56:45 -0700224static int do_ota_dexopt(const char* args[DEXOPT_PARAM_COUNT],
225 char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
Andreas Gampe01ad5982016-03-09 16:27:29 -0800226 // Time to fork and run otapreopt.
227
228 // Check that the tool exists.
229 struct stat s;
230 if (stat(kOtaPreopt, &s) != 0) {
231 LOG(ERROR) << "Otapreopt chroot tool not found.";
232 return -1;
Andreas Gampe73dae112015-11-19 14:12:14 -0800233 }
Andreas Gampe01ad5982016-03-09 16:27:29 -0800234
235 pid_t pid = fork();
236 if (pid == 0) {
Andreas Gampe548bdb92016-06-02 17:56:45 -0700237 const char* argv[1 + DEXOPT_PARAM_COUNT + 1];
Andreas Gampe01ad5982016-03-09 16:27:29 -0800238 argv[0] = kOtaPreopt;
Andreas Gampe548bdb92016-06-02 17:56:45 -0700239
240 for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) {
241 argv[i + 1] = args[i];
Andreas Gampe01ad5982016-03-09 16:27:29 -0800242 }
Andreas Gampe548bdb92016-06-02 17:56:45 -0700243
244 argv[DEXOPT_PARAM_COUNT + 1] = nullptr;
Andreas Gampe01ad5982016-03-09 16:27:29 -0800245
246 execv(argv[0], (char * const *)argv);
247 PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed";
248 exit(99);
249 } else {
250 int res = wait_child(pid);
251 if (res == 0) {
252 ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
253 } else {
254 ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
255 }
256 return res;
257 }
Andreas Gampe73dae112015-11-19 14:12:14 -0800258}
259
Andreas Gampe548bdb92016-06-02 17:56:45 -0700260static int do_regular_dexopt(const char* args[DEXOPT_PARAM_COUNT],
261 char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
262 return dexopt(args);
263}
264
265using DexoptFn = int (*)(const char* args[DEXOPT_PARAM_COUNT],
266 char reply[REPLY_MAX]);
267
Andreas Gampe73dae112015-11-19 14:12:14 -0800268static int do_dexopt(char **arg, char reply[REPLY_MAX])
Mike Lockwood94afecf2012-10-24 10:45:23 -0700269{
Andreas Gampe548bdb92016-06-02 17:56:45 -0700270 const char* args[DEXOPT_PARAM_COUNT];
271 for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) {
272 CHECK(arg[i] != nullptr);
273 args[i] = arg[i];
Andreas Gampe73dae112015-11-19 14:12:14 -0800274 }
Andreas Gampe548bdb92016-06-02 17:56:45 -0700275
276 int dexopt_flags = atoi(arg[6]);
277 DexoptFn dexopt_fn;
278 if ((dexopt_flags & DEXOPT_OTA) != 0) {
279 dexopt_fn = do_ota_dexopt;
280 } else {
281 dexopt_fn = do_regular_dexopt;
282 }
283 return dexopt_fn(args, reply);
Andreas Gampe4d0f8252016-03-20 11:30:28 -0700284}
285
286static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
287{
288 uid_t uid = static_cast<uid_t>(atoi(arg[0]));
289 const char* pkgname = arg[1];
290 if (merge_profiles(uid, pkgname)) {
291 strncpy(reply, "true", REPLY_MAX);
292 } else {
293 strncpy(reply, "false", REPLY_MAX);
294 }
295 return 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700296}
297
David Sehr6727c2d2016-05-17 16:06:22 -0700298static int do_dump_profiles(char **arg, char reply[REPLY_MAX])
299{
300 uid_t uid = static_cast<uid_t>(atoi(arg[0]));
301 const char* pkgname = arg[1];
302 const char* dex_files = arg[2];
303 if (dump_profile(uid, pkgname, dex_files)) {
304 strncpy(reply, "true", REPLY_MAX);
305 } else {
306 strncpy(reply, "false", REPLY_MAX);
307 }
308 return 0;
309}
310
Andreas Gampe02d0de52015-11-11 20:43:16 -0800311static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Narayan Kamath091ea772014-11-10 15:03:46 +0000312{
313 return mark_boot_complete(arg[0] /* instruction set */);
314}
315
Andreas Gampe02d0de52015-11-11 20:43:16 -0800316static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700317{
Narayan Kamath1b400322014-04-11 13:17:00 +0100318 return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700319}
320
Andreas Gampe02d0de52015-11-11 20:43:16 -0800321static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700322{
Jeff Sharkey6fe28a02015-04-09 13:10:03 -0700323 return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700324}
325
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700326static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700327 int64_t codesize = 0;
328 int64_t datasize = 0;
329 int64_t cachesize = 0;
330 int64_t asecsize = 0;
331 int res = 0;
332
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600333 /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
334 const char* code_path */
335 res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
336 arg[5], &codesize, &datasize, &cachesize, &asecsize);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700337
338 /*
339 * Each int64_t can take up 22 characters printed out. Make sure it
340 * doesn't go over REPLY_MAX in the future.
341 */
342 snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
343 codesize, datasize, cachesize, asecsize);
344 return res;
345}
346
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600347static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
348 ino_t inode = 0;
349 int res = 0;
350
351 /* const char *uuid, const char *pkgname, int userid, int flags */
352 res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
353
Jeff Sharkey7240a152016-04-11 00:30:24 -0600354 snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600355 return res;
356}
357
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700358static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
359 /* const char* from_uuid, const char *to_uuid, const char *package_name,
Janis Danisevskiseecb2d22016-01-12 14:45:55 +0000360 const char *data_app_name, appid_t appid, const char* seinfo,
361 int target_sdk_version */
362 return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
363 atoi(arg[4]), arg[5], atoi(arg[6]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700364}
365
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600366static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Robin Lee095c7632014-04-25 15:05:19 +0100367{
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600368 /* const char *uuid, userid_t userid, int user_serial, int flags */
369 return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
Robin Lee095c7632014-04-25 15:05:19 +0100370}
371
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600372static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700373{
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600374 /* const char *uuid, userid_t userid, int flags */
375 return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700376}
377
Andreas Gampe02d0de52015-11-11 20:43:16 -0800378static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700379{
Jeff Sharkey6fe28a02015-04-09 13:10:03 -0700380 return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700381}
382
Andreas Gampe02d0de52015-11-11 20:43:16 -0800383static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +0100384{
385 return idmap(arg[0], arg[1], atoi(arg[2]));
386}
387
Andreas Gampe02d0de52015-11-11 20:43:16 -0800388static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -0800389{
390 /* oat_dir, instruction_set */
391 return create_oat_dir(arg[0], arg[1]);
392}
393
Andreas Gampe02d0de52015-11-11 20:43:16 -0800394static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -0800395{
396 /* oat_dir */
397 return rm_package_dir(arg[0]);
Alex Light43c5d302014-07-21 12:23:48 -0700398}
399
Calin Juravleedae6692016-03-23 13:55:31 +0000400static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
David Brazdild828d682016-03-08 12:50:20 +0000401{
402 /* package_name */
Calin Juravleedae6692016-03-23 13:55:31 +0000403 return clear_app_profiles(arg[0]);
404}
405
406static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
407{
408 /* package_name */
409 return destroy_app_profiles(arg[0]);
David Brazdild828d682016-03-08 12:50:20 +0000410}
411
Andreas Gampe02d0de52015-11-11 20:43:16 -0800412static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
Narayan Kamathd845c962015-06-04 13:20:27 +0100413{
414 /* relative_path, from_base, to_base */
415 return link_file(arg[0], arg[1], arg[2]);
416}
417
Andreas Gampee65b4fa2016-03-01 11:46:45 -0800418static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
419 // apk_path, instruction_set, oat_dir
420 return move_ab(arg[0], arg[1], arg[2]);
421}
422
Andreas Gampeb31206b2016-09-09 17:07:04 -0700423static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
424 // apk_path, instruction_set, oat_dir
425 return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1;
426}
427
Mike Lockwood94afecf2012-10-24 10:45:23 -0700428struct cmdinfo {
429 const char *name;
430 unsigned numargs;
431 int (*func)(char **arg, char reply[REPLY_MAX]);
432};
433
434struct cmdinfo cmds[] = {
435 { "ping", 0, do_ping },
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700436
Janis Danisevskiseecb2d22016-01-12 14:45:55 +0000437 { "create_app_data", 7, do_create_app_data },
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700438 { "restorecon_app_data", 6, do_restorecon_app_data },
Jeff Sharkeycc6281c2016-02-06 19:46:09 -0700439 { "migrate_app_data", 4, do_migrate_app_data },
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600440 { "clear_app_data", 5, do_clear_app_data },
441 { "destroy_app_data", 5, do_destroy_app_data },
Janis Danisevskiseecb2d22016-01-12 14:45:55 +0000442 { "move_complete_app", 7, do_move_complete_app },
Jeff Sharkey2f720f72016-04-10 20:51:40 -0600443 { "get_app_size", 6, do_get_app_size },
444 { "get_app_data_inode", 4, do_get_app_data_inode },
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700445
Jeff Sharkey379a12b2016-04-14 20:45:06 -0600446 { "create_user_data", 4, do_create_user_data },
447 { "destroy_user_data", 3, do_destroy_user_data },
448
Jeff Haob63d91f2016-03-16 15:59:25 -0700449 { "dexopt", 10, do_dexopt },
Narayan Kamath091ea772014-11-10 15:03:46 +0000450 { "markbootcomplete", 1, do_mark_boot_complete },
Narayan Kamath1b400322014-04-11 13:17:00 +0100451 { "rmdex", 2, do_rm_dex },
Jeff Sharkey6fe28a02015-04-09 13:10:03 -0700452 { "freecache", 2, do_free_cache },
Jeff Sharkey6fe28a02015-04-09 13:10:03 -0700453 { "linklib", 4, do_linklib },
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +0100454 { "idmap", 3, do_idmap },
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -0800455 { "createoatdir", 2, do_create_oat_dir },
Narayan Kamathd845c962015-06-04 13:20:27 +0100456 { "rmpackagedir", 1, do_rm_package_dir },
Calin Juravleedae6692016-03-23 13:55:31 +0000457 { "clear_app_profiles", 1, do_clear_app_profiles },
458 { "destroy_app_profiles", 1, do_destroy_app_profiles },
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -0700459 { "linkfile", 3, do_link_file },
Andreas Gampee65b4fa2016-03-01 11:46:45 -0800460 { "move_ab", 3, do_move_ab },
Andreas Gampe4d0f8252016-03-20 11:30:28 -0700461 { "merge_profiles", 2, do_merge_profiles },
David Sehr6727c2d2016-05-17 16:06:22 -0700462 { "dump_profiles", 3, do_dump_profiles },
Andreas Gampeb31206b2016-09-09 17:07:04 -0700463 { "delete_odex", 3, do_delete_odex },
Mike Lockwood94afecf2012-10-24 10:45:23 -0700464};
465
466static int readx(int s, void *_buf, int count)
467{
Jeff Sharkey19803802015-04-07 12:44:51 -0700468 char *buf = (char *) _buf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700469 int n = 0, r;
470 if (count < 0) return -1;
471 while (n < count) {
472 r = read(s, buf + n, count - n);
473 if (r < 0) {
474 if (errno == EINTR) continue;
475 ALOGE("read error: %s\n", strerror(errno));
476 return -1;
477 }
478 if (r == 0) {
479 ALOGE("eof\n");
480 return -1; /* EOF */
481 }
482 n += r;
483 }
484 return 0;
485}
486
487static int writex(int s, const void *_buf, int count)
488{
Jeff Sharkey19803802015-04-07 12:44:51 -0700489 const char *buf = (const char *) _buf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700490 int n = 0, r;
491 if (count < 0) return -1;
492 while (n < count) {
493 r = write(s, buf + n, count - n);
494 if (r < 0) {
495 if (errno == EINTR) continue;
496 ALOGE("write error: %s\n", strerror(errno));
497 return -1;
498 }
499 n += r;
500 }
501 return 0;
502}
503
504
505/* Tokenize the command buffer, locate a matching command,
506 * ensure that the required number of arguments are provided,
507 * call the function(), return the result.
508 */
509static int execute(int s, char cmd[BUFFER_MAX])
510{
511 char reply[REPLY_MAX];
512 char *arg[TOKEN_MAX+1];
513 unsigned i;
514 unsigned n = 0;
515 unsigned short count;
516 int ret = -1;
517
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700518 // ALOGI("execute('%s')\n", cmd);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700519
520 /* default reply is "" */
521 reply[0] = 0;
522
523 /* n is number of args (not counting arg[0]) */
524 arg[0] = cmd;
525 while (*cmd) {
526 if (isspace(*cmd)) {
527 *cmd++ = 0;
528 n++;
529 arg[n] = cmd;
530 if (n == TOKEN_MAX) {
531 ALOGE("too many arguments\n");
532 goto done;
533 }
534 }
Serguei Katkov62bb3852014-10-29 19:38:01 +0600535 if (*cmd) {
536 cmd++;
537 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700538 }
539
540 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
541 if (!strcmp(cmds[i].name,arg[0])) {
542 if (n != cmds[i].numargs) {
543 ALOGE("%s requires %d arguments (%d given)\n",
544 cmds[i].name, cmds[i].numargs, n);
545 } else {
546 ret = cmds[i].func(arg + 1, reply);
547 }
548 goto done;
549 }
550 }
551 ALOGE("unsupported command '%s'\n", arg[0]);
552
553done:
554 if (reply[0]) {
555 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
556 } else {
557 n = snprintf(cmd, BUFFER_MAX, "%d", ret);
558 }
559 if (n > BUFFER_MAX) n = BUFFER_MAX;
560 count = n;
561
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700562 // ALOGI("reply: '%s'\n", cmd);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700563 if (writex(s, &count, sizeof(count))) return -1;
564 if (writex(s, cmd, count)) return -1;
565 return 0;
566}
567
Andreas Gamped089ca12016-06-27 14:25:30 -0700568static bool initialize_globals() {
Andreas Gampe02d0de52015-11-11 20:43:16 -0800569 const char* data_path = getenv("ANDROID_DATA");
570 if (data_path == nullptr) {
571 ALOGE("Could not find ANDROID_DATA");
572 return false;
573 }
574 const char* root_path = getenv("ANDROID_ROOT");
575 if (root_path == nullptr) {
576 ALOGE("Could not find ANDROID_ROOT");
577 return false;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700578 }
579
Andreas Gampe02d0de52015-11-11 20:43:16 -0800580 return init_globals_from_data_and_root(data_path, root_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700581}
582
Andreas Gampe02d0de52015-11-11 20:43:16 -0800583static int initialize_directories() {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700584 int res = -1;
585
586 // Read current filesystem layout version to handle upgrade paths
587 char version_path[PATH_MAX];
588 snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
589
590 int oldVersion;
591 if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
592 oldVersion = 0;
593 }
594 int version = oldVersion;
595
Jeff Sharkeye02657d2016-01-13 09:37:46 -0700596 if (version < 2) {
597 SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
Mike Lockwood94afecf2012-10-24 10:45:23 -0700598 version = 2;
599 }
600
Robin Lee07053fc2014-04-29 19:42:01 +0100601 if (ensure_config_user_dirs(0) == -1) {
602 ALOGE("Failed to setup misc for user 0");
603 goto fail;
604 }
605
Robin Lee095c7632014-04-25 15:05:19 +0100606 if (version == 2) {
607 ALOGD("Upgrading to /data/misc/user directories");
608
Robin Lee60fd3fe2014-10-07 16:55:02 +0100609 char misc_dir[PATH_MAX];
610 snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
611
612 char keychain_added_dir[PATH_MAX];
613 snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
614
615 char keychain_removed_dir[PATH_MAX];
616 snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
617
Robin Lee095c7632014-04-25 15:05:19 +0100618 DIR *dir;
619 struct dirent *dirent;
Jeff Sharkeye02657d2016-01-13 09:37:46 -0700620 dir = opendir("/data/user");
Robin Lee095c7632014-04-25 15:05:19 +0100621 if (dir != NULL) {
622 while ((dirent = readdir(dir))) {
Robin Lee60fd3fe2014-10-07 16:55:02 +0100623 const char *name = dirent->d_name;
Robin Lee095c7632014-04-25 15:05:19 +0100624
Robin Lee60fd3fe2014-10-07 16:55:02 +0100625 // skip "." and ".."
626 if (name[0] == '.') {
627 if (name[1] == 0) continue;
628 if ((name[1] == '.') && (name[2] == 0)) continue;
629 }
630
631 uint32_t user_id = atoi(name);
632
633 // /data/misc/user/<user_id>
634 if (ensure_config_user_dirs(user_id) == -1) {
635 goto fail;
636 }
637
638 char misc_added_dir[PATH_MAX];
639 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
640
641 char misc_removed_dir[PATH_MAX];
642 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
643
644 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
645 gid_t gid = uid;
646 if (access(keychain_added_dir, F_OK) == 0) {
647 if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
648 ALOGE("Some files failed to copy");
Robin Lee095c7632014-04-25 15:05:19 +0100649 }
Robin Lee60fd3fe2014-10-07 16:55:02 +0100650 }
651 if (access(keychain_removed_dir, F_OK) == 0) {
652 if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
653 ALOGE("Some files failed to copy");
Robin Lee095c7632014-04-25 15:05:19 +0100654 }
655 }
656 }
657 closedir(dir);
Robin Lee095c7632014-04-25 15:05:19 +0100658
Robin Lee60fd3fe2014-10-07 16:55:02 +0100659 if (access(keychain_added_dir, F_OK) == 0) {
660 delete_dir_contents(keychain_added_dir, 1, 0);
Robin Lee07053fc2014-04-29 19:42:01 +0100661 }
Robin Lee60fd3fe2014-10-07 16:55:02 +0100662 if (access(keychain_removed_dir, F_OK) == 0) {
663 delete_dir_contents(keychain_removed_dir, 1, 0);
Robin Lee07053fc2014-04-29 19:42:01 +0100664 }
665 }
666
667 version = 3;
Robin Lee095c7632014-04-25 15:05:19 +0100668 }
669
Mike Lockwood94afecf2012-10-24 10:45:23 -0700670 // Persist layout version if changed
671 if (version != oldVersion) {
672 if (fs_write_atomic_int(version_path, version) == -1) {
673 ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
674 goto fail;
675 }
676 }
677
678 // Success!
679 res = 0;
680
681fail:
Mike Lockwood94afecf2012-10-24 10:45:23 -0700682 return res;
683}
684
Stephen Smalley7abb52b2014-03-26 09:30:37 -0400685static int log_callback(int type, const char *fmt, ...) {
686 va_list ap;
687 int priority;
688
689 switch (type) {
690 case SELINUX_WARNING:
691 priority = ANDROID_LOG_WARN;
692 break;
693 case SELINUX_INFO:
694 priority = ANDROID_LOG_INFO;
695 break;
696 default:
697 priority = ANDROID_LOG_ERROR;
698 break;
699 }
700 va_start(ap, fmt);
701 LOG_PRI_VA(priority, "SELinux", fmt, ap);
702 va_end(ap);
703 return 0;
704}
705
Andreas Gampe02d0de52015-11-11 20:43:16 -0800706static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700707 char buf[BUFFER_MAX];
708 struct sockaddr addr;
709 socklen_t alen;
Jeff Sharkey90874002016-12-05 11:18:55 -0700710 int lsocket, s, ret;
Stephen Smalleybd558d62013-04-16 12:16:50 -0400711 int selinux_enabled = (is_selinux_enabled() > 0);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700712
Jeff Sharkeye3637242015-04-08 20:56:42 -0700713 setenv("ANDROID_LOG_TAGS", "*:v", 1);
714 android::base::InitLogging(argv);
715
Mike Lockwood94afecf2012-10-24 10:45:23 -0700716 ALOGI("installd firing up\n");
717
Stephen Smalley7abb52b2014-03-26 09:30:37 -0400718 union selinux_callback cb;
719 cb.func_log = log_callback;
720 selinux_set_callback(SELINUX_CB_LOG, cb);
721
Andreas Gampe02d0de52015-11-11 20:43:16 -0800722 if (!initialize_globals()) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700723 ALOGE("Could not initialize globals; exiting.\n");
724 exit(1);
725 }
726
727 if (initialize_directories() < 0) {
728 ALOGE("Could not create directories; exiting.\n");
729 exit(1);
730 }
731
Stephen Smalleybd558d62013-04-16 12:16:50 -0400732 if (selinux_enabled && selinux_status_open(true) < 0) {
733 ALOGE("Could not open selinux status; exiting.\n");
734 exit(1);
735 }
736
Jeff Sharkey90874002016-12-05 11:18:55 -0700737 if ((ret = InstalldNativeService::start()) != android::OK) {
738 ALOGE("Unable to start InstalldNativeService: %d", ret);
739 exit(1);
740 }
741
Mike Lockwood94afecf2012-10-24 10:45:23 -0700742 lsocket = android_get_control_socket(SOCKET_PATH);
743 if (lsocket < 0) {
744 ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
745 exit(1);
746 }
747 if (listen(lsocket, 5)) {
748 ALOGE("Listen on socket failed: %s\n", strerror(errno));
749 exit(1);
750 }
751 fcntl(lsocket, F_SETFD, FD_CLOEXEC);
752
753 for (;;) {
754 alen = sizeof(addr);
755 s = accept(lsocket, &addr, &alen);
756 if (s < 0) {
757 ALOGE("Accept failed: %s\n", strerror(errno));
758 continue;
759 }
760 fcntl(s, F_SETFD, FD_CLOEXEC);
761
762 ALOGI("new connection\n");
763 for (;;) {
764 unsigned short count;
765 if (readx(s, &count, sizeof(count))) {
766 ALOGE("failed to read size\n");
767 break;
768 }
769 if ((count < 1) || (count >= BUFFER_MAX)) {
770 ALOGE("invalid size %d\n", count);
771 break;
772 }
773 if (readx(s, buf, count)) {
774 ALOGE("failed to read command\n");
775 break;
776 }
777 buf[count] = 0;
Stephen Smalleybd558d62013-04-16 12:16:50 -0400778 if (selinux_enabled && selinux_status_updated() > 0) {
779 selinux_android_seapp_context_reload();
780 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700781 if (execute(s, buf)) break;
782 }
783 ALOGI("closing connection\n");
784 close(s);
785 }
786
787 return 0;
788}
Andreas Gampe02d0de52015-11-11 20:43:16 -0800789
790} // namespace installd
791} // namespace android
792
793int main(const int argc, char *argv[]) {
794 return android::installd::installd_main(argc, argv);
795}