X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fcore%2Finfo.c;h=1eb7d916a365159827d7fc688313c4639ea850c6;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=0b08203d50e5a743b5e13ab81db1d69e6f922ce7;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/sound/core/info.c b/sound/core/info.c index 0b08203d5..1eb7d916a 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -181,30 +181,37 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer, struct snd_info_entry *entry; snd_info_buffer_t *buf; size_t size = 0; + loff_t pos; data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO); snd_assert(data != NULL, return -ENXIO); + pos = *offset; + if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) + return -EIO; + if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) + return -EIO; entry = data->entry; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: buf = data->rbuffer; if (buf == NULL) return -EIO; - if (file->f_pos >= (long)buf->size) + if (pos >= buf->size) return 0; - size = buf->size - file->f_pos; + size = buf->size - pos; size = min(count, size); - if (copy_to_user(buffer, buf->buffer + file->f_pos, size)) + if (copy_to_user(buffer, buf->buffer + pos, size)) return -EFAULT; - file->f_pos += size; break; case SNDRV_INFO_CONTENT_DATA: if (entry->c.ops->read) - return entry->c.ops->read(entry, + size = entry->c.ops->read(entry, data->file_private_data, - file, buffer, count); + file, buffer, count, pos); break; } + if ((ssize_t) size > 0) + *offset = pos + size; return size; } @@ -215,34 +222,39 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer struct snd_info_entry *entry; snd_info_buffer_t *buf; size_t size = 0; + loff_t pos; data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO); snd_assert(data != NULL, return -ENXIO); entry = data->entry; + pos = *offset; + if (pos < 0 || (long) pos != pos || (ssize_t) count < 0) + return -EIO; + if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos) + return -EIO; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: buf = data->wbuffer; if (buf == NULL) return -EIO; - if (file->f_pos < 0) - return -EINVAL; - if (file->f_pos >= (long)buf->len) + if (pos >= buf->len) return -ENOMEM; - size = buf->len - file->f_pos; + size = buf->len - pos; size = min(count, size); - if (copy_from_user(buf->buffer + file->f_pos, buffer, size)) + if (copy_from_user(buf->buffer + pos, buffer, size)) return -EFAULT; - if ((long)buf->size < file->f_pos + size) - buf->size = file->f_pos + size; - file->f_pos += size; + if ((long)buf->size < pos + size) + buf->size = pos + size; break; case SNDRV_INFO_CONTENT_DATA: if (entry->c.ops->write) - return entry->c.ops->write(entry, + size = entry->c.ops->write(entry, data->file_private_data, - file, buffer, count); + file, buffer, count, pos); break; } + if ((ssize_t) size > 0) + *offset = pos + size; return size; }