Skip to content

Commit 1ab8425

Browse files
konisakpm00
authored andcommitted
nilfs2: fix inode number range checks
Patch series "nilfs2: fix potential issues related to reserved inodes". This series fixes one use-after-free issue reported by syzbot, caused by nilfs2's internal inode being exposed in the namespace on a corrupted filesystem, and a couple of flaws that cause problems if the starting number of non-reserved inodes written in the on-disk super block is intentionally (or corruptly) changed from its default value. This patch (of 3): In the current implementation of nilfs2, "nilfs->ns_first_ino", which gives the first non-reserved inode number, is read from the superblock, but its lower limit is not checked. As a result, if a number that overlaps with the inode number range of reserved inodes such as the root directory or metadata files is set in the super block parameter, the inode number test macros (NILFS_MDT_INODE and NILFS_VALID_INODE) will not function properly. In addition, these test macros use left bit-shift calculations using with the inode number as the shift count via the BIT macro, but the result of a shift calculation that exceeds the bit width of an integer is undefined in the C specification, so if "ns_first_ino" is set to a large value other than the default value NILFS_USER_INO (=11), the macros may potentially malfunction depending on the environment. Fix these issues by checking the lower bound of "nilfs->ns_first_ino" and by preventing bit shifts equal to or greater than the NILFS_USER_INO constant in the inode number test macros. Also, change the type of "ns_first_ino" from signed integer to unsigned integer to avoid the need for type casting in comparisons such as the lower bound check introduced this time. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ryusuke Konishi <[email protected]> Cc: Hillf Danton <[email protected]> Cc: Jan Kara <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 68ed2a3 commit 1ab8425

File tree

3 files changed

+10
-3
lines changed

3 files changed

+10
-3
lines changed

fs/nilfs2/nilfs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ enum {
116116
#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
117117

118118
#define NILFS_MDT_INODE(sb, ino) \
119-
((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & BIT(ino)))
119+
((ino) < NILFS_USER_INO && (NILFS_MDT_INO_BITS & BIT(ino)))
120120
#define NILFS_VALID_INODE(sb, ino) \
121-
((ino) >= NILFS_FIRST_INO(sb) || (NILFS_SYS_INO_BITS & BIT(ino)))
121+
((ino) >= NILFS_FIRST_INO(sb) || \
122+
((ino) < NILFS_USER_INO && (NILFS_SYS_INO_BITS & BIT(ino))))
122123

123124
/**
124125
* struct nilfs_transaction_info: context information for synchronization

fs/nilfs2/the_nilfs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,12 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
452452
}
453453

454454
nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino);
455+
if (nilfs->ns_first_ino < NILFS_USER_INO) {
456+
nilfs_err(nilfs->ns_sb,
457+
"too small lower limit for non-reserved inode numbers: %u",
458+
nilfs->ns_first_ino);
459+
return -EINVAL;
460+
}
455461

456462
nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
457463
if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) {

fs/nilfs2/the_nilfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ struct the_nilfs {
182182
unsigned long ns_nrsvsegs;
183183
unsigned long ns_first_data_block;
184184
int ns_inode_size;
185-
int ns_first_ino;
185+
unsigned int ns_first_ino;
186186
u32 ns_crc_seed;
187187

188188
/* /sys/fs/<nilfs>/<device> */

0 commit comments

Comments
 (0)