blob: 35936a23af6fbce7eca394f205651ccc00d4cfcb [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*/
Mark Salyzyna5e161b2016-09-29 08:08:05 -070016#define LOG_TAG "installd"
Mike Lockwood94afecf2012-10-24 10:45:23 -070017
Andreas Gampe02d0de52015-11-11 20:43:16 -080018#include <fcntl.h>
Stephen Smalleybd558d62013-04-16 12:16:50 -040019#include <selinux/android.h>
20#include <selinux/avc.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080021#include <sys/capability.h>
Jeff Sharkeyc7d1b222016-01-11 13:07:09 -070022#include <sys/fsuid.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080023#include <sys/prctl.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080024#include <sys/stat.h>
25
26#include <android-base/logging.h>
27#include <cutils/fs.h>
Andreas Gampe02d0de52015-11-11 20:43:16 -080028#include <cutils/properties.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070029#include <log/log.h> // TODO: Move everything to base::logging.
Andreas Gampe02d0de52015-11-11 20:43:16 -080030#include <private/android_filesystem_config.h>
31
Jeff Sharkeyf3e30b92016-12-09 17:06:57 -070032#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"
Andreas Gampe02d0de52015-11-11 20:43:16 -080037
Andreas Gampe02d0de52015-11-11 20:43:16 -080038namespace android {
39namespace installd {
40
41// Check that installd-deps sizes match cutils sizes.
42static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
43static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
44
45////////////////////////
46// Plug-in functions. //
47////////////////////////
48
49int 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
54bool calculate_oat_file_path(char path[PKG_PATH_MAX],
55 const char *oat_dir,
56 const char *apk_path,
57 const char *instruction_set) {
Dan Austin63235022016-03-28 15:09:02 -070058 const char *file_name_start;
59 const char *file_name_end;
Andreas Gampe02d0de52015-11-11 20:43:16 -080060
61 file_name_start = strrchr(apk_path, '/');
62 if (file_name_start == NULL) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -070063 SLOGE("apk_path '%s' has no '/'s in it\n", apk_path);
Andreas Gampe02d0de52015-11-11 20:43:16 -080064 return false;
65 }
66 file_name_end = strrchr(apk_path, '.');
67 if (file_name_end < file_name_start) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -070068 SLOGE("apk_path '%s' has no extension\n", apk_path);
Andreas Gampe02d0de52015-11-11 20:43:16 -080069 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 */
89bool 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) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -070094 SLOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
Andreas Gampe02d0de52015-11-11 20:43:16 -080095 return false;
96 }
97
98 strcpy(path, apk_path);
99 char *end = strrchr(path, '/');
100 if (end == NULL) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700101 SLOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800102 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) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700111 SLOGE("apk_path '%s' has no extension.\n", apk_path);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800112 return false;
113 }
114 strcpy(end + 1, "odex");
115 return true;
116}
117
118bool create_cache_path(char path[PKG_PATH_MAX],
119 const char *src,
120 const char *instruction_set) {
Greg Kaiser00087b72016-03-14 13:29:10 -0700121 /* demand that we are an absolute path */
122 if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
Andreas Gampe02d0de52015-11-11 20:43:16 -0800123 return false;
124 }
125
Greg Kaiser00087b72016-03-14 13:29:10 -0700126 size_t srclen = strlen(src);
127
Andreas Gampe02d0de52015-11-11 20:43:16 -0800128 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
David Brazdil249c1792016-09-06 15:35:28 +0100144 sprintf(path,"%s%s/%s/%s",
Andreas Gampe02d0de52015-11-11 20:43:16 -0800145 android_data_dir.path,
146 DALVIK_CACHE,
147 instruction_set,
David Brazdil249c1792016-09-06 15:35:28 +0100148 src + 1 /* skip the leading / */);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800149
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
David Brazdil249c1792016-09-06 15:35:28 +0100163 strcat(path, DALVIK_CACHE_POSTFIX);
Andreas Gampe02d0de52015-11-11 20:43:16 -0800164 return true;
165}
166
Andreas Gamped089ca12016-06-27 14:25:30 -0700167static bool initialize_globals() {
Andreas Gampe02d0de52015-11-11 20:43:16 -0800168 const char* data_path = getenv("ANDROID_DATA");
169 if (data_path == nullptr) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700170 SLOGE("Could not find ANDROID_DATA");
Andreas Gampe02d0de52015-11-11 20:43:16 -0800171 return false;
172 }
173 const char* root_path = getenv("ANDROID_ROOT");
174 if (root_path == nullptr) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700175 SLOGE("Could not find ANDROID_ROOT");
Andreas Gampe02d0de52015-11-11 20:43:16 -0800176 return false;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700177 }
178
Andreas Gampe02d0de52015-11-11 20:43:16 -0800179 return init_globals_from_data_and_root(data_path, root_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700180}
181
Andreas Gampe02d0de52015-11-11 20:43:16 -0800182static int initialize_directories() {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700183 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
Jeff Sharkeye02657d2016-01-13 09:37:46 -0700195 if (version < 2) {
196 SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
Mike Lockwood94afecf2012-10-24 10:45:23 -0700197 version = 2;
198 }
199
Robin Lee07053fc2014-04-29 19:42:01 +0100200 if (ensure_config_user_dirs(0) == -1) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700201 SLOGE("Failed to setup misc for user 0");
Robin Lee07053fc2014-04-29 19:42:01 +0100202 goto fail;
203 }
204
Robin Lee095c7632014-04-25 15:05:19 +0100205 if (version == 2) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700206 SLOGD("Upgrading to /data/misc/user directories");
Robin Lee095c7632014-04-25 15:05:19 +0100207
Robin Lee60fd3fe2014-10-07 16:55:02 +0100208 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
Robin Lee095c7632014-04-25 15:05:19 +0100217 DIR *dir;
218 struct dirent *dirent;
Jeff Sharkeye02657d2016-01-13 09:37:46 -0700219 dir = opendir("/data/user");
Robin Lee095c7632014-04-25 15:05:19 +0100220 if (dir != NULL) {
221 while ((dirent = readdir(dir))) {
Robin Lee60fd3fe2014-10-07 16:55:02 +0100222 const char *name = dirent->d_name;
Robin Lee095c7632014-04-25 15:05:19 +0100223
Robin Lee60fd3fe2014-10-07 16:55:02 +0100224 // 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) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700247 SLOGE("Some files failed to copy");
Robin Lee095c7632014-04-25 15:05:19 +0100248 }
Robin Lee60fd3fe2014-10-07 16:55:02 +0100249 }
250 if (access(keychain_removed_dir, F_OK) == 0) {
251 if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700252 SLOGE("Some files failed to copy");
Robin Lee095c7632014-04-25 15:05:19 +0100253 }
254 }
255 }
256 closedir(dir);
Robin Lee095c7632014-04-25 15:05:19 +0100257
Robin Lee60fd3fe2014-10-07 16:55:02 +0100258 if (access(keychain_added_dir, F_OK) == 0) {
259 delete_dir_contents(keychain_added_dir, 1, 0);
Robin Lee07053fc2014-04-29 19:42:01 +0100260 }
Robin Lee60fd3fe2014-10-07 16:55:02 +0100261 if (access(keychain_removed_dir, F_OK) == 0) {
262 delete_dir_contents(keychain_removed_dir, 1, 0);
Robin Lee07053fc2014-04-29 19:42:01 +0100263 }
264 }
265
266 version = 3;
Robin Lee095c7632014-04-25 15:05:19 +0100267 }
268
Mike Lockwood94afecf2012-10-24 10:45:23 -0700269 // Persist layout version if changed
270 if (version != oldVersion) {
271 if (fs_write_atomic_int(version_path, version) == -1) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700272 SLOGE("Failed to save version to %s: %s", version_path, strerror(errno));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700273 goto fail;
274 }
275 }
276
277 // Success!
278 res = 0;
279
280fail:
Mike Lockwood94afecf2012-10-24 10:45:23 -0700281 return res;
282}
283
Stephen Smalley7abb52b2014-03-26 09:30:37 -0400284static 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
Andreas Gampe02d0de52015-11-11 20:43:16 -0800305static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
Jeff Sharkey6c2c0562016-12-07 12:12:00 -0700306 int ret;
Stephen Smalleybd558d62013-04-16 12:16:50 -0400307 int selinux_enabled = (is_selinux_enabled() > 0);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700308
Jeff Sharkeye3637242015-04-08 20:56:42 -0700309 setenv("ANDROID_LOG_TAGS", "*:v", 1);
310 android::base::InitLogging(argv);
311
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700312 SLOGI("installd firing up");
Mike Lockwood94afecf2012-10-24 10:45:23 -0700313
Stephen Smalley7abb52b2014-03-26 09:30:37 -0400314 union selinux_callback cb;
315 cb.func_log = log_callback;
316 selinux_set_callback(SELINUX_CB_LOG, cb);
317
Andreas Gampe02d0de52015-11-11 20:43:16 -0800318 if (!initialize_globals()) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700319 SLOGE("Could not initialize globals; exiting.\n");
Mike Lockwood94afecf2012-10-24 10:45:23 -0700320 exit(1);
321 }
322
323 if (initialize_directories() < 0) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700324 SLOGE("Could not create directories; exiting.\n");
Mike Lockwood94afecf2012-10-24 10:45:23 -0700325 exit(1);
326 }
327
Stephen Smalleybd558d62013-04-16 12:16:50 -0400328 if (selinux_enabled && selinux_status_open(true) < 0) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700329 SLOGE("Could not open selinux status; exiting.\n");
Stephen Smalleybd558d62013-04-16 12:16:50 -0400330 exit(1);
331 }
332
Jeff Sharkey90874002016-12-05 11:18:55 -0700333 if ((ret = InstalldNativeService::start()) != android::OK) {
Mark Salyzyna5e161b2016-09-29 08:08:05 -0700334 SLOGE("Unable to start InstalldNativeService: %d", ret);
Jeff Sharkey90874002016-12-05 11:18:55 -0700335 exit(1);
336 }
337
Jeff Sharkey6c2c0562016-12-07 12:12:00 -0700338 IPCThreadState::self()->joinThreadPool();
Mike Lockwood94afecf2012-10-24 10:45:23 -0700339
Jeff Sharkey6c2c0562016-12-07 12:12:00 -0700340 LOG(INFO) << "installd shutting down";
Mike Lockwood94afecf2012-10-24 10:45:23 -0700341
342 return 0;
343}
Andreas Gampe02d0de52015-11-11 20:43:16 -0800344
345} // namespace installd
346} // namespace android
347
348int main(const int argc, char *argv[]) {
349 return android::installd::installd_main(argc, argv);
350}