Skip to content

Commit b567ecd

Browse files
ian-abbottgregkh
authored andcommitted
staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
commit 0bd0db4 upstream. The `INSN_CONFIG` comedi instruction with sub-instruction code `INSN_CONFIG_DIGITAL_TRIG` includes a base channel in `data[3]`. This is used as a right shift amount for other bitmask values without being checked. Shift amounts greater than or equal to 32 will result in undefined behavior. Add code to deal with this. Fixes: 33cdce6 ("staging: comedi: addi_apci_1032: conform to new INSN_CONFIG_DIGITAL_TRIG") Cc: <[email protected]> #3.8+ 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 27e2944 commit b567ecd

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

drivers/staging/comedi/drivers/addi_apci_1032.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,22 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
115115
unsigned int *data)
116116
{
117117
struct apci1032_private *devpriv = dev->private;
118-
unsigned int shift, oldmask;
118+
unsigned int shift, oldmask, himask, lomask;
119119

120120
switch (data[0]) {
121121
case INSN_CONFIG_DIGITAL_TRIG:
122122
if (data[1] != 0)
123123
return -EINVAL;
124124
shift = data[3];
125-
oldmask = (1U << shift) - 1;
125+
if (shift < 32) {
126+
oldmask = (1U << shift) - 1;
127+
himask = data[4] << shift;
128+
lomask = data[5] << shift;
129+
} else {
130+
oldmask = 0xffffffffu;
131+
himask = 0;
132+
lomask = 0;
133+
}
126134
switch (data[2]) {
127135
case COMEDI_DIGITAL_TRIG_DISABLE:
128136
devpriv->ctrl = 0;
@@ -145,8 +153,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
145153
devpriv->mode2 &= oldmask;
146154
}
147155
/* configure specified channels */
148-
devpriv->mode1 |= data[4] << shift;
149-
devpriv->mode2 |= data[5] << shift;
156+
devpriv->mode1 |= himask;
157+
devpriv->mode2 |= lomask;
150158
break;
151159
case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
152160
if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
@@ -163,8 +171,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
163171
devpriv->mode2 &= oldmask;
164172
}
165173
/* configure specified channels */
166-
devpriv->mode1 |= data[4] << shift;
167-
devpriv->mode2 |= data[5] << shift;
174+
devpriv->mode1 |= himask;
175+
devpriv->mode2 |= lomask;
168176
break;
169177
default:
170178
return -EINVAL;

0 commit comments

Comments
 (0)