Skip to content

Commit ff9dd3d

Browse files
2045geminigregkh
authored andcommitted
media: rainshadow-cec: fix TOCTOU race condition in rain_interrupt()
commit 7af160a upstream. In the interrupt handler rain_interrupt(), the buffer full check on rain->buf_len is performed before acquiring rain->buf_lock. This creates a Time-of-Check to Time-of-Use (TOCTOU) race condition, as rain->buf_len is concurrently accessed and modified in the work handler rain_irq_work_handler() under the same lock. Multiple interrupt invocations can race, with each reading buf_len before it becomes full and then proceeding. This can lead to both interrupts attempting to write to the buffer, incrementing buf_len beyond its capacity (DATA_SIZE) and causing a buffer overflow. Fix this bug by moving the spin_lock() to before the buffer full check. This ensures that the check and the subsequent buffer modification are performed atomically, preventing the race condition. An corresponding spin_unlock() is added to the overflow path to correctly release the lock. This possible bug was found by an experimental static analysis tool developed by our team. Fixes: 0f314f6 ("[media] rainshadow-cec: new RainShadow Tech HDMI CEC driver") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 9f886d2 commit ff9dd3d

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

drivers/media/cec/usb/rainshadow/rainshadow-cec.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,12 @@ static irqreturn_t rain_interrupt(struct serio *serio, unsigned char data,
171171
{
172172
struct rain *rain = serio_get_drvdata(serio);
173173

174+
spin_lock(&rain->buf_lock);
174175
if (rain->buf_len == DATA_SIZE) {
176+
spin_unlock(&rain->buf_lock);
175177
dev_warn_once(rain->dev, "buffer overflow\n");
176178
return IRQ_HANDLED;
177179
}
178-
spin_lock(&rain->buf_lock);
179180
rain->buf_len++;
180181
rain->buf[rain->buf_wr_idx] = data;
181182
rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff;

0 commit comments

Comments
 (0)