summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-17 11:49:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-17 11:49:00 -0700
commitd44ade05aa21468bd30652bc4492891b854a400a (patch)
treee146ae0c13621fc867f739bc84f98f8ce0875915 /drivers/char
parent3dc0df03396a3329c644b29b421892a32ecb9387 (diff)
parent8cb2c9285e4ce9154f45fb15633ebd45dfd8d9cf (diff)
downloadlwn-d44ade05aa21468bd30652bc4492891b854a400a.tar.gz
lwn-d44ade05aa21468bd30652bc4492891b854a400a.zip
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio updates from Michael Tsirkin: - new virtio CAN driver - support for LoongArch architecture in fw_cfg - support for firmware notifications in vdpa/octeon_ep - support for VFs in virtio core - fixes, cleanups all over the place, notably: - vhost: fix vhost_get_avail_idx for a non empty ring fixing an significant old perf regression - READ_ONCE() annotations mean virtio ring is now free of KCSAN warnings * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (37 commits) can: virtio: Fix comment in UAPI header can: virtio: Add virtio CAN driver virtio: add num_vf callback to virtio_bus fw_cfg: Add support for LoongArch architecture vdpa/octeon_ep: fix IRQ-to-ring mapping in interrupt handler vdpa/octeon_ep: Add vDPA device event handling for firmware notifications vdpa/octeon_ep: Use 4 bytes for mailbox signature vdpa/octeon_ep: Fix PF->VF mailbox data address calculation vhost_task_create: kill unnecessary .exit_signal initialization vhost: remove unnecessary module_init/exit functions vdpa/mlx5: Use kvzalloc_flex() for MTT command memory vdpa_sim_net: switch to dynamic root device vdpa_sim_blk: switch to dynamic root device virtio-mem: Destroy mutex before freeing virtio_mem virtio-balloon: Destroy mutex before freeing virtio_balloon tools/virtio: fix build for kmalloc_obj API and missing stubs virtio_ring: Add READ_ONCE annotations for device-writable fields vduse: fix compat handling for VDUSE_IOTLB_GET_FD/VDUSE_VQ_GET_INFO tools/virtio: check mmap return value in vringh_test vhost/net: complete zerocopy ubufs only once ...
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/virtio-rng.c23
-rw-r--r--drivers/char/virtio_console.c52
2 files changed, 52 insertions, 23 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 0ce02d7e5048..5e83ffa105e4 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -7,6 +7,7 @@
#include <asm/barrier.h>
#include <linux/err.h>
#include <linux/hw_random.h>
+#include <linux/nospec.h>
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/virtio.h>
@@ -69,8 +70,26 @@ static void request_entropy(struct virtrng_info *vi)
static unsigned int copy_data(struct virtrng_info *vi, void *buf,
unsigned int size)
{
- size = min_t(unsigned int, size, vi->data_avail);
- memcpy(buf, vi->data + vi->data_idx, size);
+ unsigned int idx, avail;
+
+ /*
+ * vi->data_avail was set from the device-reported used.len and
+ * vi->data_idx was advanced by previous copy_data() calls. A
+ * malicious or buggy virtio-rng backend can drive either past
+ * sizeof(vi->data). Clamp at point of use and harden the index
+ * with array_index_nospec() so the memcpy() below cannot be
+ * steered into adjacent slab memory, including under
+ * speculation.
+ */
+ avail = min_t(unsigned int, vi->data_avail, sizeof(vi->data));
+ if (vi->data_idx >= avail) {
+ vi->data_avail = 0;
+ request_entropy(vi);
+ return 0;
+ }
+ size = min_t(unsigned int, size, avail - vi->data_idx);
+ idx = array_index_nospec(vi->data_idx, sizeof(vi->data));
+ memcpy(buf, vi->data + idx, size);
vi->data_idx += size;
vi->data_avail -= size;
if (vi->data_avail == 0)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 9a33217c68d9..198b97314168 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1771,32 +1771,40 @@ static void config_intr(struct virtio_device *vdev)
schedule_work(&portdev->config_work);
}
-static void config_work_handler(struct work_struct *work)
+static void update_size_from_config(struct ports_device *portdev)
{
- struct ports_device *portdev;
+ struct virtio_device *vdev;
+ struct port *port;
+ u16 rows, cols;
- portdev = container_of(work, struct ports_device, config_work);
- if (!use_multiport(portdev)) {
- struct virtio_device *vdev;
- struct port *port;
- u16 rows, cols;
+ vdev = portdev->vdev;
- vdev = portdev->vdev;
- virtio_cread(vdev, struct virtio_console_config, cols, &cols);
- virtio_cread(vdev, struct virtio_console_config, rows, &rows);
+ /*
+ * We'll use this way of resizing only for legacy support.
+ * For multiport devices, use control messages to indicate
+ * console size changes so that it can be done per-port.
+ *
+ * Don't test F_SIZE at all if we're rproc: not a valid feature.
+ */
+ if (is_rproc_serial(vdev) ||
+ use_multiport(portdev) ||
+ !virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE))
+ return;
- port = find_port_by_id(portdev, 0);
- set_console_size(port, rows, cols);
+ virtio_cread(vdev, struct virtio_console_config, cols, &cols);
+ virtio_cread(vdev, struct virtio_console_config, rows, &rows);
- /*
- * We'll use this way of resizing only for legacy
- * support. For newer userspace
- * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages
- * to indicate console size changes so that it can be
- * done per-port.
- */
- resize_console(port);
- }
+ port = find_port_by_id(portdev, 0);
+ set_console_size(port, rows, cols);
+ resize_console(port);
+}
+
+static void config_work_handler(struct work_struct *work)
+{
+ struct ports_device *portdev;
+
+ portdev = container_of(work, struct ports_device, config_work);
+ update_size_from_config(portdev);
}
static int init_vqs(struct ports_device *portdev)
@@ -2052,6 +2060,8 @@ static int virtcons_probe(struct virtio_device *vdev)
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 1);
+ update_size_from_config(portdev);
+
return 0;
free_chrdev: