Skip to content

Commit fe21a3d

Browse files
tiwaigregkh
authored andcommitted
ALSA: vx: Fix possible transfer overflow
[ Upstream commit 874e1f6fad9a5184b67f4cee37c1335cd2cc5677 ] The pseudo DMA transfer codes in VX222 and VX-pocket driver have a slight bug where they check the buffer boundary wrongly, and may overflow. Also, the zero sample count might be handled badly for the playback (although it shouldn't happen in theory). This patch addresses these issues. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=141541 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3b985d3 commit fe21a3d

3 files changed

Lines changed: 16 additions & 14 deletions

File tree

sound/drivers/vx/vx_pcm.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,8 +1048,10 @@ static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream
10481048
/* ok, let's accelerate! */
10491049
int align = pipe->align * 3;
10501050
space = (count / align) * align;
1051-
vx_pseudo_dma_read(chip, runtime, pipe, space);
1052-
count -= space;
1051+
if (space > 0) {
1052+
vx_pseudo_dma_read(chip, runtime, pipe, space);
1053+
count -= space;
1054+
}
10531055
}
10541056
/* read the rest of bytes */
10551057
while (count > 0) {

sound/pci/vx222/vx222_ops.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,12 +269,12 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
269269

270270
/* Transfer using pseudo-dma.
271271
*/
272-
if (offset + count > pipe->buffer_bytes) {
272+
if (offset + count >= pipe->buffer_bytes) {
273273
int length = pipe->buffer_bytes - offset;
274274
count -= length;
275275
length >>= 2; /* in 32bit words */
276276
/* Transfer using pseudo-dma. */
277-
while (length-- > 0) {
277+
for (; length > 0; length--) {
278278
outl(cpu_to_le32(*addr), port);
279279
addr++;
280280
}
@@ -284,7 +284,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
284284
pipe->hw_ptr += count;
285285
count >>= 2; /* in 32bit words */
286286
/* Transfer using pseudo-dma. */
287-
while (count-- > 0) {
287+
for (; count > 0; count--) {
288288
outl(cpu_to_le32(*addr), port);
289289
addr++;
290290
}
@@ -307,20 +307,20 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
307307
vx2_setup_pseudo_dma(chip, 0);
308308
/* Transfer using pseudo-dma.
309309
*/
310-
if (offset + count > pipe->buffer_bytes) {
310+
if (offset + count >= pipe->buffer_bytes) {
311311
int length = pipe->buffer_bytes - offset;
312312
count -= length;
313313
length >>= 2; /* in 32bit words */
314314
/* Transfer using pseudo-dma. */
315-
while (length-- > 0)
315+
for (; length > 0; length--)
316316
*addr++ = le32_to_cpu(inl(port));
317317
addr = (u32 *)runtime->dma_area;
318318
pipe->hw_ptr = 0;
319319
}
320320
pipe->hw_ptr += count;
321321
count >>= 2; /* in 32bit words */
322322
/* Transfer using pseudo-dma. */
323-
while (count-- > 0)
323+
for (; count > 0; count--)
324324
*addr++ = le32_to_cpu(inl(port));
325325

326326
vx2_release_pseudo_dma(chip);

sound/pcmcia/vx/vxp_ops.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,12 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
369369
unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
370370

371371
vx_setup_pseudo_dma(chip, 1);
372-
if (offset + count > pipe->buffer_bytes) {
372+
if (offset + count >= pipe->buffer_bytes) {
373373
int length = pipe->buffer_bytes - offset;
374374
count -= length;
375375
length >>= 1; /* in 16bit words */
376376
/* Transfer using pseudo-dma. */
377-
while (length-- > 0) {
377+
for (; length > 0; length--) {
378378
outw(cpu_to_le16(*addr), port);
379379
addr++;
380380
}
@@ -384,7 +384,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
384384
pipe->hw_ptr += count;
385385
count >>= 1; /* in 16bit words */
386386
/* Transfer using pseudo-dma. */
387-
while (count-- > 0) {
387+
for (; count > 0; count--) {
388388
outw(cpu_to_le16(*addr), port);
389389
addr++;
390390
}
@@ -411,20 +411,20 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
411411
if (snd_BUG_ON(count % 2))
412412
return;
413413
vx_setup_pseudo_dma(chip, 0);
414-
if (offset + count > pipe->buffer_bytes) {
414+
if (offset + count >= pipe->buffer_bytes) {
415415
int length = pipe->buffer_bytes - offset;
416416
count -= length;
417417
length >>= 1; /* in 16bit words */
418418
/* Transfer using pseudo-dma. */
419-
while (length-- > 0)
419+
for (; length > 0; length--)
420420
*addr++ = le16_to_cpu(inw(port));
421421
addr = (unsigned short *)runtime->dma_area;
422422
pipe->hw_ptr = 0;
423423
}
424424
pipe->hw_ptr += count;
425425
count >>= 1; /* in 16bit words */
426426
/* Transfer using pseudo-dma. */
427-
while (count-- > 1)
427+
for (; count > 1; count--)
428428
*addr++ = le16_to_cpu(inw(port));
429429
/* Disable DMA */
430430
pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK;

0 commit comments

Comments
 (0)