Skip to content

Commit 08ae4b2

Browse files
ian-abbottgregkh
authored andcommitted
comedi: Fail COMEDI_INSNLIST ioctl if n_insns is too large
The handling of the `COMEDI_INSNLIST` ioctl allocates a kernel buffer to hold the array of `struct comedi_insn`, getting the length from the `n_insns` member of the `struct comedi_insnlist` supplied by the user. The allocation will fail with a WARNING and a stack dump if it is too large. Avoid that by failing with an `-EINVAL` error if the supplied `n_insns` value is unreasonable. Define the limit on the `n_insns` value in the `MAX_INSNS` macro. Set this to the same value as `MAX_SAMPLES` (65536), which is the maximum allowed sum of the values of the member `n` in the array of `struct comedi_insn`, and sensible comedi instructions will have an `n` of at least 1. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=d6995b62e5ac7d79557a Fixes: ed9eccb ("Staging: add comedi core") Tested-by: Ian Abbott <[email protected]> Cc: [email protected] # 5.13+ Signed-off-by: Ian Abbott <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2aa4ad6 commit 08ae4b2

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

drivers/comedi/comedi_fops.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,16 @@ static int do_insnlist_ioctl(struct comedi_device *dev,
15891589
return i;
15901590
}
15911591

1592+
#define MAX_INSNS MAX_SAMPLES
1593+
static int check_insnlist_len(struct comedi_device *dev, unsigned int n_insns)
1594+
{
1595+
if (n_insns > MAX_INSNS) {
1596+
dev_dbg(dev->class_dev, "insnlist length too large\n");
1597+
return -EINVAL;
1598+
}
1599+
return 0;
1600+
}
1601+
15921602
/*
15931603
* COMEDI_INSN ioctl
15941604
* synchronous instruction
@@ -2239,6 +2249,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
22392249
rc = -EFAULT;
22402250
break;
22412251
}
2252+
rc = check_insnlist_len(dev, insnlist.n_insns);
2253+
if (rc)
2254+
break;
22422255
insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
22432256
if (!insns) {
22442257
rc = -ENOMEM;
@@ -3142,6 +3155,9 @@ static int compat_insnlist(struct file *file, unsigned long arg)
31423155
if (copy_from_user(&insnlist32, compat_ptr(arg), sizeof(insnlist32)))
31433156
return -EFAULT;
31443157

3158+
rc = check_insnlist_len(dev, insnlist32.n_insns);
3159+
if (rc)
3160+
return rc;
31453161
insns = kcalloc(insnlist32.n_insns, sizeof(*insns), GFP_KERNEL);
31463162
if (!insns)
31473163
return -ENOMEM;

0 commit comments

Comments
 (0)