diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 21:20:54 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 21:20:54 +0400 |
commit | d8cacd3a259bf522ea5e6c4c60eba67ba22f599c (patch) | |
tree | 24af775fc95240a5be8fdc7bbdb4c25d44ed644c /drivers | |
parent | d75671e36e14b73d7c0d3cec49328dcd984af699 (diff) | |
parent | 9e266ece2178784a1027e04a56c8547dc51b15ce (diff) | |
download | linux-d8cacd3a259bf522ea5e6c4c60eba67ba22f599c.tar.xz |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio update from Rusty Russell:
"More console fixes; these are the theoretical ones which didn't get
CC:stable. But for that reason, I did a merge with master partway
through to avoid an unnecessary conflict.
Also: a fun lguest bug turns out if you don't clear the TF flag when
trapping Bad Things happen to the guest kernel as the stack
overflows..."
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio_pci: pm: Use CONFIG_PM_SLEEP instead of CONFIG_PM
lguest: fix GPF in guest when using gdb.
lguest: fix guest kernel stack overflow when TF bit set.
lguest: fix BUG_ON() in invalid guest page table.
virtio: console: prevent use-after-free of port name in port unplug
virtio: console: cleanup an error message
virtio: console: fix locking around send_sigio_to_port()
virtio: console: add locking in port unplug path
virtio: console: add locks around buffer removal in port unplug path
tools/lguest: offer VIRTIO_F_ANY_LAYOUT for net device.
virtio tools: add .gitignore
lguest: Point to the right directory for the lguest launcher
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/virtio_console.c | 27 | ||||
-rw-r--r-- | drivers/lguest/interrupts_and_traps.c | 10 | ||||
-rw-r--r-- | drivers/lguest/page_tables.c | 4 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 4 |
4 files changed, 31 insertions, 14 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index fc45567ad3ac..b79cf3e1b793 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1529,18 +1529,22 @@ static void remove_port_data(struct port *port) { struct port_buffer *buf; + spin_lock_irq(&port->inbuf_lock); /* Remove unused data this port might have received. */ discard_port_data(port); - reclaim_consumed_buffers(port); - /* Remove buffers we queued up for the Host to send us data in. */ while ((buf = virtqueue_detach_unused_buf(port->in_vq))) free_buf(buf, true); + spin_unlock_irq(&port->inbuf_lock); + + spin_lock_irq(&port->outvq_lock); + reclaim_consumed_buffers(port); /* Free pending buffers from the out-queue. */ while ((buf = virtqueue_detach_unused_buf(port->out_vq))) free_buf(buf, true); + spin_unlock_irq(&port->outvq_lock); } /* @@ -1554,6 +1558,7 @@ static void unplug_port(struct port *port) list_del(&port->list); spin_unlock_irq(&port->portdev->ports_lock); + spin_lock_irq(&port->inbuf_lock); if (port->guest_connected) { /* Let the app know the port is going down. */ send_sigio_to_port(port); @@ -1564,6 +1569,7 @@ static void unplug_port(struct port *port) wake_up_interruptible(&port->waitqueue); } + spin_unlock_irq(&port->inbuf_lock); if (is_console_port(port)) { spin_lock_irq(&pdrvdata_lock); @@ -1585,9 +1591,8 @@ static void unplug_port(struct port *port) device_destroy(pdrvdata.class, port->dev->devt); cdev_del(port->cdev); - kfree(port->name); - debugfs_remove(port->debugfs_file); + kfree(port->name); /* * Locks around here are not necessary - a port can't be @@ -1681,7 +1686,9 @@ static void handle_control_message(struct ports_device *portdev, * If the guest is connected, it'll be interested in * knowing the host connection state changed. */ + spin_lock_irq(&port->inbuf_lock); send_sigio_to_port(port); + spin_unlock_irq(&port->inbuf_lock); break; case VIRTIO_CONSOLE_PORT_NAME: /* @@ -1801,13 +1808,13 @@ static void in_intr(struct virtqueue *vq) if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev)) discard_port_data(port); + /* Send a SIGIO indicating new data in case the process asked for it */ + send_sigio_to_port(port); + spin_unlock_irqrestore(&port->inbuf_lock, flags); wake_up_interruptible(&port->waitqueue); - /* Send a SIGIO indicating new data in case the process asked for it */ - send_sigio_to_port(port); - if (is_console_port(port) && hvc_poll(port->cons.hvc)) hvc_kick(); } @@ -2241,10 +2248,8 @@ static int __init init(void) } pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); - if (!pdrvdata.debugfs_dir) { - pr_warning("Error %ld creating debugfs dir for virtio-ports\n", - PTR_ERR(pdrvdata.debugfs_dir)); - } + if (!pdrvdata.debugfs_dir) + pr_warning("Error creating debugfs dir for virtio-ports\n"); INIT_LIST_HEAD(&pdrvdata.consoles); INIT_LIST_HEAD(&pdrvdata.portdevs); diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 28433a155d67..70dfcdc29f1f 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -140,6 +140,16 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, cpu->regs->eip = idt_address(lo, hi); /* + * Trapping always clears these flags: + * TF: Trap flag + * VM: Virtual 8086 mode + * RF: Resume + * NT: Nested task. + */ + cpu->regs->eflags &= + ~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT); + + /* * There are two kinds of interrupt handlers: 0xE is an "interrupt * gate" which expects interrupts to be disabled on entry. */ diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index a35d8d100165..bfb39bb56ef1 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c @@ -669,8 +669,10 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) #ifdef CONFIG_X86_PAE gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t); - if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) + if (!(pmd_flags(gpmd) & _PAGE_PRESENT)) { kill_guest(cpu, "Bad address %#lx", vaddr); + return -1UL; + } gpte = lgread(cpu, gpte_addr(cpu, gpmd, vaddr), pte_t); #else gpte = lgread(cpu, gpte_addr(cpu, gpgd, vaddr), pte_t); diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 1aba255b5879..98917fc872a4 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -766,7 +766,7 @@ static void virtio_pci_remove(struct pci_dev *pci_dev) kfree(vp_dev); } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int virtio_pci_freeze(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -824,7 +824,7 @@ static struct pci_driver virtio_pci_driver = { .id_table = virtio_pci_id_table, .probe = virtio_pci_probe, .remove = virtio_pci_remove, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP .driver.pm = &virtio_pci_pm_ops, #endif }; |