-
Notifications
You must be signed in to change notification settings - Fork 1.2k
core: tee_ree_fs: conditionally remove corrupt dirf.db file #7645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
5143759 to
2e528c6
Compare
|
What if the power outage happens in the middle of writing data to |
|
Yes, a power outage during the writing process can result in a corrupted dirf.db file, making secure storage unusable. Currently, the creation of dirf.db involves the following RPC steps: Although commit 5a9d570a attempts to handle power outages between steps 2 and 4 by checking ht_head_is_partially_done, it does not cover the case where a power outage occurs immediately after step 1. Adding temporary copy in ree-fs_new_write() in tee-supplicant is a possible solution, but we still need to distinguish between corruption caused by power outages and potential REE-side attacks in TEE side. If the target device supports CFG_REE_FS_INTEGRITY_RPMB, maybe we shall directly refer to the status of dirfile.db.hash in RPMB for checking. For this case, we use file size:0 and no hash setting as the pattern from power outage. |
|
@jforissier |
|
I'll take another look at this. |
core/tee/tee_ree_fs.c
Outdated
| if (fdp->fd != -1) | ||
| tee_fs_rpc_close(OPTEE_RPC_CMD_FS, fdp->fd); | ||
| if (create) | ||
| if (create || !hash) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can hash be used to determine whether the file should be removed?
Wouldn't it make more sense to check if the file is too small (size 0?) and return TEE_ERROR_ITEM_NOT_FOUND?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Jenswi,
If an empty dirf.db file is present and no hash exists (possibly in RPMB), this situation typically results from an unexpected power outage during the initialization flow.
When the system attempts to read the dirf.db file, it calls init_head_from_data to reconstruct the hash tree. However, the RPC read command fails to retrieve the expected hash tree header—the returned buffer is zero and does not match the expected size of the hash tree header. As a result, the object is interpreted as corrupted, and the current implementation returns TEE_ERROR_CORRUPT_OBJECT.
Relevant code flow:
init_head_from_data
No hash case
rpc_read_head
rpc_read
Since rpc_read is a fundamental function and operates correctly, it is preferable to handle this error case in the control flow. Therefore, we recommend addressing this scenario in the ree_fs_open_primitive function, utilizing hash information to support proper error handling.
On the other hand, if there is an empty dirf.db file but a valid hash exists, it is more likely that the dirf.db file was modified on the REE side. In this case, we can still apply the same error handling flow to maintain consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an empty dirf.db file is present and no hash exists (possibly in RPMB), this situation typically results from an unexpected power outage during the initialization flow.
What do you mean by "possibly in RPMB"? That it might be supplied with RPMB or not? Without RPMB, will it always be NULL or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my local environment, flag CFG_REE_FS_INTEGRITY_RPMB is enabled. However, without RPMB, it seems that no hash records are generated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So without CFG_REE_FS_INTEGRITY_RPMB enabled, you recommend to always remove "dirf.db" if it doesn't open correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not mentioning this earlier—this change is based on the scenario where CFG_REE_FS_INTEGRITY_RPMB is enabled. If this flag is required, I can update the PR accordingly.
For cases without CFG_REE_FS_INTEGRITY_RPMB, it would be better to have an alternative method for handling hash records. Without hash records, I suggest keeping the current implementation or use flag: CFG_INSECURE to control whether automatically removing corrupted dirf.db if it doesn't open correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OP-TEE currently supports 2 ways to protect REE_FS against rollback: RPMB (based on a hash) and Monotonic Counter (nv_counter_get_ree_fs()). Should it be addressed here?
Suggestion:
/*
* Recreate the database if the rollback protection does
* not protect its state.
*/
if (create ||
(IS_ENABLED(CFG_REE_FS_INTEGRITY_RPMB) && !hash) ||
(!IS_ENABLED(CFG_REE_FS_INTEGRITY_RPMB) && !min_counter)) {which could factorize to if (create || (!hash && !min_counter)).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Etienne,
Thank you for providing clear instructions. I will update the pull request.
066478d to
e6e9651
Compare
During the creation of the OP-TEE REE-FS database file, several RPC commands are executed. If an unexpected power outage occurs during the initial database setup in mass production, an incomplete dirf.db file with a size of 0 bytes may be left behind. This patch updates the flow to automatically remove an empty dirf.db file if rollback protection does not safeguard its state. This allows the caller to recreate the dirf.db file as needed. Link: OP-TEE#7512 Signed-off-by: Ox Yeh <ox.yeh@mediatek.com>
e6e9651 to
321e90c
Compare
When a trusted application uses the REE-FS secure store API during the first boot, OP-TEE OS creates the dirf.db file. If a power outage occurs immediately after the creation of dirf.db, it may result in an empty file with an unset hash. This corrupted dirf.db file blocks subsequent REE-FS secure store operations. This commit addresses the issue by allowing the system to detect and delete an empty, corrupted dirf.db file, enabling secure store operations to proceed.
How to Simulate
422 static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash,423 uint32_t min_counter,424 const TEE_UUID *uuid,425 struct tee_fs_dirfile_fileh *dfh,426 struct tee_file_handle **fh)427 {428 TEE_Result res;429 struct tee_fs_fd *fdp;430431 fdp = calloc(1, sizeof(struct tee_fs_fd));432 if (!fdp)433 return TEE_ERROR_OUT_OF_MEMORY;434 fdp->fd = -1;435 fdp->uuid = uuid;436437 if (create)438 res = tee_fs_rpc_create_dfh(OPTEE_RPC_CMD_FS,439 dfh, &fdp->fd);440 else441 res = tee_fs_rpc_open_dfh(OPTEE_RPC_CMD_FS, dfh, &fdp->fd);442443 if (res != TEE_SUCCESS)444 goto out;Effect of the Commit
After applying this commit, the system will automatically remove a corrupted dirf.db file for this power outage case (i.e., a file with size 0 with an unset hash), allowing subsequent secure store operations to function correctly.