blob: 2b02f91e06fa774ade8b5d75eca5a44ffa29dc62 [file] [log] [blame]
Jeff Sharkeydeb24052015-03-02 21:01:40 -08001/*
2 * Copyright (C) 2015 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
Jeff Sharkeydeb24052015-03-02 21:01:40 -080017#include "sehandle.h"
18#include "Utils.h"
19#include "Process.h"
20
Jeff Sharkey36801cc2015-03-13 16:09:20 -070021#include <base/logging.h>
Jeff Sharkey9c484982015-03-31 10:35:33 -070022#include <base/stringprintf.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080023#include <cutils/fs.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080024#include <private/android_filesystem_config.h>
Jeff Sharkey9c484982015-03-31 10:35:33 -070025#include <logwrap/logwrap.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080026
27#include <fcntl.h>
28#include <linux/fs.h>
29#include <stdlib.h>
30#include <sys/mount.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <sys/wait.h>
34
35#ifndef UMOUNT_NOFOLLOW
36#define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
37#endif
38
Jeff Sharkey9c484982015-03-31 10:35:33 -070039using android::base::StringPrintf;
40
Jeff Sharkeydeb24052015-03-02 21:01:40 -080041namespace android {
42namespace vold {
43
Jeff Sharkey95c87cc2015-04-01 11:54:32 -070044security_context_t sBlkidContext = nullptr;
45security_context_t sBlkidUntrustedContext = nullptr;
46security_context_t sFsckContext = nullptr;
47security_context_t sFsckUntrustedContext = nullptr;
48
Jeff Sharkey9c484982015-03-31 10:35:33 -070049static const char* kBlkidPath = "/system/bin/blkid";
50
Jeff Sharkeydeb24052015-03-02 21:01:40 -080051status_t CreateDeviceNode(const std::string& path, dev_t dev) {
52 const char* cpath = path.c_str();
53 status_t res = 0;
54
55 char* secontext = nullptr;
56 if (sehandle) {
57 if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) {
58 setfscreatecon(secontext);
59 }
60 }
61
62 mode_t mode = 0660 | S_IFBLK;
63 if (mknod(cpath, mode, dev) < 0) {
64 if (errno != EEXIST) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070065 PLOG(ERROR) << "Failed to create device node for " << major(dev)
66 << ":" << minor(dev) << " at " << path;
Jeff Sharkeydeb24052015-03-02 21:01:40 -080067 res = -errno;
68 }
69 }
70
71 if (secontext) {
72 setfscreatecon(nullptr);
73 freecon(secontext);
74 }
75
76 return res;
77}
78
79status_t DestroyDeviceNode(const std::string& path) {
80 const char* cpath = path.c_str();
81 if (TEMP_FAILURE_RETRY(unlink(cpath))) {
82 return -errno;
83 } else {
84 return OK;
85 }
86}
87
88status_t ForceUnmount(const std::string& path) {
89 const char* cpath = path.c_str();
90 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
91 return OK;
92 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -070093 PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGTERM";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080094 Process::killProcessesWithOpenFiles(cpath, SIGTERM);
Jeff Sharkey9c484982015-03-31 10:35:33 -070095 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080096
97 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
98 return OK;
99 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700100 PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGKILL";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800101 Process::killProcessesWithOpenFiles(cpath, SIGKILL);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700102 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800103
104 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
105 return OK;
106 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700107 PLOG(ERROR) << "Failed to unmount " << path << "; giving up";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800108 return -errno;
109}
110
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700111status_t BindMount(const std::string& source, const std::string& target) {
112 if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
113 PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
114 return -errno;
115 }
116 return OK;
117}
118
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700119static status_t readMetadata(const std::string& path, std::string& fsType,
120 std::string& fsUuid, std::string& fsLabel, bool untrusted) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700121 fsType.clear();
122 fsUuid.clear();
123 fsLabel.clear();
124
125 std::string cmd(StringPrintf("%s -c /dev/null %s", kBlkidPath, path.c_str()));
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700126 if (setexeccon(untrusted ? sBlkidUntrustedContext : sBlkidContext)) {
127 LOG(ERROR) << "Failed to setexeccon()";
128 return -EPERM;
129 }
Jeff Sharkey9c484982015-03-31 10:35:33 -0700130 FILE* fp = popen(cmd.c_str(), "r");
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700131 if (setexeccon(NULL)) {
132 abort();
133 }
Jeff Sharkey9c484982015-03-31 10:35:33 -0700134 if (!fp) {
135 PLOG(ERROR) << "Failed to run " << cmd;
136 return -errno;
137 }
138
139 status_t res = OK;
140 char line[1024];
141 char value[128];
142 if (fgets(line, sizeof(line), fp) != nullptr) {
143 LOG(DEBUG) << "blkid identified " << path << " as " << line;
144
145 // Extract values from blkid output, if defined
146 char* start = strstr(line, "TYPE=");
147 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
148 fsType = value;
149 }
150
151 start = strstr(line, "UUID=");
152 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
153 fsUuid = value;
154 }
155
156 start = strstr(line, "LABEL=");
157 if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
158 fsLabel = value;
159 }
160 } else {
161 LOG(WARNING) << "blkid failed to identify " << path;
162 res = -ENODATA;
163 }
164
165 pclose(fp);
166 return res;
167}
168
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700169status_t ReadMetadata(const std::string& path, std::string& fsType,
170 std::string& fsUuid, std::string& fsLabel) {
171 return readMetadata(path, fsType, fsUuid, fsLabel, false);
172}
173
174status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
175 std::string& fsUuid, std::string& fsLabel) {
176 return readMetadata(path, fsType, fsUuid, fsLabel, true);
177}
178
Jeff Sharkey9c484982015-03-31 10:35:33 -0700179status_t ForkExecvp(const std::vector<std::string>& args, int* status,
180 bool ignore_int_quit, bool logwrap) {
181 int argc = args.size();
182 char** argv = (char**) calloc(argc, sizeof(char*));
183 for (int i = 0; i < argc; i++) {
184 argv[i] = (char*) args[i].c_str();
185 if (i == 0) {
186 LOG(VERBOSE) << args[i];
187 } else {
188 LOG(VERBOSE) << " " << args[i];
189 }
190 }
191 int res = android_fork_execvp(argc, argv, status, ignore_int_quit, logwrap);
192 free(argv);
193 return res;
194}
195
196status_t ReadRandomBytes(size_t bytes, std::string& out) {
197 out.clear();
198
199 int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
200 if (fd == -1) {
201 return -errno;
202 }
203
204 char buf[BUFSIZ];
205 size_t n;
206 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], std::min(sizeof(buf), bytes)))) > 0) {
207 out.append(buf, n);
208 bytes -= n;
209 }
210 TEMP_FAILURE_RETRY(close(fd));
211
212 if (bytes == 0) {
213 return OK;
214 } else {
215 return -EIO;
216 }
217}
218
219status_t HexToStr(const std::string& hex, std::string& str) {
220 str.clear();
221 bool even = true;
222 char cur = 0;
223 for (size_t i = 0; i < hex.size(); i++) {
224 int val = 0;
225 switch (hex[i]) {
226 case ' ': case '-': case ':': continue;
227 case 'f': case 'F': val = 15; break;
228 case 'e': case 'E': val = 14; break;
229 case 'd': case 'D': val = 13; break;
230 case 'c': case 'C': val = 12; break;
231 case 'b': case 'B': val = 11; break;
232 case 'a': case 'A': val = 10; break;
233 case '9': val = 9; break;
234 case '8': val = 8; break;
235 case '7': val = 7; break;
236 case '6': val = 6; break;
237 case '5': val = 5; break;
238 case '4': val = 4; break;
239 case '3': val = 3; break;
240 case '2': val = 2; break;
241 case '1': val = 1; break;
242 case '0': val = 0; break;
243 default: return -EINVAL;
244 }
245
246 if (even) {
247 cur = val << 4;
248 } else {
249 cur += val;
250 str.push_back(cur);
251 cur = 0;
252 }
253 even = !even;
254 }
255 return even ? OK : -EINVAL;
256}
257
258static const char* kLookup = "0123456789abcdef";
259
260status_t StrToHex(const std::string& str, std::string& hex) {
261 hex.clear();
262 for (size_t i = 0; i < str.size(); i++) {
263 hex.push_back(kLookup[str[i] >> 4]);
264 hex.push_back(kLookup[str[i] & 0x0F]);
265 }
266 return OK;
267}
268
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800269} // namespace vold
270} // namespace android