Commit 7e66208d authored by Dexuan Cui's avatar Dexuan Cui Committed by Greg Kroah-Hartman

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

commit ba50bf1c upstream.

fc96df16 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: fc96df16 ("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: 's avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: 's avatarDexuan Cui <decui@microsoft.com>
Signed-off-by: 's avatarSasha Levin <sashal@kernel.org>
Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cdc5dc5b
......@@ -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);
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;
}
if (!ring_info->ring_buffer)
return -EINVAL;
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);
......
......@@ -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);
......
......@@ -1176,8 +1176,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) \
......
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