1 /*
2 * Copyright (C) 2015 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 #pragma once
18
19 #include <stdbool.h>
20
21 #if BUILD_STORAGE_TEST
22 #define FULL_ASSERT 1
23 #else
24 #define FULL_ASSERT 0
25 #endif
26 #if FULL_ASSERT
27 #define full_assert assert
28 #else
29 #define full_assert(x) \
30 do { \
31 } while (0)
32 #endif
33
34 #include "block_mac.h"
35 #include "block_set.h"
36 #include "block_tree.h"
37
38 /**
39 * struct super_block_backup - Backup of root block for file system state
40 * @flags: Super-block flags for the backup, with the bits in
41 * SUPER_BLOCK_VERSION_MASK set to 0 (i.e. the backup does not
42 * contain a version).
43 * @free: Block and mac of backup free set root node.
44 * @files: Block and mac of backup files tree root node.
45 * @checkpoint: Block and mac of the backup checkpoint metadata block, if
46 * any.
47 *
48 * Block numbers and macs in @free and @files are packed as indicated by
49 * @block_num_size and @mac_size, but unlike other on-disk data, the size of the
50 * whole field is always the full 24 bytes needed for a 8 byte block number and
51 * 16 byte mac so this structure is always a fixed size.
52 */
53 struct super_block_backup {
54 uint32_t flags;
55 struct block_mac free;
56 struct block_mac files;
57 struct block_mac checkpoint;
58 };
59 STATIC_ASSERT(sizeof(struct super_block_backup) == 76);
60
61 /**
62 * struct fs - File system state
63 * @node: List node for fs_list.
64 * @dev: Main block device.
65 * @transactions: Transaction list.
66 * @allocated: List of block sets containing blocks
67 * allocated by active transactions.
68 * @free: Block set of free blocks.
69 * @files: B+ tree of all files.
70 * @checkpoint: Block and mac of the latest committed
71 * checkpoint metadata. Points to a block that
72 * holds the files root and free set at the
73 * time of the most recent checkpoint.
74 * @checkpoint_free: Block set of free blocks at the time of the
75 * last committed checkpoint. A block is only
76 * free if it is in both @free and
77 * @checkpoint_free.
78 * @super_dev: Block device used to store super blocks.
79 * @readable: %true if the file system is initialized and
80 * readable. If false, no reads are valid and
81 * @writable must be %false.
82 * @writable: %true if the file system may be modified. If
83 * %false, filesystem contents may be readable,
84 * but no superblock or block changes are
85 * permitted.
86 * @allow_tampering: %false if the filesystem must detect
87 * tampering of read and write operations.
88 * %true otherwise. If %false, when a write
89 * operation is reported as successfully
90 * completed it should not be possible for
91 * non-secure code to modify the stored data.
92 * @key: Key to use for encrypt, decrypt and mac.
93 * @super_block: Block numbers in @super_dev to store
94 * super-block in.
95 * @super_block_version: Last read or written super block version.
96 * @written_super_block_version: Last written super block version.
97 * @main_repaired: %true if main file system has been repaired
98 * since being wiped. In alternate state only
99 * used to persist this flag in the super
100 * block.
101 * @alternate_data: If true, the current superblock is for a
102 * filesystem with a backing store in an
103 * alternate data location and @backup contains
104 * the superblock of the normal filesystem. If
105 * false, @backup may contain a backup of the
106 * superblock for an alternate filesystem, but
107 * it may be outdated.
108 * @needs_full_scan: %true if an error was detected in this file
109 * system data and the file system should be
110 * scanned on the next mount. Persisted to the
111 * super block so that we can initiate a scan
112 * the next time we mount the file system.
113 * @checkpoint_required: %true if a checkpoint must be created before
114 * committing any changes to the file system.
115 * @backup: Backup superblock of other filesystem state
116 * (alternate if @alternate_data is false, main
117 * otherwise) Should be preserved across all
118 * filesystem operations after initialization.
119 * @min_block_num: First block number that can store non
120 * super blocks.
121 * @block_num_size: Number of bytes used to store block numbers.
122 * @mac_size: Number of bytes used to store mac values.
123 * Must be 16 if @dev is not tamper_detecting.
124 * @reserved_count: Number of free blocks reserved for active
125 * transactions.
126 * @initial_super_block_tr: Internal transaction containing initial
127 * super block that must be written before any
128 * other data. If %NULL superblock is already
129 * a safe state.
130 * @name: File system name, used to identify the file
131 * system in debugging and error reporting
132 * messages.
133 */
134
135 struct fs {
136 struct list_node node;
137 struct block_device* dev;
138 struct list_node transactions;
139 struct list_node allocated;
140 struct block_set free;
141 struct block_tree files;
142 struct block_mac checkpoint;
143 struct block_set checkpoint_free;
144 struct block_device* super_dev;
145 bool readable;
146 bool writable;
147 bool allow_tampering;
148 const struct key* key;
149 data_block_t super_block[2];
150 unsigned int super_block_version;
151 unsigned int written_super_block_version;
152 bool main_repaired;
153 bool alternate_data;
154 bool needs_full_scan;
155 bool checkpoint_required;
156 struct super_block_backup backup;
157 data_block_t min_block_num;
158 size_t block_num_size;
159 size_t mac_size;
160 data_block_t reserved_count;
161 struct transaction* initial_super_block_tr;
162 const char* name;
163 };
164
165 bool update_super_block(struct transaction* tr,
166 const struct block_mac* free,
167 const struct block_mac* files,
168 const struct block_mac* checkpoint);
169
170 void fs_mark_scan_required(struct fs* fs);
171
172 /**
173 * typedef fs_init_flags32_t - Flags that control filesystem clearing and
174 * backups. These flags may be ORed together.
175 *
176 * %FS_INIT_FLAGS_NONE
177 * No flags set
178 *
179 * %FS_INIT_FLAGS_DO_CLEAR
180 * Unconditionally clear the filesystem, regardless of corruption state.
181 * %FS_INIT_FLAGS_RECOVERY_* flags are ignored when combined with this flag.
182 *
183 * %FS_INIT_FLAGS_RECOVERY_CLEAR_ALLOWED
184 * Allows clearing of corrupt filesystem.
185 *
186 * %FS_INIT_FLAGS_ALTERNATE_DATA
187 * Indicates that the filesystem is temporarily running on top of an alternate
188 * location for the @dev block device and rollback should be enforced
189 * separately from the normal mode.
190 *
191 * %FS_INIT_FLAGS_ALLOW_TAMPERING
192 * Allow this filesystem to be initialized with the super block not stored on
193 * a tamper-detecting block device. This filesystem WILL NOT detect any
194 * tampering and a malicious actor may arbitrarily roll it back to any
195 * previous state.
196 *
197 * %FS_INIT_FLAGS_RESTORE_CHECKPOINT
198 * Restore this filesystem to the current checkpointed state, discarding any
199 * changes since that checkpoint was made.
200 *
201 * %FS_INIT_FLAGS_AUTO_CHECKPOINT
202 * Automatically create a checkpoint of the filesystem state on mount.
203 */
204 typedef uint32_t fs_init_flags32_t;
205 #define FS_INIT_FLAGS_NONE 0U
206 #define FS_INIT_FLAGS_DO_CLEAR (1U << 0)
207 #define FS_INIT_FLAGS_RECOVERY_CLEAR_ALLOWED (1U << 1)
208 #define FS_INIT_FLAGS_ALTERNATE_DATA (1U << 2)
209 #define FS_INIT_FLAGS_ALLOW_TAMPERING (1U << 3)
210 #define FS_INIT_FLAGS_RESTORE_CHECKPOINT (1U << 4)
211 #define FS_INIT_FLAGS_AUTO_CHECKPOINT (1U << 5)
212 #define FS_INIT_FLAGS_MASK \
213 (FS_INIT_FLAGS_DO_CLEAR | FS_INIT_FLAGS_RECOVERY_CLEAR_ALLOWED | \
214 FS_INIT_FLAGS_ALTERNATE_DATA | FS_INIT_FLAGS_ALLOW_TAMPERING | \
215 FS_INIT_FLAGS_RESTORE_CHECKPOINT | FS_INIT_FLAGS_AUTO_CHECKPOINT)
216
217 int fs_init(struct fs* fs,
218 const char* name,
219 const struct key* key,
220 struct block_device* dev,
221 struct block_device* super_dev,
222 fs_init_flags32_t flags);
223
fs_is_repaired(struct fs * fs)224 static inline bool fs_is_repaired(struct fs* fs) {
225 return fs->main_repaired && !fs->alternate_data;
226 }
227
fs_is_readable(struct fs * fs)228 static inline bool fs_is_readable(struct fs* fs) {
229 return fs->readable;
230 }
231
fs_is_writable(struct fs * fs)232 static inline bool fs_is_writable(struct fs* fs) {
233 return fs->writable;
234 }
235
236 /**
237 * enum fs_check_result - Result of a filesystem check
238 * @FS_CHECK_NO_ERROR: No error was enountered in the checked blocks.
239 * @FS_CHECK_INVALID_BLOCK: A MAC mismatch error or invalid block was
240 * encountered while trying to load a block in the
241 * file-system. This type of error may indicate that
242 * the non-secure data is out of sync with the RPMB
243 * superblock. The file-system is likely corrupt.
244 * @FS_CHECK_INVALID_FREE_SET: The free set was not internally valid or invalid
245 * blocks were encountered in the free set tree.
246 * @FS_CHECK_INVALID_FILE_TREE: The file tree was not internally valid but no
247 * invalid blocks were encountered.
248 * @FS_CHECK_UNKNOWN: An unknown error was encountered while checking the
249 * file-system. The file-system may not be entirely
250 * readable or valid.
251 */
252 enum fs_check_result {
253 FS_CHECK_NO_ERROR = 0,
254 FS_CHECK_INVALID_BLOCK,
255 FS_CHECK_INVALID_FREE_SET,
256 FS_CHECK_INVALID_FILE_TREE,
257 FS_CHECK_UNKNOWN,
258 };
259
260 /**
261 * fs_check_full - Check the file system tree
262 * @fs: File system state object.
263 *
264 * Walk the filesystem tree and visit each file, checking the file tree and each
265 * file block map for consistency.
266 *
267 * Returns @fs_check_result.FS_CHECK_NO_ERROR if no corruption was encountered
268 * or any encountered corruption was repaired. Returns another @fs_check_result
269 * variant describing the error if the filesystem remains corrupted after this
270 * operation. Errors are prioritized in the following order (highest to lowest):
271 * %FS_CHECK_INVALID_BLOCK (except in the free set, which is reported
272 * separately), %FS_CHECK_INVALID_FILE_TREE, %FS_CHECK_INVALID_FREE_SET,
273 * %FS_CHECK_UNKNOWN. This ordering is intended to allow callers to
274 * differentiate between invalid blocks that indicate corruption and possibly
275 * transient communication errors with the storage proxy.
276 */
277 enum fs_check_result fs_check_full(struct fs* fs);
278
279 /**
280 * fs_check_quick - Quickly check the file-system tree
281 * @fs: File system state object.
282 *
283 * Perform a basic check that the file-system roots are valid. Suitable for use
284 * while mounting file-systems where we don't want to pay the cost to walk the
285 * entire file-system tree.
286 *
287 * Returns @fs_check_result.FS_CHECK_NO_ERROR if no corruption was encountered,
288 * or another @fs_check_result variant describing the error.
289 */
290 enum fs_check_result fs_check_quick(struct fs* fs);
291
292 /**
293 * fs_check - Check the file system tree
294 * @fs: File system state object.
295 *
296 * If the filesystem was not previously marked as requiring a full scan, perform
297 * a quick check (i.e. behave the same as fs_check_quick()). If the file system
298 * has been marked as potentially having an error, do a full scan using
299 * fs_check_full().
300 *
301 * Returns an @fs_check_result variant, see fs_check_quick() and fs_check_full()
302 * for details.
303 */
304 enum fs_check_result fs_check(struct fs* fs);
305
306 void fs_file_tree_init(const struct fs* fs, struct block_tree* tree);
307
308 void fs_unknown_super_block_state_all(void);
309 void write_current_super_block(struct fs* fs, bool reinitialize);
310
311 void fs_destroy(struct fs* fs);
312
313 /**
314 * fs_fail_all_transactions - Fail all pending transactions in all filesystems
315 *
316 * This functions fails any pending transactions that have not already failed.
317 */
318 void fs_fail_all_transactions(void);
319