blob: 1937c2817e65e1e2afc4670f489525286aac1803 [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
Jeff Sharkeyf0121c52015-04-06 14:08:45 -070088status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
89 const char* cpath = path.c_str();
90
91 char* secontext = nullptr;
92 if (sehandle) {
93 if (!selabel_lookup(sehandle, &secontext, cpath, S_IFDIR)) {
94 setfscreatecon(secontext);
95 }
96 }
97
98 int res = fs_prepare_dir(cpath, mode, uid, gid);
99
100 if (secontext) {
101 setfscreatecon(nullptr);
102 freecon(secontext);
103 }
104
105 if (res == 0) {
106 return OK;
107 } else {
108 return -errno;
109 }
110}
111
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800112status_t ForceUnmount(const std::string& path) {
113 const char* cpath = path.c_str();
114 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
115 return OK;
116 }
Jeff Sharkeyf0121c52015-04-06 14:08:45 -0700117 PLOG(WARNING) << "Failed to unmount " << path;
118
119 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800120 Process::killProcessesWithOpenFiles(cpath, SIGTERM);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800121
122 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
123 return OK;
124 }
Jeff Sharkeyf0121c52015-04-06 14:08:45 -0700125 PLOG(WARNING) << "Failed to unmount " << path;
126
127 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800128 Process::killProcessesWithOpenFiles(cpath, SIGKILL);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800129
130 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
131 return OK;
132 }
Jeff Sharkeyf0121c52015-04-06 14:08:45 -0700133 PLOG(ERROR) << "Failed to unmount " << path;
134
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800135 return -errno;
136}
137
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700138status_t BindMount(const std::string& source, const std::string& target) {
139 if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
140 PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
141 return -errno;
142 }
143 return OK;
144}
145
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700146static status_t readMetadata(const std::string& path, std::string& fsType,
147 std::string& fsUuid, std::string& fsLabel, bool untrusted) {
Jeff Sharkey9c484982015-03-31 10:35:33 -0700148 fsType.clear();
149 fsUuid.clear();
150 fsLabel.clear();
151
152 std::string cmd(StringPrintf("%s -c /dev/null %s", kBlkidPath, path.c_str()));
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700153 if (setexeccon(untrusted ? sBlkidUntrustedContext : sBlkidContext)) {
154 LOG(ERROR) << "Failed to setexeccon()";
155 return -EPERM;
156 }
Jeff Sharkey9c484982015-03-31 10:35:33 -0700157 FILE* fp = popen(cmd.c_str(), "r");
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700158 if (setexeccon(NULL)) {
159 abort();
160 }
Jeff Sharkey9c484982015-03-31 10:35:33 -0700161 if (!fp) {
162 PLOG(ERROR) << "Failed to run " << cmd;
163 return -errno;
164 }
165
166 status_t res = OK;
167 char line[1024];
168 char value[128];
169 if (fgets(line, sizeof(line), fp) != nullptr) {
170 LOG(DEBUG) << "blkid identified " << path << " as " << line;
171
172 // Extract values from blkid output, if defined
173 char* start = strstr(line, "TYPE=");
174 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
175 fsType = value;
176 }
177
178 start = strstr(line, "UUID=");
179 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
180 fsUuid = value;
181 }
182
183 start = strstr(line, "LABEL=");
184 if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
185 fsLabel = value;
186 }
187 } else {
188 LOG(WARNING) << "blkid failed to identify " << path;
189 res = -ENODATA;
190 }
191
192 pclose(fp);
193 return res;
194}
195
Jeff Sharkey95c87cc2015-04-01 11:54:32 -0700196status_t ReadMetadata(const std::string& path, std::string& fsType,
197 std::string& fsUuid, std::string& fsLabel) {
198 return readMetadata(path, fsType, fsUuid, fsLabel, false);
199}
200
201status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
202 std::string& fsUuid, std::string& fsLabel) {
203 return readMetadata(path, fsType, fsUuid, fsLabel, true);
204}
205
Jeff Sharkey9c484982015-03-31 10:35:33 -0700206status_t ForkExecvp(const std::vector<std::string>& args, int* status,
207 bool ignore_int_quit, bool logwrap) {
208 int argc = args.size();
209 char** argv = (char**) calloc(argc, sizeof(char*));
210 for (int i = 0; i < argc; i++) {
211 argv[i] = (char*) args[i].c_str();
212 if (i == 0) {
213 LOG(VERBOSE) << args[i];
214 } else {
215 LOG(VERBOSE) << " " << args[i];
216 }
217 }
218 int res = android_fork_execvp(argc, argv, status, ignore_int_quit, logwrap);
219 free(argv);
220 return res;
221}
222
223status_t ReadRandomBytes(size_t bytes, std::string& out) {
224 out.clear();
225
226 int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
227 if (fd == -1) {
228 return -errno;
229 }
230
231 char buf[BUFSIZ];
232 size_t n;
233 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], std::min(sizeof(buf), bytes)))) > 0) {
234 out.append(buf, n);
235 bytes -= n;
236 }
237 TEMP_FAILURE_RETRY(close(fd));
238
239 if (bytes == 0) {
240 return OK;
241 } else {
242 return -EIO;
243 }
244}
245
246status_t HexToStr(const std::string& hex, std::string& str) {
247 str.clear();
248 bool even = true;
249 char cur = 0;
250 for (size_t i = 0; i < hex.size(); i++) {
251 int val = 0;
252 switch (hex[i]) {
253 case ' ': case '-': case ':': continue;
254 case 'f': case 'F': val = 15; break;
255 case 'e': case 'E': val = 14; break;
256 case 'd': case 'D': val = 13; break;
257 case 'c': case 'C': val = 12; break;
258 case 'b': case 'B': val = 11; break;
259 case 'a': case 'A': val = 10; break;
260 case '9': val = 9; break;
261 case '8': val = 8; break;
262 case '7': val = 7; break;
263 case '6': val = 6; break;
264 case '5': val = 5; break;
265 case '4': val = 4; break;
266 case '3': val = 3; break;
267 case '2': val = 2; break;
268 case '1': val = 1; break;
269 case '0': val = 0; break;
270 default: return -EINVAL;
271 }
272
273 if (even) {
274 cur = val << 4;
275 } else {
276 cur += val;
277 str.push_back(cur);
278 cur = 0;
279 }
280 even = !even;
281 }
282 return even ? OK : -EINVAL;
283}
284
285static const char* kLookup = "0123456789abcdef";
286
287status_t StrToHex(const std::string& str, std::string& hex) {
288 hex.clear();
289 for (size_t i = 0; i < str.size(); i++) {
290 hex.push_back(kLookup[str[i] >> 4]);
291 hex.push_back(kLookup[str[i] & 0x0F]);
292 }
293 return OK;
294}
295
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800296} // namespace vold
297} // namespace android