1 /*
2 * Copyright (C) 2016 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 "fscrypt_init_extensions.h"
18
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fts.h>
22 #include <sys/mount.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25
26 #include <string>
27 #include <vector>
28
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/parseint.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34 #include <cutils/properties.h>
35 #include <cutils/sockets.h>
36 #include <fscrypt/fscrypt.h>
37 #include <keyutils.h>
38 #include <logwrap/logwrap.h>
39
40 #define TAG "fscrypt"
41
42 using namespace android::fscrypt;
43
FscryptInstallKeyring()44 bool FscryptInstallKeyring() {
45 if (keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0) != -1) {
46 LOG(INFO) << "Keyring is already created";
47 return true;
48 }
49 key_serial_t device_keyring = add_key("keyring", "fscrypt", 0, 0, KEY_SPEC_SESSION_KEYRING);
50
51 if (device_keyring == -1) {
52 PLOG(ERROR) << "Failed to create keyring";
53 return false;
54 }
55 LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid();
56 return true;
57 }
58
59 // TODO(b/139378601): use a single central implementation of this.
delete_dir_contents(const std::string & dir)60 static void delete_dir_contents(const std::string& dir) {
61 char* const paths[2] = {const_cast<char*>(dir.c_str()), nullptr};
62 FTS* fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr);
63 FTSENT* cur;
64 while ((cur = fts_read(fts)) != nullptr) {
65 if (cur->fts_info == FTS_ERR) {
66 PLOG(ERROR) << "fts_read";
67 break;
68 }
69 if (dir == cur->fts_path) {
70 continue;
71 }
72 switch (cur->fts_info) {
73 case FTS_D:
74 break; // Ignore these
75 case FTS_DP:
76 if (rmdir(cur->fts_path) == -1) {
77 PLOG(ERROR) << "rmdir " << cur->fts_path;
78 }
79 break;
80 default:
81 PLOG(ERROR) << "FTS unexpected type " << cur->fts_info << " at " << cur->fts_path;
82 if (rmdir(cur->fts_path) != -1) break;
83 // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
84 FALLTHROUGH_INTENDED;
85 case FTS_F:
86 case FTS_SL:
87 case FTS_SLNONE:
88 if (unlink(cur->fts_path) == -1) {
89 PLOG(ERROR) << "unlink " << cur->fts_path;
90 }
91 break;
92 }
93 }
94
95 if (fts_close(fts) != 0) {
96 PLOG(ERROR) << "fts_close";
97 }
98 }
99
100 // Look up an encryption policy The policy (key reference
101 // and encryption options) to use is read from files that were written by vold.
LookupPolicy(const std::string & ref_basename,EncryptionPolicy * policy)102 static bool LookupPolicy(const std::string& ref_basename, EncryptionPolicy* policy) {
103 std::string ref_filename = std::string("/data") + ref_basename;
104 if (!android::base::ReadFileToString(ref_filename, &policy->key_raw_ref)) {
105 LOG(ERROR) << "Unable to read system policy with name " << ref_filename;
106 return false;
107 }
108
109 auto options_filename = std::string("/data") + fscrypt_key_mode;
110 std::string options_string;
111 if (!android::base::ReadFileToString(options_filename, &options_string)) {
112 LOG(ERROR) << "Cannot read encryption options string";
113 return false;
114 }
115 if (!ParseOptions(options_string, &policy->options)) {
116 LOG(ERROR) << "Invalid encryption options string: " << options_string;
117 return false;
118 }
119 return true;
120 }
121
EnsurePolicyOrLog(const EncryptionPolicy & policy,const std::string & dir)122 static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
123 if (!EnsurePolicy(policy, dir)) {
124 std::string ref_hex;
125 BytesToHex(policy.key_raw_ref, &ref_hex);
126 LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
127 return false;
128 }
129 return true;
130 }
131
SetPolicyOn(const std::string & ref_basename,const std::string & dir)132 static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
133 EncryptionPolicy policy;
134 if (!LookupPolicy(ref_basename, &policy)) return false;
135 if (!EnsurePolicyOrLog(policy, dir)) return false;
136 return true;
137 }
138
FscryptSetDirectoryPolicy(const std::string & ref_basename,FscryptAction action,const std::string & dir)139 bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
140 const std::string& dir) {
141 if (action == FscryptAction::kNone) {
142 return true;
143 }
144 if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
145 return true;
146 }
147 if (action == FscryptAction::kDeleteIfNecessary) {
148 LOG(ERROR) << "Setting policy failed, deleting: " << dir;
149 delete_dir_contents(dir);
150 return SetPolicyOn(ref_basename, dir);
151 }
152 return false;
153 }
154