1 /* 2 * Copyright (C) 2019 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 "view_compiler.h" 18 19 #include <string> 20 21 #include <fcntl.h> 22 #include <sys/stat.h> 23 #include <sys/types.h> 24 #include <sys/wait.h> 25 #include <unistd.h> 26 27 #include "utils.h" 28 29 #include "android-base/logging.h" 30 #include "android-base/stringprintf.h" 31 #include "android-base/unique_fd.h" 32 33 namespace android { 34 namespace installd { 35 36 using base::unique_fd; 37 38 bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file, 39 int uid) { 40 CHECK(apk_path != nullptr); 41 CHECK(package_name != nullptr); 42 CHECK(out_dex_file != nullptr); 43 44 // viewcompiler won't have permission to open anything, so we have to open the files first 45 // and pass file descriptors. 46 47 // Open input file 48 unique_fd infd{open(apk_path, O_RDONLY)}; // NOLINT(android-cloexec-open) 49 if (infd.get() < 0) { 50 PLOG(ERROR) << "Could not open input file: " << apk_path; 51 return false; 52 } 53 54 // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so 55 // we close stdout and open it towards the right output. 56 unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644)}; 57 if (outfd.get() < 0) { 58 PLOG(ERROR) << "Could not open output file: " << out_dex_file; 59 return false; 60 } 61 if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) { 62 PLOG(ERROR) << "Could not change output file permissions"; 63 return false; 64 } 65 if (dup2(outfd, STDOUT_FILENO) < 0) { 66 PLOG(ERROR) << "Could not duplicate output file descriptor"; 67 return false; 68 } 69 70 // Prepare command line arguments for viewcompiler 71 std::string args[] = {"/system/bin/viewcompiler", 72 "--apk", 73 "--infd", 74 android::base::StringPrintf("%d", infd.get()), 75 "--dex", 76 "--package", 77 package_name}; 78 char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()), 79 const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()), 80 const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()), 81 const_cast<char*>(args[6].c_str()), nullptr}; 82 83 pid_t pid = fork(); 84 if (pid == 0) { 85 // Now that we've opened the files we need, drop privileges. 86 drop_capabilities(uid); 87 execv("/system/bin/viewcompiler", argv); 88 _exit(1); 89 } 90 91 return wait_child(pid) == 0; 92 } 93 94 } // namespace installd 95 } // namespace android 96