/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VoldNativeService.h" #include "VolumeManager.h" #include #include #include #include #include #ifndef LOG_TAG #define LOG_TAG "vold" #endif using android::base::StringPrintf; using std::endl; namespace android { namespace vold { namespace { constexpr const char* kDump = "android.permission.DUMP"; static binder::Status ok() { return binder::Status::ok(); } static binder::Status exception(uint32_t code, const std::string& msg) { return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } binder::Status checkPermission(const char* permission) { pid_t pid; uid_t uid; if (checkCallingPermission(String16(permission), reinterpret_cast(&pid), reinterpret_cast(&uid))) { return ok(); } else { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, permission)); } } binder::Status checkUid(uid_t expectedUid) { uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid == expectedUid || uid == AID_ROOT) { return ok(); } else { return exception(binder::Status::EX_SECURITY, StringPrintf("UID %d is not expected UID %d", uid, expectedUid)); } } #define ENFORCE_UID(uid) { \ binder::Status status = checkUid((uid)); \ if (!status.isOk()) { \ return status; \ } \ } } // namespace status_t VoldNativeService::start() { IPCThreadState::self()->disableBackgroundScheduling(true); status_t ret = BinderService::publish(); if (ret != android::OK) { return ret; } sp ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); return android::OK; } status_t VoldNativeService::dump(int fd, const Vector & /* args */) { auto out = std::fstream(StringPrintf("/proc/self/fd/%d", fd)); const binder::Status dump_permission = checkPermission(kDump); if (!dump_permission.isOk()) { out << dump_permission.toString8() << endl; return PERMISSION_DENIED; } out << "vold is happy!" << endl; out.flush(); return NO_ERROR; } binder::Status VoldNativeService::reset() { ENFORCE_UID(AID_SYSTEM); LOG(INFO) << "reset() via Binder!"; VolumeManager::Instance()->reset(); return ok(); } } // namespace vold } // namespace android