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