diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-07 13:53:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-07 13:53:32 -0400 |
commit | 32cf95db22d49cf4a3b421ba9fd156bb5f920ebb (patch) | |
tree | 48df4fe0b994c33155c7b19269621f6c122fee60 /drivers | |
parent | 630aac5ab6d6708c2cf715ddb5a77928e0aacb04 (diff) | |
parent | d1306eb675ad7a9a760b6b8e8e189824b8db89e7 (diff) |
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
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hv/ring_buffer.c | 26 | ||||
-rw-r--r-- | drivers/misc/mic/vop/vop_vringh.c | 5 | ||||
-rw-r--r-- | drivers/nvmem/mxs-ocotp.c | 4 |
3 files changed, 27 insertions, 8 deletions
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 5613e2b5cff7..a40a73a7b71d 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c | |||
@@ -103,15 +103,29 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi) | |||
103 | * there is room for the producer to send the pending packet. | 103 | * there is room for the producer to send the pending packet. |
104 | */ | 104 | */ |
105 | 105 | ||
106 | static bool hv_need_to_signal_on_read(u32 prev_write_sz, | 106 | static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi) |
107 | struct hv_ring_buffer_info *rbi) | ||
108 | { | 107 | { |
109 | u32 cur_write_sz; | 108 | u32 cur_write_sz; |
110 | u32 r_size; | 109 | u32 r_size; |
111 | u32 write_loc = rbi->ring_buffer->write_index; | 110 | u32 write_loc; |
112 | u32 read_loc = rbi->ring_buffer->read_index; | 111 | u32 read_loc = rbi->ring_buffer->read_index; |
113 | u32 pending_sz = rbi->ring_buffer->pending_send_sz; | 112 | u32 pending_sz; |
114 | 113 | ||
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; | ||
115 | /* If the other end is not blocked on write don't bother. */ | 129 | /* If the other end is not blocked on write don't bother. */ |
116 | if (pending_sz == 0) | 130 | if (pending_sz == 0) |
117 | return false; | 131 | return false; |
@@ -120,7 +134,7 @@ static bool hv_need_to_signal_on_read(u32 prev_write_sz, | |||
120 | cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) : | 134 | cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) : |
121 | read_loc - write_loc; | 135 | read_loc - write_loc; |
122 | 136 | ||
123 | if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz)) | 137 | if (cur_write_sz >= pending_sz) |
124 | return true; | 138 | return true; |
125 | 139 | ||
126 | return false; | 140 | return false; |
@@ -455,7 +469,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, | |||
455 | /* Update the read index */ | 469 | /* Update the read index */ |
456 | hv_set_next_read_location(inring_info, next_read_location); | 470 | hv_set_next_read_location(inring_info, next_read_location); |
457 | 471 | ||
458 | *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info); | 472 | *signal = hv_need_to_signal_on_read(inring_info); |
459 | 473 | ||
460 | return ret; | 474 | return ret; |
461 | } | 475 | } |
diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c index e94c7fb6712a..88e45234d527 100644 --- a/drivers/misc/mic/vop/vop_vringh.c +++ b/drivers/misc/mic/vop/vop_vringh.c | |||
@@ -945,6 +945,11 @@ static long vop_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
945 | ret = -EFAULT; | 945 | ret = -EFAULT; |
946 | goto free_ret; | 946 | goto free_ret; |
947 | } | 947 | } |
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 | } | ||
948 | mutex_lock(&vdev->vdev_mutex); | 953 | mutex_lock(&vdev->vdev_mutex); |
949 | mutex_lock(&vi->vop_mutex); | 954 | mutex_lock(&vi->vop_mutex); |
950 | ret = vop_virtio_add_device(vdev, dd_config); | 955 | ret = vop_virtio_add_device(vdev, dd_config); |
diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c index 8ba19bba3156..2bb3c5799ac4 100644 --- a/drivers/nvmem/mxs-ocotp.c +++ b/drivers/nvmem/mxs-ocotp.c | |||
@@ -94,7 +94,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, | |||
94 | if (ret) | 94 | if (ret) |
95 | goto close_banks; | 95 | goto close_banks; |
96 | 96 | ||
97 | while (val_size) { | 97 | while (val_size >= reg_size) { |
98 | if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) { | 98 | if ((offset < OCOTP_DATA_OFFSET) || (offset % 16)) { |
99 | /* fill up non-data register */ | 99 | /* fill up non-data register */ |
100 | *buf = 0; | 100 | *buf = 0; |
@@ -103,7 +103,7 @@ static int mxs_ocotp_read(void *context, const void *reg, size_t reg_size, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | buf++; | 105 | buf++; |
106 | val_size--; | 106 | val_size -= reg_size; |
107 | offset += reg_size; | 107 | offset += reg_size; |
108 | } | 108 | } |
109 | 109 | ||