xref: /aosp_15_r20/system/core/init/fscrypt_init_extensions.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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 <logwrap/logwrap.h>
38 
39 #define TAG "fscrypt"
40 
41 using namespace android::fscrypt;
42 
43 // TODO(b/139378601): use a single central implementation of this.
delete_dir_contents(const std::string & dir)44 static void delete_dir_contents(const std::string& dir) {
45     char* const paths[2] = {const_cast<char*>(dir.c_str()), nullptr};
46     FTS* fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr);
47     FTSENT* cur;
48     while ((cur = fts_read(fts)) != nullptr) {
49         if (cur->fts_info == FTS_ERR) {
50             PLOG(ERROR) << "fts_read";
51             break;
52         }
53         if (dir == cur->fts_path) {
54             continue;
55         }
56         switch (cur->fts_info) {
57             case FTS_D:
58                 break;  // Ignore these
59             case FTS_DP:
60                 if (rmdir(cur->fts_path) == -1) {
61                     PLOG(ERROR) << "rmdir " << cur->fts_path;
62                 }
63                 break;
64             default:
65                 PLOG(ERROR) << "FTS unexpected type " << cur->fts_info << " at " << cur->fts_path;
66                 if (rmdir(cur->fts_path) != -1) break;
67                 // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
68                 FALLTHROUGH_INTENDED;
69             case FTS_F:
70             case FTS_SL:
71             case FTS_SLNONE:
72                 if (unlink(cur->fts_path) == -1) {
73                     PLOG(ERROR) << "unlink " << cur->fts_path;
74                 }
75                 break;
76         }
77     }
78 
79     if (fts_close(fts) != 0) {
80         PLOG(ERROR) << "fts_close";
81     }
82 }
83 
84 // Look up an encryption policy  The policy (key reference
85 // and encryption options) to use is read from files that were written by vold.
LookupPolicy(const std::string & ref_basename,EncryptionPolicy * policy)86 static bool LookupPolicy(const std::string& ref_basename, EncryptionPolicy* policy) {
87     std::string ref_filename = std::string("/data") + ref_basename;
88     if (!android::base::ReadFileToString(ref_filename, &policy->key_raw_ref)) {
89         LOG(ERROR) << "Unable to read system policy with name " << ref_filename;
90         return false;
91     }
92 
93     auto options_filename = std::string("/data") + fscrypt_key_mode;
94     std::string options_string;
95     if (!android::base::ReadFileToString(options_filename, &options_string)) {
96         LOG(ERROR) << "Cannot read encryption options string";
97         return false;
98     }
99     if (!ParseOptions(options_string, &policy->options)) {
100         LOG(ERROR) << "Invalid encryption options string: " << options_string;
101         return false;
102     }
103     return true;
104 }
105 
EnsurePolicyOrLog(const EncryptionPolicy & policy,const std::string & dir)106 static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
107     if (!EnsurePolicy(policy, dir)) {
108         std::string ref_hex;
109         BytesToHex(policy.key_raw_ref, &ref_hex);
110         LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
111         return false;
112     }
113     return true;
114 }
115 
SetPolicyOn(const std::string & ref_basename,const std::string & dir)116 static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
117     EncryptionPolicy policy;
118     if (!LookupPolicy(ref_basename, &policy)) return false;
119     if (!EnsurePolicyOrLog(policy, dir)) return false;
120     return true;
121 }
122 
FscryptSetDirectoryPolicy(const std::string & ref_basename,FscryptAction action,const std::string & dir)123 bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
124                                const std::string& dir) {
125     if (action == FscryptAction::kNone) {
126         return true;
127     }
128     if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
129         return true;
130     }
131     if (action == FscryptAction::kDeleteIfNecessary) {
132         LOG(ERROR) << "Setting policy failed, deleting: " << dir;
133         delete_dir_contents(dir);
134         return SetPolicyOn(ref_basename, dir);
135     }
136     return false;
137 }
138