Bug #9749
closedkcephfs: kernel divide-by-zero crash in __validate_layout (fs/ceph/ioctl.c)
0%
Description
Our UC-KLEE tool discovered a Linux kernel divide-by-zero crash in the Ceph
client driver. I found the bug on kernel 3.16.3, but it appears to date back to
commit 8f4e91dee2a245e4be6942f4a8d83a769e13a47d (2009-10-06).
The bug occurs in the ioctl code for CEPH_IOC_SET_LAYOUT and
CEPH_IOC_SET_LAYOUT_POLICY, which improperly checks the userspace input before
using it as the divisor in a modulus (%) operation.
This bug appears to be exploitable by a non-privileged user issuing an offending
ioctl.
The backtraces reported by our tool are:
__validate_layout () at fs/ceph/ioctl.c:42
ceph_ioctl_set_layout () at fs/ceph/ioctl.c:102
ceph_ioctl () at fs/ceph/ioctl.c:279
__validate_layout () at fs/ceph/ioctl.c:42
ceph_ioctl_set_layout_policy () at fs/ceph/ioctl.c:147
ceph_ioctl () at fs/ceph/ioctl.c:282
The offending code in fs/ceph/ioctl.c is as follows:
42 if ((l->object_size & ~PAGE_MASK) ||
43 (l->stripe_unit & ~PAGE_MASK) ||
44 (l->stripe_unit != 0 &&
45 ((unsigned)l->object_size % (unsigned)l->stripe_unit)))
46 return -EINVAL;
The 'stripe_unit' field is 64 bits, so a value such as 0xff00000000000000 will
pass the "stripe_unit != 0" test but result in a zero divisor once cast to
32 bits on line 45.