aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2023-05-29 21:58:20 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2023-05-29 21:58:20 +0000
commit6a71277c3037df2c3a70464c2e2bf20dec2c128a (patch)
tree2d09a267c1b55dd491520124d212936a6ee57322
parent5267120645fa52eac771c9bd8e28d68620a3bb89 (diff)
downloadsrc-6a71277c3037df2c3a70464c2e2bf20dec2c128a.tar.gz
src-6a71277c3037df2c3a70464c2e2bf20dec2c128a.zip
Fix a bug in fsck_ffs(8) triggered by corrupted filesystems.
When loading the root directory ensure that it is a directory and has a size greater than the minimum directory size. If an invalid root directory is found, fall back to full fsck. Reported-by: Robert Morris PR: 271414 MFC-after: 1 week Sponsored-by: The FreeBSD Foundation
-rw-r--r--sbin/fsck_ffs/suj.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index c86d6b711635..1e935b864b7c 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -2377,7 +2377,7 @@ suj_check(const char *filesys)
{
struct inodesc idesc;
struct csum *cgsum;
- union dinode *jip;
+ union dinode *dp, *jip;
struct inode ip;
uint64_t blocks;
int i, retval;
@@ -2419,7 +2419,17 @@ suj_check(const char *filesys)
idesc.id_func = findino;
idesc.id_name = SUJ_FILE;
ginode(UFS_ROOTINO, &ip);
- if ((ckinode(ip.i_dp, &idesc) & FOUND) == FOUND) {
+ dp = ip.i_dp;
+ if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
+ irelse(&ip);
+ err_suj("root inode is not a directory\n");
+ }
+ if (DIP(dp, di_size) < 0 || DIP(dp, di_size) > MAXDIRSIZE) {
+ irelse(&ip);
+ err_suj("negative or oversized root directory %jd\n",
+ (uintmax_t)DIP(dp, di_size));
+ }
+ if ((ckinode(dp, &idesc) & FOUND) == FOUND) {
sujino = idesc.id_parent;
irelse(&ip);
} else {