aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-12-06 23:35:34 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-07 11:39:31 -0500
commite45f4676108d19ae93918f06cb6731c86108341a (patch)
tree66811c091d94f77697835e53d6d9b052af143982 /sound
parent91046a8a693823d434f0aa70419c48ebeb8e1b11 (diff)
[PATCH] sound/oss/emu10k1: handle userspace copy errors
Propagate copy_to/from_user() errors back through callers. Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/oss/emu10k1/audio.c8
-rw-r--r--sound/oss/emu10k1/cardwi.c31
-rw-r--r--sound/oss/emu10k1/cardwi.h2
-rw-r--r--sound/oss/emu10k1/passthrough.c13
4 files changed, 38 insertions, 16 deletions
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
index 86dd23974e05..49f902f35c28 100644
--- a/sound/oss/emu10k1/audio.c
+++ b/sound/oss/emu10k1/audio.c
@@ -111,9 +111,15 @@ static ssize_t emu10k1_audio_read(struct file *file, char __user *buffer, size_t
111 111
112 if ((bytestocopy >= wiinst->buffer.fragment_size) 112 if ((bytestocopy >= wiinst->buffer.fragment_size)
113 || (bytestocopy >= count)) { 113 || (bytestocopy >= count)) {
114 int rc;
115
114 bytestocopy = min_t(u32, bytestocopy, count); 116 bytestocopy = min_t(u32, bytestocopy, count);
115 117
116 emu10k1_wavein_xferdata(wiinst, (u8 __user *)buffer, &bytestocopy); 118 rc = emu10k1_wavein_xferdata(wiinst,
119 (u8 __user *)buffer,
120 &bytestocopy);
121 if (rc)
122 return rc;
117 123
118 count -= bytestocopy; 124 count -= bytestocopy;
119 buffer += bytestocopy; 125 buffer += bytestocopy;
diff --git a/sound/oss/emu10k1/cardwi.c b/sound/oss/emu10k1/cardwi.c
index 8bbf44b881b4..060d1be94d33 100644
--- a/sound/oss/emu10k1/cardwi.c
+++ b/sound/oss/emu10k1/cardwi.c
@@ -304,11 +304,12 @@ void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
304 } 304 }
305} 305}
306 306
307static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov) 307static int copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
308{ 308{
309 if (cov == 1) 309 if (cov == 1) {
310 __copy_to_user(dst, src + str, len); 310 if (__copy_to_user(dst, src + str, len))
311 else { 311 return -EFAULT;
312 } else {
312 u8 byte; 313 u8 byte;
313 u32 i; 314 u32 i;
314 315
@@ -316,22 +317,26 @@ static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov)
316 317
317 for (i = 0; i < len; i++) { 318 for (i = 0; i < len; i++) {
318 byte = src[2 * i] ^ 0x80; 319 byte = src[2 * i] ^ 0x80;
319 __copy_to_user(dst + i, &byte, 1); 320 if (__copy_to_user(dst + i, &byte, 1))
321 return -EFAULT;
320 } 322 }
321 } 323 }
324
325 return 0;
322} 326}
323 327
324void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size) 328int emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
325{ 329{
326 struct wavein_buffer *buffer = &wiinst->buffer; 330 struct wavein_buffer *buffer = &wiinst->buffer;
327 u32 sizetocopy, sizetocopy_now, start; 331 u32 sizetocopy, sizetocopy_now, start;
328 unsigned long flags; 332 unsigned long flags;
333 int ret;
329 334
330 sizetocopy = min_t(u32, buffer->size, *size); 335 sizetocopy = min_t(u32, buffer->size, *size);
331 *size = sizetocopy; 336 *size = sizetocopy;
332 337
333 if (!sizetocopy) 338 if (!sizetocopy)
334 return; 339 return 0;
335 340
336 spin_lock_irqsave(&wiinst->lock, flags); 341 spin_lock_irqsave(&wiinst->lock, flags);
337 start = buffer->pos; 342 start = buffer->pos;
@@ -345,11 +350,17 @@ void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size)
345 if (sizetocopy > sizetocopy_now) { 350 if (sizetocopy > sizetocopy_now) {
346 sizetocopy -= sizetocopy_now; 351 sizetocopy -= sizetocopy_now;
347 352
348 copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov); 353 ret = copy_block(data, buffer->addr, start, sizetocopy_now,
349 copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov); 354 buffer->cov);
355 if (ret == 0)
356 ret = copy_block(data + sizetocopy_now, buffer->addr, 0,
357 sizetocopy, buffer->cov);
350 } else { 358 } else {
351 copy_block(data, buffer->addr, start, sizetocopy, buffer->cov); 359 ret = copy_block(data, buffer->addr, start, sizetocopy,
360 buffer->cov);
352 } 361 }
362
363 return ret;
353} 364}
354 365
355void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst) 366void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
diff --git a/sound/oss/emu10k1/cardwi.h b/sound/oss/emu10k1/cardwi.h
index 15cfb9b35596..e82029b46ad1 100644
--- a/sound/oss/emu10k1/cardwi.h
+++ b/sound/oss/emu10k1/cardwi.h
@@ -83,7 +83,7 @@ void emu10k1_wavein_close(struct emu10k1_wavedevice *);
83void emu10k1_wavein_start(struct emu10k1_wavedevice *); 83void emu10k1_wavein_start(struct emu10k1_wavedevice *);
84void emu10k1_wavein_stop(struct emu10k1_wavedevice *); 84void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
85void emu10k1_wavein_getxfersize(struct wiinst *, u32 *); 85void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
86void emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *); 86int emu10k1_wavein_xferdata(struct wiinst *, u8 __user *, u32 *);
87int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *); 87int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
88void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *); 88void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
89 89
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
index 4e3baca7d41f..6d21d4368dec 100644
--- a/sound/oss/emu10k1/passthrough.c
+++ b/sound/oss/emu10k1/passthrough.c
@@ -162,12 +162,15 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
162 162
163 DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed); 163 DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed);
164 if (count < needed) { 164 if (count < needed) {
165 copy_from_user(pt->buf + pt->prepend_size, buffer, count); 165 if (copy_from_user(pt->buf + pt->prepend_size,
166 buffer, count))
167 return -EFAULT;
166 pt->prepend_size += count; 168 pt->prepend_size += count;
167 DPD(3, "prepend size now %d\n", pt->prepend_size); 169 DPD(3, "prepend size now %d\n", pt->prepend_size);
168 return count; 170 return count;
169 } 171 }
170 copy_from_user(pt->buf + pt->prepend_size, buffer, needed); 172 if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed))
173 return -EFAULT;
171 r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock); 174 r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock);
172 if (r) 175 if (r)
173 return r; 176 return r;
@@ -178,7 +181,8 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
178 blocks_copied = 0; 181 blocks_copied = 0;
179 while (blocks > 0) { 182 while (blocks > 0) {
180 u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2); 183 u16 __user *bufptr = (u16 __user *) buffer + (bytes_copied/2);
181 copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE); 184 if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE))
185 return -EFAULT;
182 r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock); 186 r = pt_putblock(wave_dev, (u16 *)pt->buf, nonblock);
183 if (r) { 187 if (r) {
184 if (bytes_copied) 188 if (bytes_copied)
@@ -193,7 +197,8 @@ ssize_t emu10k1_pt_write(struct file *file, const char __user *buffer, size_t co
193 i = count - bytes_copied; 197 i = count - bytes_copied;
194 if (i) { 198 if (i) {
195 pt->prepend_size = i; 199 pt->prepend_size = i;
196 copy_from_user(pt->buf, buffer + bytes_copied, i); 200 if (copy_from_user(pt->buf, buffer + bytes_copied, i))
201 return -EFAULT;
197 bytes_copied += i; 202 bytes_copied += i;
198 DPD(3, "filling prepend buffer with %d bytes", i); 203 DPD(3, "filling prepend buffer with %d bytes", i);
199 } 204 }