History

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

Linus Torvalds committed 10 years ago

Commit 32cf95d2 parents 630aac5 d1306eb3 files · +27 −8Browse files

Unified · Split

3 files
  1. drivers/hv/ring_buffer.c +20 −6
  2. drivers/misc/mic/vop/vop_vringh.c +5 −0
  3. drivers/nvmem/mxs-ocotp.c +2 −2
drivers/hv/ring_buffer.c+20−6
@@ -103,15 +103,29 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) · 102 unmodified lines
103103 * there is room for the producer to send the pending packet.
104104 */
105105
106−static bool hv_need_to_signal_on_read(u32 prev_write_sz,
107− struct hv_ring_buffer_info *rbi)
106+static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
108107 {
109108 u32 cur_write_sz;
110109 u32 r_size;
111− u32 write_loc = rbi->ring_buffer->write_index;
110+ u32 write_loc;
112111 u32 read_loc = rbi->ring_buffer->read_index;
113− u32 pending_sz = rbi->ring_buffer->pending_send_sz;
112+ u32 pending_sz;
114113
114+ /*
115+ * Issue a full memory barrier before making the signaling decision.
116+ * Here is the reason for having this barrier:
117+ * If the reading of the pend_sz (in this function)
118+ * were to be reordered and read before we commit the new read
119+ * index (in the calling function) we could
120+ * have a problem. If the host were to set the pending_sz after we
121+ * have sampled pending_sz and go to sleep before we commit the
122+ * read index, we could miss sending the interrupt. Issue a full
123+ * memory barrier to address this.
124+ */
125+ mb();
126+
127+ pending_sz = rbi->ring_buffer->pending_send_sz;
128+ write_loc = rbi->ring_buffer->write_index;
115129 /* If the other end is not blocked on write don't bother. */
116130 if (pending_sz == 0)
117131 return false;
@@ -120,7 +134,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, · 2 unmodified lines
120134 cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
121135 read_loc - write_loc;
122136
123− if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz))
137+ if (cur_write_sz >= pending_sz)
124138 return true;
125139
126140 return false;
@@ -455,7 +469,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, · 328 unmodified lines
455469 /* Update the read index */
456470 hv_set_next_read_location(inring_info, next_read_location);
457471
458− *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info);
472+ *signal = hv_need_to_signal_on_read(inring_info);
459473
460474 return ret;
461475 }
drivers/misc/mic/vop/vop_vringh.c+5−0
@@ -945,6 +945,11 @@ static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg) · 944 unmodified lines
945945 ret = -EFAULT;
946946 goto free_ret;
947947 }
948+ /* Ensure desc has not changed between the two reads */
949+ if (memcmp(&dd, dd_config, sizeof(dd))) {
950+ ret = -EINVAL;
951+ goto free_ret;
952+ }
948953 mutex_lock(&vdev->vdev_mutex);
949954 mutex_lock(&vi->vop_mutex);
950955 ret = vop_virtio_add_device(vdev, dd_config);
drivers/nvmem/mxs-ocotp.c+2−2
@@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, · 93 unmodified lines
9494 if (ret)
9595 goto close_banks;
9696
97− while (val_size) {
97+ while (val_size >= reg_size) {
9898 if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) {
9999 /* fill up non-data register */
100100 *buf = 0;
@@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, · 2 unmodified lines
103103 }
104104
105105 buf++;
106− val_size--;
106+ val_size -= reg_size;
107107 offset += reg_size;
108108 }
109109