Drivers: hv: vmbus: Check for ring when getting debug info

fc96df16a1 is good and can already fix the "return stack garbage" issue,
but let's also improve hv_ringbuffer_get_debuginfo(), which would silently
return stack garbage, if people forget to check channel->state or
ring_info->ring_buffer, when using the function in the future.

Having an error check in the function would eliminate the potential risk.

Add a Fixes tag to indicate the patch depdendency.

Fixes: fc96df16a1 ("Drivers: hv: vmbus: Return -EINVAL for the sys files for unopened channels")
Cc: stable@vger.kernel.org
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Dexuan Cui 2018-12-17 20:16:09 +00:00 committed by Sasha Levin
parent bfeffd1552
commit ba50bf1ce9
3 changed files with 78 additions and 47 deletions

View File

@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
}
/* Get various debug metrics for the specified ring buffer. */
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info)
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info)
{
u32 bytes_avail_towrite;
u32 bytes_avail_toread;
if (ring_info->ring_buffer) {
hv_get_ringbuffer_availbytes(ring_info,
&bytes_avail_toread,
&bytes_avail_towrite);
if (!ring_info->ring_buffer)
return -EINVAL;
debug_info->bytes_avail_toread = bytes_avail_toread;
debug_info->bytes_avail_towrite = bytes_avail_towrite;
debug_info->current_read_index =
ring_info->ring_buffer->read_index;
debug_info->current_write_index =
ring_info->ring_buffer->write_index;
debug_info->current_interrupt_mask =
ring_info->ring_buffer->interrupt_mask;
}
hv_get_ringbuffer_availbytes(ring_info,
&bytes_avail_toread,
&bytes_avail_towrite);
debug_info->bytes_avail_toread = bytes_avail_toread;
debug_info->bytes_avail_towrite = bytes_avail_towrite;
debug_info->current_read_index = ring_info->ring_buffer->read_index;
debug_info->current_write_index = ring_info->ring_buffer->write_index;
debug_info->current_interrupt_mask
= ring_info->ring_buffer->interrupt_mask;
return 0;
}
EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);

View File

@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
&outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(out_intr_mask);
@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
&outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_read_index);
}
static DEVICE_ATTR_RO(out_read_index);
@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
&outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.current_write_index);
}
static DEVICE_ATTR_RO(out_write_index);
@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
&outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(out_read_bytes_avail);
@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info outbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
&outbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(out_write_bytes_avail);
@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
}
static DEVICE_ATTR_RO(in_intr_mask);
@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_read_index);
}
static DEVICE_ATTR_RO(in_read_index);
@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.current_write_index);
}
static DEVICE_ATTR_RO(in_write_index);
@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
}
static DEVICE_ATTR_RO(in_read_bytes_avail);
@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
{
struct hv_device *hv_dev = device_to_hv_device(dev);
struct hv_ring_buffer_debug_info inbound;
int ret;
if (!hv_dev->channel)
return -ENODEV;
if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
return -EINVAL;
hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
}
static DEVICE_ATTR_RO(in_write_bytes_avail);

View File

@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
u32 bytes_avail_towrite;
};
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
struct hv_ring_buffer_debug_info *debug_info);
/* Vmbus interface */
#define vmbus_driver_register(driver) \