Skip to content

Commit 74058c0

Browse files
plougherakpm00
authored andcommitted
Squashfs: fix uninit-value in squashfs_get_parent
Syzkaller reports a "KMSAN: uninit-value in squashfs_get_parent" bug. This is caused by open_by_handle_at() being called with a file handle containing an invalid parent inode number. In particular the inode number is that of a symbolic link, rather than a directory. Squashfs_get_parent() gets called with that symbolic link inode, and accesses the parent member field. unsigned int parent_ino = squashfs_i(inode)->parent; Because non-directory inodes in Squashfs do not have a parent value, this is uninitialised, and this causes an uninitialised value access. The fix is to initialise parent with the invalid inode 0, which will cause an EINVAL error to be returned. Regular inodes used to share the parent field with the block_list_start field. This is removed in this commit to enable the parent field to contain the invalid inode number 0. Link: https://lkml.kernel.org/r/[email protected] Fixes: 1226014 ("Squashfs: export operations") Signed-off-by: Phillip Lougher <[email protected]> Reported-by: [email protected] Closes: https://lore.kernel.org/all/[email protected]/ Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent f322a97 commit 74058c0

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

fs/squashfs/inode.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
169169
squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
170170
squashfs_i(inode)->block_list_start = block;
171171
squashfs_i(inode)->offset = offset;
172+
squashfs_i(inode)->parent = 0;
172173
inode->i_data.a_ops = &squashfs_aops;
173174

174175
TRACE("File inode %x:%x, start_block %llx, block_list_start "
@@ -216,6 +217,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
216217
squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
217218
squashfs_i(inode)->block_list_start = block;
218219
squashfs_i(inode)->offset = offset;
220+
squashfs_i(inode)->parent = 0;
219221
inode->i_data.a_ops = &squashfs_aops;
220222

221223
TRACE("File inode %x:%x, start_block %llx, block_list_start "
@@ -296,6 +298,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
296298
inode->i_mode |= S_IFLNK;
297299
squashfs_i(inode)->start = block;
298300
squashfs_i(inode)->offset = offset;
301+
squashfs_i(inode)->parent = 0;
299302

300303
if (type == SQUASHFS_LSYMLINK_TYPE) {
301304
__le32 xattr;
@@ -333,6 +336,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
333336
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
334337
rdev = le32_to_cpu(sqsh_ino->rdev);
335338
init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
339+
squashfs_i(inode)->parent = 0;
336340

337341
TRACE("Device inode %x:%x, rdev %x\n",
338342
SQUASHFS_INODE_BLK(ino), offset, rdev);
@@ -357,6 +361,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
357361
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
358362
rdev = le32_to_cpu(sqsh_ino->rdev);
359363
init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
364+
squashfs_i(inode)->parent = 0;
360365

361366
TRACE("Device inode %x:%x, rdev %x\n",
362367
SQUASHFS_INODE_BLK(ino), offset, rdev);
@@ -377,6 +382,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
377382
inode->i_mode |= S_IFSOCK;
378383
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
379384
init_special_inode(inode, inode->i_mode, 0);
385+
squashfs_i(inode)->parent = 0;
380386
break;
381387
}
382388
case SQUASHFS_LFIFO_TYPE:
@@ -396,6 +402,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
396402
inode->i_op = &squashfs_inode_ops;
397403
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
398404
init_special_inode(inode, inode->i_mode, 0);
405+
squashfs_i(inode)->parent = 0;
399406
break;
400407
}
401408
default:

fs/squashfs/squashfs_fs_i.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct squashfs_inode_info {
1616
u64 xattr;
1717
unsigned int xattr_size;
1818
int xattr_count;
19+
int parent;
1920
union {
2021
struct {
2122
u64 fragment_block;
@@ -27,7 +28,6 @@ struct squashfs_inode_info {
2728
u64 dir_idx_start;
2829
int dir_idx_offset;
2930
int dir_idx_cnt;
30-
int parent;
3131
};
3232
};
3333
struct inode vfs_inode;

0 commit comments

Comments
 (0)