mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
ceph: fix use-after-free in ceph_statfs()
KASAN found an UAF in ceph_statfs. This was a one-off bug but looking at the code it looks like the monmap access needs to be protected as it can be modified while we're accessing it. Fix this by protecting the access with the monc->mutex. BUG: KASAN: use-after-free in ceph_statfs+0x21d/0x2c0 Read of size 8 at addr ffff88006844f2e0 by task trinity-c5/304 CPU: 0 PID: 304 Comm: trinity-c5 Not tainted 4.17.0-rc6+ #172 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.0.0-prebuilt.qemu-project.org 04/01/2014 Call Trace: dump_stack+0xa5/0x11b ? show_regs_print_info+0x5/0x5 ? kmsg_dump_rewind+0x118/0x118 ? ceph_statfs+0x21d/0x2c0 print_address_description+0x73/0x2b0 ? ceph_statfs+0x21d/0x2c0 kasan_report+0x243/0x360 ceph_statfs+0x21d/0x2c0 ? ceph_umount_begin+0x80/0x80 ? kmem_cache_alloc+0xdf/0x1a0 statfs_by_dentry+0x79/0xb0 vfs_statfs+0x28/0x110 user_statfs+0x8c/0xe0 ? vfs_statfs+0x110/0x110 ? __fdget_raw+0x10/0x10 __se_sys_statfs+0x5d/0xa0 ? user_statfs+0xe0/0xe0 ? mutex_unlock+0x1d/0x40 ? __x64_sys_statfs+0x20/0x30 do_syscall_64+0xee/0x290 ? syscall_return_slowpath+0x1c0/0x1c0 ? page_fault+0x1e/0x30 ? syscall_return_slowpath+0x13c/0x1c0 ? prepare_exit_to_usermode+0xdb/0x140 ? syscall_trace_enter+0x330/0x330 ? __put_user_4+0x1c/0x30 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Allocated by task 130: __kmalloc+0x124/0x210 ceph_monmap_decode+0x1c1/0x400 dispatch+0x113/0xd20 ceph_con_workfn+0xa7e/0x44e0 process_one_work+0x5f0/0xa30 worker_thread+0x184/0xa70 kthread+0x1a0/0x1c0 ret_from_fork+0x35/0x40 Freed by task 130: kfree+0xb8/0x210 dispatch+0x15a/0xd20 ceph_con_workfn+0xa7e/0x44e0 process_one_work+0x5f0/0xa30 worker_thread+0x184/0xa70 kthread+0x1a0/0x1c0 ret_from_fork+0x35/0x40 Signed-off-by: Luis Henriques <lhenriques@suse.com> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
aae1a442f8
commit
73fb0949cf
@ -45,7 +45,7 @@ static void ceph_put_super(struct super_block *s)
|
||||
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
|
||||
struct ceph_monmap *monmap = fsc->client->monc.monmap;
|
||||
struct ceph_mon_client *monc = &fsc->client->monc;
|
||||
struct ceph_statfs st;
|
||||
u64 fsid;
|
||||
int err;
|
||||
@ -58,7 +58,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
}
|
||||
|
||||
dout("statfs\n");
|
||||
err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st);
|
||||
err = ceph_monc_do_statfs(monc, data_pool, &st);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -94,8 +94,11 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
buf->f_namelen = NAME_MAX;
|
||||
|
||||
/* Must convert the fsid, for consistent values across arches */
|
||||
fsid = le64_to_cpu(*(__le64 *)(&monmap->fsid)) ^
|
||||
le64_to_cpu(*((__le64 *)&monmap->fsid + 1));
|
||||
mutex_lock(&monc->mutex);
|
||||
fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^
|
||||
le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1));
|
||||
mutex_unlock(&monc->mutex);
|
||||
|
||||
buf->f_fsid.val[0] = fsid & 0xffffffff;
|
||||
buf->f_fsid.val[1] = fsid >> 32;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user