154 lines
5.1 KiB
C++
154 lines
5.1 KiB
C++
/*
|
|
* Copyright (C) 2016 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 "fscrypt_init_extensions.h"
|
|
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fts.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <android-base/file.h>
|
|
#include <android-base/logging.h>
|
|
#include <android-base/parseint.h>
|
|
#include <android-base/stringprintf.h>
|
|
#include <android-base/strings.h>
|
|
#include <cutils/properties.h>
|
|
#include <cutils/sockets.h>
|
|
#include <fscrypt/fscrypt.h>
|
|
#include <keyutils.h>
|
|
#include <logwrap/logwrap.h>
|
|
|
|
#define TAG "fscrypt"
|
|
|
|
using namespace android::fscrypt;
|
|
|
|
bool FscryptInstallKeyring() {
|
|
if (keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0) != -1) {
|
|
LOG(INFO) << "Keyring is already created";
|
|
return true;
|
|
}
|
|
key_serial_t device_keyring = add_key("keyring", "fscrypt", 0, 0, KEY_SPEC_SESSION_KEYRING);
|
|
|
|
if (device_keyring == -1) {
|
|
PLOG(ERROR) << "Failed to create keyring";
|
|
return false;
|
|
}
|
|
LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid();
|
|
return true;
|
|
}
|
|
|
|
// TODO(b/139378601): use a single central implementation of this.
|
|
static void delete_dir_contents(const std::string& dir) {
|
|
char* const paths[2] = {const_cast<char*>(dir.c_str()), nullptr};
|
|
FTS* fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr);
|
|
FTSENT* cur;
|
|
while ((cur = fts_read(fts)) != nullptr) {
|
|
if (cur->fts_info == FTS_ERR) {
|
|
PLOG(ERROR) << "fts_read";
|
|
break;
|
|
}
|
|
if (dir == cur->fts_path) {
|
|
continue;
|
|
}
|
|
switch (cur->fts_info) {
|
|
case FTS_D:
|
|
break; // Ignore these
|
|
case FTS_DP:
|
|
if (rmdir(cur->fts_path) == -1) {
|
|
PLOG(ERROR) << "rmdir " << cur->fts_path;
|
|
}
|
|
break;
|
|
default:
|
|
PLOG(ERROR) << "FTS unexpected type " << cur->fts_info << " at " << cur->fts_path;
|
|
if (rmdir(cur->fts_path) != -1) break;
|
|
// FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
|
|
FALLTHROUGH_INTENDED;
|
|
case FTS_F:
|
|
case FTS_SL:
|
|
case FTS_SLNONE:
|
|
if (unlink(cur->fts_path) == -1) {
|
|
PLOG(ERROR) << "unlink " << cur->fts_path;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fts_close(fts) != 0) {
|
|
PLOG(ERROR) << "fts_close";
|
|
}
|
|
}
|
|
|
|
// Look up an encryption policy The policy (key reference
|
|
// and encryption options) to use is read from files that were written by vold.
|
|
static bool LookupPolicy(const std::string& ref_basename, EncryptionPolicy* policy) {
|
|
std::string ref_filename = std::string("/data") + ref_basename;
|
|
if (!android::base::ReadFileToString(ref_filename, &policy->key_raw_ref)) {
|
|
LOG(ERROR) << "Unable to read system policy with name " << ref_filename;
|
|
return false;
|
|
}
|
|
|
|
auto options_filename = std::string("/data") + fscrypt_key_mode;
|
|
std::string options_string;
|
|
if (!android::base::ReadFileToString(options_filename, &options_string)) {
|
|
LOG(ERROR) << "Cannot read encryption options string";
|
|
return false;
|
|
}
|
|
if (!ParseOptions(options_string, &policy->options)) {
|
|
LOG(ERROR) << "Invalid encryption options string: " << options_string;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
|
|
if (!EnsurePolicy(policy, dir)) {
|
|
std::string ref_hex;
|
|
BytesToHex(policy.key_raw_ref, &ref_hex);
|
|
LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
|
|
EncryptionPolicy policy;
|
|
if (!LookupPolicy(ref_basename, &policy)) return false;
|
|
if (!EnsurePolicyOrLog(policy, dir)) return false;
|
|
return true;
|
|
}
|
|
|
|
bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
|
|
const std::string& dir) {
|
|
if (action == FscryptAction::kNone) {
|
|
return true;
|
|
}
|
|
if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
|
|
return true;
|
|
}
|
|
if (action == FscryptAction::kDeleteIfNecessary) {
|
|
LOG(ERROR) << "Setting policy failed, deleting: " << dir;
|
|
delete_dir_contents(dir);
|
|
return SetPolicyOn(ref_basename, dir);
|
|
}
|
|
return false;
|
|
}
|