Project

General

Profile

Actions

Bug #9749

closed

kcephfs: kernel divide-by-zero crash in __validate_layout (fs/ceph/ioctl.c)

Added by David Ramos over 9 years ago. Updated over 9 years ago.

Status:
Resolved
Priority:
Urgent
Assignee:
Category:
-
Target version:
-
% Done:

0%

Source:
other
Tags:
Backport:
Regression:
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Crash signature (v1):
Crash signature (v2):

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.

Actions

Also available in: Atom PDF