Skip to content

Commit 38282ba

Browse files
JustinStittceladon
authored and
celadon
committed
cdrom: rearrange last_media_change check to avoid unintentional overflow
[ Upstream commit efb905aeb44b0e99c0e6b07865b1885ae0471ebf ] When running syzkaller with the newly reintroduced signed integer wrap sanitizer we encounter this splat: [ 366.015950] UBSAN: signed-integer-overflow in ../drivers/cdrom/cdrom.c:2361:33 [ 366.021089] -9223372036854775808 - 346321 cannot be represented in type '__s64' (aka 'long long') [ 366.025894] program syz-executor.4 is using a deprecated SCSI ioctl, please convert it to SG_IO [ 366.027502] CPU: 5 PID: 28472 Comm: syz-executor.7 Not tainted 6.8.0-rc2-00035-gb3ef86b5a957 #1 [ 366.027512] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 366.027518] Call Trace: [ 366.027523] <TASK> [ 366.027533] dump_stack_lvl+0x93/0xd0 [ 366.027899] handle_overflow+0x171/0x1b0 [ 366.038787] ata1.00: invalid multi_count 32 ignored [ 366.043924] cdrom_ioctl+0x2c3f/0x2d10 [ 366.063932] ? __pm_runtime_resume+0xe6/0x130 [ 366.071923] sr_block_ioctl+0x15d/0x1d0 [ 366.074624] ? __pfx_sr_block_ioctl+0x10/0x10 [ 366.077642] blkdev_ioctl+0x419/0x500 [ 366.080231] ? __pfx_blkdev_ioctl+0x10/0x10 ... Historically, the signed integer overflow sanitizer did not work in the kernel due to its interaction with `-fwrapv` but this has since been changed [1] in the newest version of Clang. It was re-enabled in the kernel with Commit 557f8c582a9ba8ab ("ubsan: Reintroduce signed overflow sanitizer"). Let's rearrange the check to not perform any arithmetic, thus not tripping the sanitizer. Link: llvm/llvm-project#82432 [1] Closes: KSPP/linux#354 Cc: [email protected] Signed-off-by: Justin Stitt <[email protected]> Link: https://lore.kernel.org/lkml/[email protected] Reviewed-by: Phillip Potter <[email protected]> Link: https://lore.kernel.org/lkml/ZjqU0fbzHrlnad8D@equinox Signed-off-by: Phillip Potter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 5e3365c commit 38282ba

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

drivers/cdrom/cdrom.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,49 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
23362336
return ret;
23372337
}
23382338

2339+
/*
2340+
* Media change detection with timing information.
2341+
*
2342+
* arg is a pointer to a cdrom_timed_media_change_info struct.
2343+
* arg->last_media_change may be set by calling code to signal
2344+
* the timestamp (in ms) of the last known media change (by the caller).
2345+
* Upon successful return, ioctl call will set arg->last_media_change
2346+
* to the latest media change timestamp known by the kernel/driver
2347+
* and set arg->has_changed to 1 if that timestamp is more recent
2348+
* than the timestamp set by the caller.
2349+
*/
2350+
static int cdrom_ioctl_timed_media_change(struct cdrom_device_info *cdi,
2351+
unsigned long arg)
2352+
{
2353+
int ret;
2354+
struct cdrom_timed_media_change_info __user *info;
2355+
struct cdrom_timed_media_change_info tmp_info;
2356+
2357+
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
2358+
return -ENOSYS;
2359+
2360+
info = (struct cdrom_timed_media_change_info __user *)arg;
2361+
cd_dbg(CD_DO_IOCTL, "entering CDROM_TIMED_MEDIA_CHANGE\n");
2362+
2363+
ret = cdrom_ioctl_media_changed(cdi, CDSL_CURRENT);
2364+
if (ret < 0)
2365+
return ret;
2366+
2367+
if (copy_from_user(&tmp_info, info, sizeof(tmp_info)) != 0)
2368+
return -EFAULT;
2369+
2370+
tmp_info.media_flags = 0;
2371+
if (cdi->last_media_change_ms > tmp_info.last_media_change)
2372+
tmp_info.media_flags |= MEDIA_CHANGED_FLAG;
2373+
2374+
tmp_info.last_media_change = cdi->last_media_change_ms;
2375+
2376+
if (copy_to_user(info, &tmp_info, sizeof(*info)) != 0)
2377+
return -EFAULT;
2378+
2379+
return 0;
2380+
}
2381+
23392382
static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
23402383
unsigned long arg)
23412384
{

0 commit comments

Comments
 (0)