Files
kernel_arpi/fs/incfs/vfs.h
Tadeusz Struk d5faa13b59 ANDROID: incremental-fs: fix mount_fs issue
Syzbot recently found a number of issues related to incremental-fs
(see bug numbers below). All have to do with the fact that incr-fs
allows mounts of the same source and target multiple times.
The correct behavior for a file system is to allow only one such
mount, and then every subsequent attempt should fail with a -EBUSY
error code. In case of the issues listed below the common pattern
is that the reproducer calls:

mount("./file0", "./file0", "incremental-fs", 0, NULL)

many times and then invokes a file operation like chmod, setxattr,
or open on the ./file0. This causes a recursive call for all the
mounted instances, which eventually causes a stack overflow and
a kernel crash:

BUG: stack guard page was hit at ffffc90000c0fff8
kernel stack overflow (double-fault): 0000 [#1] PREEMPT SMP KASAN

The reason why many mounts with the same source and target are
possible is because the incfs_mount_fs() as it is allocates a new
super_block for every call, regardless of whether a given mount already
exists or not. This happens every time the sget() function is called
with a test param equal to NULL.
The correct behavior for an FS mount implementation is to call
appropriate mount vfs call for it's type, i.e. mount_bdev() for
a block device backed FS, mount_single() for a pseudo file system,
like sysfs that is mounted in a single, well know location, or
mount_nodev() for other special purpose FS like overlayfs.
In case of incremental-fs the open coded mount logic doesn't check
for abusive mount attempts such as overlays.
To fix this issue the logic needs to be changed to pass a proper
test function to sget() call, which then checks if a super_block
for a mount instance has already been allocated and also allows
the VFS to properly verify invalid mount attempts.

Bug: 211066171
Bug: 213140206
Bug: 213215835
Bug: 211914587
Bug: 211213635
Bug: 213137376
Bug: 211161296

Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
Change-Id: I66cfc3f1b5aaffb32b0845b2dad3ff26fe952e27
2022-01-26 09:00:23 +00:00

33 lines
768 B
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2018 Google LLC
*/
#ifndef _INCFS_VFS_H
#define _INCFS_VFS_H
extern const struct file_operations incfs_file_ops;
extern const struct inode_operations incfs_file_inode_ops;
void incfs_kill_sb(struct super_block *sb);
struct dentry *incfs_mount_fs(struct file_system_type *type, int flags,
const char *dev_name, void *data);
int incfs_link(struct dentry *what, struct dentry *where);
int incfs_unlink(struct dentry *dentry);
static inline struct mount_info *get_mount_info(struct super_block *sb)
{
struct mount_info *result = sb->s_fs_info;
return result;
}
static inline struct super_block *file_superblock(struct file *f)
{
struct inode *inode = file_inode(f);
return inode->i_sb;
}
#endif