Ladi Prosek
2017-Mar-28 16:46 UTC
[PATCH v3 0/3] virtio_balloon: don't push uninitialized buffers to stats virtqueue
This series fixes issues with variable initialization in the virtio balloon driver which manifest as the driver sending invalid memory stats to the host. v1->v2: * Call update_balloon_stats instead of filling the buffer with invalid tags. * Add BUG_ON to update_balloon_stats to formalize the invariant that all slots in the buffer must be initialized. v2->v3: * Remove BUG_ON and return the actual number of counters from update_balloon_stats instead. * Added Arnd's patch to omit VM stats if CONFIG_VM_EVENT_COUNTERS is not defined. Arnd Bergmann (1): virtio_balloon: prevent uninitialized variable use Ladi Prosek (2): virtio_balloon: don't push uninitialized buffers to stats virtqueue virtio-balloon: use actual number of stats for stats queue buffers drivers/virtio/virtio_balloon.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) Thanks! Ladi
Ladi Prosek
2017-Mar-28 16:46 UTC
[PATCH v3 1/3] virtio_balloon: don't push uninitialized buffers to stats virtqueue
When init_vqs runs, virtio_balloon.stats is either uninitialized or contains stale values. The host updates its state with garbage data because it has no way of knowing that this is just a marker buffer used for signaling. This patch updates the stats before pushing the initial buffer. Signed-off-by: Ladi Prosek <lprosek at redhat.com> --- drivers/virtio/virtio_balloon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 4e11915..fcd06e1 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -429,6 +429,8 @@ static int init_vqs(struct virtio_balloon *vb) * Prime this virtqueue with one buffer so the hypervisor can * use it to signal us later (it can't be broken yet!). */ + update_balloon_stats(vb); + sg_init_one(&sg, vb->stats, sizeof vb->stats); if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) < 0) -- 2.9.3
Ladi Prosek
2017-Mar-28 16:46 UTC
[PATCH v3 2/3] virtio-balloon: use actual number of stats for stats queue buffers
The virtio balloon driver contained a not-so-obvious invariant that update_balloon_stats has to update exactly VIRTIO_BALLOON_S_NR counters in order to send valid stats to the host. This commit fixes it by having update_balloon_stats return the actual number of counters, and its callers use it when pushing buffers to the stats virtqueue. Note that it is still out of spec to change the number of counters at run-time. "Driver MUST supply the same subset of statistics in all buffers submitted to the statsq." Suggested-by: Arnd Bergmann <arnd at arndb.de> Signed-off-by: Ladi Prosek <lprosek at redhat.com> --- drivers/virtio/virtio_balloon.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index fcd06e1..d9544db 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -242,11 +242,11 @@ static inline void update_stat(struct virtio_balloon *vb, int idx, #define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT) -static void update_balloon_stats(struct virtio_balloon *vb) +static unsigned int update_balloon_stats(struct virtio_balloon *vb) { unsigned long events[NR_VM_EVENT_ITEMS]; struct sysinfo i; - int idx = 0; + unsigned int idx = 0; long available; all_vm_events(events); @@ -266,6 +266,8 @@ static void update_balloon_stats(struct virtio_balloon *vb) pages_to_bytes(i.totalram)); update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL, pages_to_bytes(available)); + + return idx; } /* @@ -291,14 +293,14 @@ static void stats_handle_request(struct virtio_balloon *vb) { struct virtqueue *vq; struct scatterlist sg; - unsigned int len; + unsigned int len, num_stats; - update_balloon_stats(vb); + num_stats = update_balloon_stats(vb); vq = vb->stats_vq; if (!virtqueue_get_buf(vq, &len)) return; - sg_init_one(&sg, vb->stats, sizeof(vb->stats)); + sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL); virtqueue_kick(vq); } @@ -423,15 +425,16 @@ static int init_vqs(struct virtio_balloon *vb) vb->deflate_vq = vqs[1]; if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) { struct scatterlist sg; + unsigned int num_stats; vb->stats_vq = vqs[2]; /* * Prime this virtqueue with one buffer so the hypervisor can * use it to signal us later (it can't be broken yet!). */ - update_balloon_stats(vb); + num_stats = update_balloon_stats(vb); - sg_init_one(&sg, vb->stats, sizeof vb->stats); + sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats); if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL) < 0) BUG(); -- 2.9.3
Ladi Prosek
2017-Mar-28 16:46 UTC
[PATCH v3 3/3] virtio_balloon: prevent uninitialized variable use
From: Arnd Bergmann <arnd at arndb.de> The latest gcc-7.0.1 snapshot reports a new warning: virtio/virtio_balloon.c: In function 'update_balloon_stats': virtio/virtio_balloon.c:258:26: error: 'events[2]' is used uninitialized in this function [-Werror=uninitialized] virtio/virtio_balloon.c:260:26: error: 'events[3]' is used uninitialized in this function [-Werror=uninitialized] virtio/virtio_balloon.c:261:56: error: 'events[18]' is used uninitialized in this function [-Werror=uninitialized] virtio/virtio_balloon.c:262:56: error: 'events[17]' is used uninitialized in this function [-Werror=uninitialized] This seems absolutely right, so we should add an extra check to prevent copying uninitialized stack data into the statistics.>From all I can tell, this has been broken since the statistics codewas originally added in 2.6.34. Fixes: 9564e138b1f6 ("virtio: Add memory statistics reporting to the balloon driver (V4)") Signed-off-by: Arnd Bergmann <arnd at arndb.de> Signed-off-by: Ladi Prosek <lprosek at redhat.com> --- drivers/virtio/virtio_balloon.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index d9544db..34adf9b 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -254,12 +254,14 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb) available = si_mem_available(); +#ifdef CONFIG_VM_EVENT_COUNTERS update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, pages_to_bytes(events[PSWPIN])); update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_OUT, pages_to_bytes(events[PSWPOUT])); update_stat(vb, idx++, VIRTIO_BALLOON_S_MAJFLT, events[PGMAJFAULT]); update_stat(vb, idx++, VIRTIO_BALLOON_S_MINFLT, events[PGFAULT]); +#endif update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMFREE, pages_to_bytes(i.freeram)); update_stat(vb, idx++, VIRTIO_BALLOON_S_MEMTOT, -- 2.9.3
Arnd Bergmann
2017-Mar-28 20:33 UTC
[PATCH v3 2/3] virtio-balloon: use actual number of stats for stats queue buffers
On Tue, Mar 28, 2017 at 6:46 PM, Ladi Prosek <lprosek at redhat.com> wrote:> The virtio balloon driver contained a not-so-obvious invariant that > update_balloon_stats has to update exactly VIRTIO_BALLOON_S_NR counters > in order to send valid stats to the host. This commit fixes it by having > update_balloon_stats return the actual number of counters, and its > callers use it when pushing buffers to the stats virtqueue. > > Note that it is still out of spec to change the number of counters > at run-time. "Driver MUST supply the same subset of statistics in all > buffers submitted to the statsq." > > Suggested-by: Arnd Bergmann <arnd at arndb.de> > Signed-off-by: Ladi Prosek <lprosek at redhat.com>>Acked-by: Arnd Bergmann <arnd at arndb.de>
Apparently Analagous Threads
- [PATCH v3 0/3] virtio_balloon: don't push uninitialized buffers to stats virtqueue
- [PATCH] virtio_balloon: prevent uninitialized variable use
- [PATCH] virtio_balloon: prevent uninitialized variable use
- [PATCH] virtio_balloon: prevent uninitialized variable use
- [PATCH] virtio_balloon: prevent uninitialized variable use