Commit 32cf95db authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-4.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull misc driver fixes from Gfreg KH:
 "Here are three small fixes for some driver problems that were
  reported.  Full details in the shortlog below.

  All of these have been in linux-next with no reported issues"

* tag 'char-misc-4.6-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  nvmem: mxs-ocotp: fix buffer overflow in read
  Drivers: hv: vmbus: Fix signaling logic in hv_need_to_signal_on_read()
  misc: mic: Fix for double fetch security bug in VOP driver
parents 630aac5a d1306eb6
...@@ -103,15 +103,29 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) ...@@ -103,15 +103,29 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
* there is room for the producer to send the pending packet. * there is room for the producer to send the pending packet.
*/ */
static bool hv_need_to_signal_on_read(u32 prev_write_sz, static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
struct hv_ring_buffer_info *rbi)
{ {
u32 cur_write_sz; u32 cur_write_sz;
u32 r_size; u32 r_size;
u32 write_loc = rbi->ring_buffer->write_index; u32 write_loc;
u32 read_loc = rbi->ring_buffer->read_index; u32 read_loc = rbi->ring_buffer->read_index;
u32 pending_sz = rbi->ring_buffer->pending_send_sz; u32 pending_sz;
/*
* Issue a full memory barrier before making the signaling decision.
* Here is the reason for having this barrier:
* If the reading of the pend_sz (in this function)
* were to be reordered and read before we commit the new read
* index (in the calling function) we could
* have a problem. If the host were to set the pending_sz after we
* have sampled pending_sz and go to sleep before we commit the
* read index, we could miss sending the interrupt. Issue a full
* memory barrier to address this.
*/
mb();
pending_sz = rbi->ring_buffer->pending_send_sz;
write_loc = rbi->ring_buffer->write_index;
/* If the other end is not blocked on write don't bother. */ /* If the other end is not blocked on write don't bother. */
if (pending_sz == 0) if (pending_sz == 0)
return false; return false;
...@@ -120,7 +134,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, ...@@ -120,7 +134,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz,
cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) : cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
read_loc - write_loc; read_loc - write_loc;
if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz)) if (cur_write_sz >= pending_sz)
return true; return true;
return false; return false;
...@@ -455,7 +469,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, ...@@ -455,7 +469,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
/* Update the read index */ /* Update the read index */
hv_set_next_read_location(inring_info, next_read_location); hv_set_next_read_location(inring_info, next_read_location);
*signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info); *signal = hv_need_to_signal_on_read(inring_info);
return ret; return ret;
} }
...@@ -945,6 +945,11 @@ static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ...@@ -945,6 +945,11 @@ static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
ret = -EFAULT; ret = -EFAULT;
goto free_ret; goto free_ret;
} }
/* Ensure desc has not changed between the two reads */
if (memcmp(&dd, dd_config, sizeof(dd))) {
ret = -EINVAL;
goto free_ret;
}
mutex_lock(&vdev->vdev_mutex); mutex_lock(&vdev->vdev_mutex);
mutex_lock(&vi->vop_mutex); mutex_lock(&vi->vop_mutex);
ret = vop_virtio_add_device(vdev, dd_config); ret = vop_virtio_add_device(vdev, dd_config);
......
...@@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, ...@@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
if (ret) if (ret)
goto close_banks; goto close_banks;
while (val_size) { while (val_size >= reg_size) {
if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) { if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
/* fill up non-data register */ /* fill up non-data register */
*buf = 0; *buf = 0;
...@@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, ...@@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size,
} }
buf++; buf++;
val_size--; val_size -= reg_size;
offset += reg_size; offset += reg_size;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment