Skip to content

Commit 0bd0db4

Browse files
ian-abbottgregkh
authored andcommitted
staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
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 f07804e commit 0bd0db4

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
@@ -106,14 +106,22 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
106106
unsigned int *data)
107107
{
108108
struct apci1032_private *devpriv = dev->private;
109-
unsigned int shift, oldmask;
109+
unsigned int shift, oldmask, himask, lomask;
110110

111111
switch (data[0]) {
112112
case INSN_CONFIG_DIGITAL_TRIG:
113113
if (data[1] != 0)
114114
return -EINVAL;
115115
shift = data[3];
116-
oldmask = (1U << shift) - 1;
116+
if (shift < 32) {
117+
oldmask = (1U << shift) - 1;
118+
himask = data[4] << shift;
119+
lomask = data[5] << shift;
120+
} else {
121+
oldmask = 0xffffffffu;
122+
himask = 0;
123+
lomask = 0;
124+
}
117125
switch (data[2]) {
118126
case COMEDI_DIGITAL_TRIG_DISABLE:
119127
devpriv->ctrl = 0;
@@ -136,8 +144,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
136144
devpriv->mode2 &= oldmask;
137145
}
138146
/* configure specified channels */
139-
devpriv->mode1 |= data[4] << shift;
140-
devpriv->mode2 |= data[5] << shift;
147+
devpriv->mode1 |= himask;
148+
devpriv->mode2 |= lomask;
141149
break;
142150
case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
143151
if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
@@ -154,8 +162,8 @@ static int apci1032_cos_insn_config(struct comedi_device *dev,
154162
devpriv->mode2 &= oldmask;
155163
}
156164
/* configure specified channels */
157-
devpriv->mode1 |= data[4] << shift;
158-
devpriv->mode2 |= data[5] << shift;
165+
devpriv->mode1 |= himask;
166+
devpriv->mode2 |= lomask;
159167
break;
160168
default:
161169
return -EINVAL;

0 commit comments

Comments
 (0)