ubifs: master area fails to recover when master node 1 is corrupted
Zhihao Cheng
chengzhihao1 at huawei.com
Sat Jan 27 01:39:13 PST 2024
在 2024/1/27 15:21, Ryder Wang 写道:
> Hi Zhihao,
>
> Your explanation is very professional. Thanks for it.
>
> But I still have a doubt about the code logic:
> ------------------------------------
> if (mst1) // false
> else {
> offs2 = (void *)mst2 - buf2; // offs2 = 0
> if (offs2 + sz + sz <= c->leb_size) // true, mst2 is the first node in LEB 2
> goto out_err
> }
> ------------------------------------
> 1. My testing result just proved that CRC-corrupted master#1 also runs to "else" clause of the code above, just like master#1 is unmapped.
> 2. For CRC corrupted master#1 case, the code logic looks inconsistent:
> 2.1. If master#2 LEB is just to be full, master#2 will be used to recover master area.
> 2.2. If master#2 LEB is not to be full, master recovering will be aborted with error.
>
> I think whether master#2 LEB is to be full has nothing to do with whether to recover master area in such case. How do you think about it?
Actually, UBIFS can still work even if master#2 is recovered in such
case(master#1 is corrupted), because the master#2 is the newest version.
The offset checking for master#2 LEB being full is a way to make sure
that UBIFS can find the newest master node. If we simply remove the
checking, UBIFS could go wrong in some situations, for example:
Powercut happens before writing mst2_v2 on LEB2, so the UBIFS image
looks like:
LEB1 LEB2
|mst1_v1 | mst1_v2 |0xFF 0xFF ... | |mst2_v1 | 0xFF 0xFF ... |
The mast1_v2 is expected to be recovered after exeucting
ubifs_recover_master_node(). If both mst1_v1 and mst1_v2 are corrupted,
UBIFS will enter into this branch:
if (mst1) // false
else {
offs2 = (void *)mst2 - buf2; // offs2 = 0
if (offs2 + sz + sz <= c->leb_size) // offset checking
goto out_err
mst = mst2;
}
If the offset checking is removed, mst_2_v1 is recovered, apperantly,
UBIFS picks wrong master node and it's not right.
So accodring to the realization of ubifs_recover_master_node(), UBFIS
choose the newest master node by various offset checking, it's just like
a whitelist of situations that UBIFS can fully trust on, other
situations are failure pathes, although some of failure pathes can make
UBIFS still get a right master node in some(not all) cases.
More information about the linux-mtd
mailing list