Skip to content

Commit 73fb094

Browse files
Luis Henriquesidryomov
authored andcommitted
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+ torvalds#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 <[email protected]> Reviewed-by: "Yan, Zheng" <[email protected]> Signed-off-by: Ilya Dryomov <[email protected]>
1 parent aae1a44 commit 73fb094

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

fs/ceph/super.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void ceph_put_super(struct super_block *s)
4545
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
4646
{
4747
struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
48-
struct ceph_monmap *monmap = fsc->client->monc.monmap;
48+
struct ceph_mon_client *monc = &fsc->client->monc;
4949
struct ceph_statfs st;
5050
u64 fsid;
5151
int err;
@@ -58,7 +58,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
5858
}
5959

6060
dout("statfs\n");
61-
err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st);
61+
err = ceph_monc_do_statfs(monc, data_pool, &st);
6262
if (err < 0)
6363
return err;
6464

@@ -94,8 +94,11 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
9494
buf->f_namelen = NAME_MAX;
9595

9696
/* Must convert the fsid, for consistent values across arches */
97-
fsid = le64_to_cpu(*(__le64 *)(&monmap->fsid)) ^
98-
le64_to_cpu(*((__le64 *)&monmap->fsid + 1));
97+
mutex_lock(&monc->mutex);
98+
fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^
99+
le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1));
100+
mutex_unlock(&monc->mutex);
101+
99102
buf->f_fsid.val[0] = fsid & 0xffffffff;
100103
buf->f_fsid.val[1] = fsid >> 32;
101104

0 commit comments

Comments
 (0)