blob: 7cf45d9b97ef5f67c4964d5f23b368427b4739ab [file] [log] [blame]
Jeff Sharkey068c6be2017-09-06 13:47:40 -06001/*
2 * Copyright (C) 2017 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 "VoldNativeService.h"
18#include "VolumeManager.h"
Jeff Sharkey9462bdd2017-09-07 15:27:28 -060019#include "MoveTask.h"
Jeff Sharkey11c2d382017-09-11 10:32:01 -060020#include "TrimTask.h"
Jeff Sharkey068c6be2017-09-06 13:47:40 -060021
22#include <fstream>
23
24#include <android-base/logging.h>
25#include <android-base/stringprintf.h>
26#include <android-base/strings.h>
Jeff Sharkey11c2d382017-09-11 10:32:01 -060027#include <fs_mgr.h>
Jeff Sharkey068c6be2017-09-06 13:47:40 -060028#include <private/android_filesystem_config.h>
29
30#ifndef LOG_TAG
31#define LOG_TAG "vold"
32#endif
33
34using android::base::StringPrintf;
35using std::endl;
36
37namespace android {
38namespace vold {
39
40namespace {
41
42constexpr const char* kDump = "android.permission.DUMP";
43
44static binder::Status ok() {
45 return binder::Status::ok();
46}
47
48static binder::Status exception(uint32_t code, const std::string& msg) {
49 return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
50}
51
Jeff Sharkey9462bdd2017-09-07 15:27:28 -060052static binder::Status error(const std::string& msg) {
53 PLOG(ERROR) << msg;
54 return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
55}
56
57static binder::Status translate(uint32_t status) {
58 if (status == 0) {
59 return binder::Status::ok();
60 } else {
Jeff Sharkey11c2d382017-09-11 10:32:01 -060061 return binder::Status::fromServiceSpecificError(status);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -060062 }
63}
64
Jeff Sharkey068c6be2017-09-06 13:47:40 -060065binder::Status checkPermission(const char* permission) {
66 pid_t pid;
67 uid_t uid;
68
69 if (checkCallingPermission(String16(permission), reinterpret_cast<int32_t*>(&pid),
70 reinterpret_cast<int32_t*>(&uid))) {
71 return ok();
72 } else {
73 return exception(binder::Status::EX_SECURITY,
74 StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission));
75 }
76}
77
78binder::Status checkUid(uid_t expectedUid) {
79 uid_t uid = IPCThreadState::self()->getCallingUid();
80 if (uid == expectedUid || uid == AID_ROOT) {
81 return ok();
82 } else {
83 return exception(binder::Status::EX_SECURITY,
84 StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
85 }
86}
87
Jeff Sharkeyec4fda22017-09-12 13:19:24 -060088binder::Status checkArgumentId(const std::string& id) {
89 if (id.empty()) {
90 return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing ID");
91 }
92 for (const char& c : id) {
93 if (!std::isalnum(c) && c != ':' && c != ',') {
94 return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
95 StringPrintf("ID %s is malformed", id.c_str()));
96 }
97 }
98 return ok();
99}
100
101binder::Status checkArgumentPath(const std::string& path) {
102 if (path.empty()) {
103 return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Missing path");
104 }
105 if (path[0] != '/') {
106 return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
107 StringPrintf("Path %s is relative", path.c_str()));
108 }
109 for (const char& c : path) {
110 if (c == '\0' || c == '\n') {
111 return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
112 StringPrintf("Path %s is malformed", path.c_str()));
113 }
114 }
115 return ok();
116}
117
118binder::Status checkArgumentHex(const std::string& hex) {
119 // Empty hex strings are allowed
120 for (const char& c : hex) {
121 if (!std::isxdigit(c) && c != ':' && c != '-') {
122 return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
123 StringPrintf("Hex %s is malformed", hex.c_str()));
124 }
125 }
126 return ok();
127}
128
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600129#define ENFORCE_UID(uid) { \
130 binder::Status status = checkUid((uid)); \
131 if (!status.isOk()) { \
132 return status; \
133 } \
134}
135
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600136#define CHECK_ARGUMENT_ID(id) { \
137 binder::Status status = checkArgumentId((id)); \
138 if (!status.isOk()) { \
139 return status; \
140 } \
141}
142
143#define CHECK_ARGUMENT_PATH(path) { \
144 binder::Status status = checkArgumentPath((path)); \
145 if (!status.isOk()) { \
146 return status; \
147 } \
148}
149
150#define CHECK_ARGUMENT_HEX(hex) { \
151 binder::Status status = checkArgumentHex((hex)); \
152 if (!status.isOk()) { \
153 return status; \
154 } \
155}
156
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600157#define ACQUIRE_LOCK std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
158
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600159} // namespace
160
161status_t VoldNativeService::start() {
162 IPCThreadState::self()->disableBackgroundScheduling(true);
163 status_t ret = BinderService<VoldNativeService>::publish();
164 if (ret != android::OK) {
165 return ret;
166 }
167 sp<ProcessState> ps(ProcessState::self());
168 ps->startThreadPool();
169 ps->giveThreadPoolName();
170 return android::OK;
171}
172
173status_t VoldNativeService::dump(int fd, const Vector<String16> & /* args */) {
174 auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd));
175 const binder::Status dump_permission = checkPermission(kDump);
176 if (!dump_permission.isOk()) {
177 out << dump_permission.toString8() << endl;
178 return PERMISSION_DENIED;
179 }
180
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600181 ACQUIRE_LOCK;
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600182 out << "vold is happy!" << endl;
183 out.flush();
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600184 return NO_ERROR;
185}
186
187binder::Status VoldNativeService::reset() {
188 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600189 ACQUIRE_LOCK;
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600190
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600191 return translate(VolumeManager::Instance()->reset());
192}
193
194binder::Status VoldNativeService::shutdown() {
195 ENFORCE_UID(AID_SYSTEM);
196 ACQUIRE_LOCK;
197
198 return translate(VolumeManager::Instance()->shutdown());
199}
200
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600201binder::Status VoldNativeService::mountAll() {
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600202 ENFORCE_UID(AID_SYSTEM);
203 ACQUIRE_LOCK;
204
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600205 struct fstab* fstab = fs_mgr_read_fstab_default();
206 int res = fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT);
207 fs_mgr_free_fstab(fstab);
208 return translate(res);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600209}
210
211binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) {
212 ENFORCE_UID(AID_SYSTEM);
213 ACQUIRE_LOCK;
214
215 return translate(VolumeManager::Instance()->onUserAdded(userId, userSerial));
216}
217
218binder::Status VoldNativeService::onUserRemoved(int32_t userId) {
219 ENFORCE_UID(AID_SYSTEM);
220 ACQUIRE_LOCK;
221
222 return translate(VolumeManager::Instance()->onUserRemoved(userId));
223}
224
225binder::Status VoldNativeService::onUserStarted(int32_t userId) {
226 ENFORCE_UID(AID_SYSTEM);
227 ACQUIRE_LOCK;
228
229 return translate(VolumeManager::Instance()->onUserStarted(userId));
230}
231
232binder::Status VoldNativeService::onUserStopped(int32_t userId) {
233 ENFORCE_UID(AID_SYSTEM);
234 ACQUIRE_LOCK;
235
236 return translate(VolumeManager::Instance()->onUserStopped(userId));
237}
238
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600239binder::Status VoldNativeService::partition(const std::string& diskId, int32_t partitionType,
240 int32_t ratio) {
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600241 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600242 CHECK_ARGUMENT_ID(diskId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600243 ACQUIRE_LOCK;
244
245 auto disk = VolumeManager::Instance()->findDisk(diskId);
246 if (disk == nullptr) {
247 return error("Failed to find disk " + diskId);
248 }
249 switch (partitionType) {
250 case PARTITION_TYPE_PUBLIC: return translate(disk->partitionPublic());
251 case PARTITION_TYPE_PRIVATE: return translate(disk->partitionPrivate());
252 case PARTITION_TYPE_MIXED: return translate(disk->partitionMixed(ratio));
253 default: return error("Unknown type " + std::to_string(partitionType));
254 }
255}
256
257binder::Status VoldNativeService::forgetPartition(const std::string& partGuid) {
258 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600259 CHECK_ARGUMENT_HEX(partGuid);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600260 ACQUIRE_LOCK;
261
262 return translate(VolumeManager::Instance()->forgetPartition(partGuid));
263}
264
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600265binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
266 int32_t mountUserId) {
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600267 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600268 CHECK_ARGUMENT_ID(volId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600269 ACQUIRE_LOCK;
270
271 auto vol = VolumeManager::Instance()->findVolume(volId);
272 if (vol == nullptr) {
273 return error("Failed to find volume " + volId);
274 }
275
276 vol->setMountFlags(mountFlags);
277 vol->setMountUserId(mountUserId);
278
279 int res = vol->mount();
280 if (mountFlags & MOUNT_FLAG_PRIMARY) {
281 VolumeManager::Instance()->setPrimary(vol);
282 }
283 return translate(res);
284}
285
286binder::Status VoldNativeService::unmount(const std::string& volId) {
287 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600288 CHECK_ARGUMENT_ID(volId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600289 ACQUIRE_LOCK;
290
291 auto vol = VolumeManager::Instance()->findVolume(volId);
292 if (vol == nullptr) {
293 return error("Failed to find volume " + volId);
294 }
295 return translate(vol->unmount());
296}
297
298binder::Status VoldNativeService::format(const std::string& volId, const std::string& fsType) {
299 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600300 CHECK_ARGUMENT_ID(volId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600301 ACQUIRE_LOCK;
302
303 auto vol = VolumeManager::Instance()->findVolume(volId);
304 if (vol == nullptr) {
305 return error("Failed to find volume " + volId);
306 }
307 return translate(vol->format(fsType));
308}
309
310binder::Status VoldNativeService::benchmark(const std::string& volId, int64_t* _aidl_return) {
311 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600312 CHECK_ARGUMENT_ID(volId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600313 ACQUIRE_LOCK;
314
315 *_aidl_return = VolumeManager::Instance()->benchmarkPrivate(volId);
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600316 return ok();
317}
318
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600319binder::Status VoldNativeService::moveStorage(const std::string& fromVolId,
320 const std::string& toVolId) {
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600321 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600322 CHECK_ARGUMENT_ID(fromVolId);
323 CHECK_ARGUMENT_ID(toVolId);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600324 ACQUIRE_LOCK;
325
326 auto fromVol = VolumeManager::Instance()->findVolume(fromVolId);
327 auto toVol = VolumeManager::Instance()->findVolume(toVolId);
328 if (fromVol == nullptr) {
329 return error("Failed to find volume " + fromVolId);
330 } else if (toVol == nullptr) {
331 return error("Failed to find volume " + toVolId);
332 }
333 (new android::vold::MoveTask(fromVol, toVol))->start();
334 return ok();
335}
336
337binder::Status VoldNativeService::remountUid(int32_t uid, int32_t remountMode) {
338 ENFORCE_UID(AID_SYSTEM);
339 ACQUIRE_LOCK;
340
341 std::string tmp;
342 switch (remountMode) {
343 case REMOUNT_MODE_NONE: tmp = "none"; break;
344 case REMOUNT_MODE_DEFAULT: tmp = "default"; break;
345 case REMOUNT_MODE_READ: tmp = "read"; break;
346 case REMOUNT_MODE_WRITE: tmp = "write"; break;
347 default: return error("Unknown mode " + std::to_string(remountMode));
348 }
349 return translate(VolumeManager::Instance()->remountUid(uid, tmp));
350}
351
352binder::Status VoldNativeService::mkdirs(const std::string& path) {
353 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600354 CHECK_ARGUMENT_PATH(path);
Jeff Sharkey9462bdd2017-09-07 15:27:28 -0600355 ACQUIRE_LOCK;
356
357 return translate(VolumeManager::Instance()->mkdirs(path.c_str()));
358}
359
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600360binder::Status VoldNativeService::createObb(const std::string& sourcePath,
361 const std::string& sourceKey, int32_t ownerGid, std::string* _aidl_return) {
362 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600363 CHECK_ARGUMENT_PATH(sourcePath);
364 CHECK_ARGUMENT_HEX(sourceKey);
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600365 ACQUIRE_LOCK;
366
367 return translate(
368 VolumeManager::Instance()->createObb(sourcePath, sourceKey, ownerGid, _aidl_return));
369}
370
371binder::Status VoldNativeService::destroyObb(const std::string& volId) {
372 ENFORCE_UID(AID_SYSTEM);
Jeff Sharkeyec4fda22017-09-12 13:19:24 -0600373 CHECK_ARGUMENT_ID(volId);
Jeff Sharkey11c2d382017-09-11 10:32:01 -0600374 ACQUIRE_LOCK;
375
376 return translate(VolumeManager::Instance()->destroyObb(volId));
377}
378
379binder::Status VoldNativeService::fstrim(int32_t fstrimFlags) {
380 ENFORCE_UID(AID_SYSTEM);
381 ACQUIRE_LOCK;
382
383 (new android::vold::TrimTask(fstrimFlags))->start();
384 return ok();
385}
386
387binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t pid, int32_t mountId,
388 android::base::unique_fd* _aidl_return) {
389 ENFORCE_UID(AID_SYSTEM);
390 ACQUIRE_LOCK;
391
392 return translate(VolumeManager::Instance()->mountAppFuse(uid, pid, mountId, _aidl_return));
393}
394
395binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId) {
396 ENFORCE_UID(AID_SYSTEM);
397 ACQUIRE_LOCK;
398
399 return translate(VolumeManager::Instance()->unmountAppFuse(uid, pid, mountId));
400}
401
Jeff Sharkey068c6be2017-09-06 13:47:40 -0600402} // namespace vold
403} // namespace android