diff options
| -rw-r--r-- | Documentation/lguest/lguest.c | 73 | ||||
| -rw-r--r-- | Documentation/lguest/lguest.txt | 5 | ||||
| -rw-r--r-- | arch/x86/lguest/Kconfig | 1 | ||||
| -rw-r--r-- | arch/x86/lguest/boot.c | 2 | ||||
| -rw-r--r-- | drivers/lguest/page_tables.c | 2 | ||||
| -rw-r--r-- | drivers/lguest/x86/core.c | 4 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 20 |
7 files changed, 77 insertions, 30 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index dc73bc54cc4..d9da7e14853 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
| @@ -39,6 +39,9 @@ | |||
| 39 | #include <limits.h> | 39 | #include <limits.h> |
| 40 | #include <stddef.h> | 40 | #include <stddef.h> |
| 41 | #include <signal.h> | 41 | #include <signal.h> |
| 42 | #include <pwd.h> | ||
| 43 | #include <grp.h> | ||
| 44 | |||
| 42 | #include <linux/virtio_config.h> | 45 | #include <linux/virtio_config.h> |
| 43 | #include <linux/virtio_net.h> | 46 | #include <linux/virtio_net.h> |
| 44 | #include <linux/virtio_blk.h> | 47 | #include <linux/virtio_blk.h> |
| @@ -298,20 +301,27 @@ static void *map_zeroed_pages(unsigned int num) | |||
| 298 | 301 | ||
| 299 | /* | 302 | /* |
| 300 | * We use a private mapping (ie. if we write to the page, it will be | 303 | * We use a private mapping (ie. if we write to the page, it will be |
| 301 | * copied). | 304 | * copied). We allocate an extra two pages PROT_NONE to act as guard |
| 305 | * pages against read/write attempts that exceed allocated space. | ||
| 302 | */ | 306 | */ |
| 303 | addr = mmap(NULL, getpagesize() * num, | 307 | addr = mmap(NULL, getpagesize() * (num+2), |
| 304 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0); | 308 | PROT_NONE, MAP_PRIVATE, fd, 0); |
| 309 | |||
| 305 | if (addr == MAP_FAILED) | 310 | if (addr == MAP_FAILED) |
| 306 | err(1, "Mmapping %u pages of /dev/zero", num); | 311 | err(1, "Mmapping %u pages of /dev/zero", num); |
| 307 | 312 | ||
| 313 | if (mprotect(addr + getpagesize(), getpagesize() * num, | ||
| 314 | PROT_READ|PROT_WRITE) == -1) | ||
| 315 | err(1, "mprotect rw %u pages failed", num); | ||
| 316 | |||
| 308 | /* | 317 | /* |
| 309 | * One neat mmap feature is that you can close the fd, and it | 318 | * One neat mmap feature is that you can close the fd, and it |
| 310 | * stays mapped. | 319 | * stays mapped. |
| 311 | */ | 320 | */ |
| 312 | close(fd); | 321 | close(fd); |
| 313 | 322 | ||
| 314 | return addr; | 323 | /* Return address after PROT_NONE page */ |
| 324 | return addr + getpagesize(); | ||
| 315 | } | 325 | } |
| 316 | 326 | ||
| 317 | /* Get some more pages for a device. */ | 327 | /* Get some more pages for a device. */ |
| @@ -343,7 +353,7 @@ static void map_at(int fd, void *addr, unsigned long offset, unsigned long len) | |||
| 343 | * done to it. This allows us to share untouched memory between | 353 | * done to it. This allows us to share untouched memory between |
| 344 | * Guests. | 354 | * Guests. |
| 345 | */ | 355 | */ |
| 346 | if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC, | 356 | if (mmap(addr, len, PROT_READ|PROT_WRITE, |
| 347 | MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED) | 357 | MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED) |
| 348 | return; | 358 | return; |
| 349 | 359 | ||
| @@ -573,10 +583,10 @@ static void *_check_pointer(unsigned long addr, unsigned int size, | |||
| 573 | unsigned int line) | 583 | unsigned int line) |
| 574 | { | 584 | { |
| 575 | /* | 585 | /* |
| 576 | * We have to separately check addr and addr+size, because size could | 586 | * Check if the requested address and size exceeds the allocated memory, |
| 577 | * be huge and addr + size might wrap around. | 587 | * or addr + size wraps around. |
| 578 | */ | 588 | */ |
| 579 | if (addr >= guest_limit || addr + size >= guest_limit) | 589 | if ((addr + size) > guest_limit || (addr + size) < addr) |
| 580 | errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr); | 590 | errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr); |
| 581 | /* | 591 | /* |
| 582 | * We return a pointer for the caller's convenience, now we know it's | 592 | * We return a pointer for the caller's convenience, now we know it's |
| @@ -1872,6 +1882,8 @@ static struct option opts[] = { | |||
| 1872 | { "block", 1, NULL, 'b' }, | 1882 | { "block", 1, NULL, 'b' }, |
| 1873 | { "rng", 0, NULL, 'r' }, | 1883 | { "rng", 0, NULL, 'r' }, |
| 1874 | { "initrd", 1, NULL, 'i' }, | 1884 | { "initrd", 1, NULL, 'i' }, |
| 1885 | { "username", 1, NULL, 'u' }, | ||
| 1886 | { "chroot", 1, NULL, 'c' }, | ||
| 1875 | { NULL }, | 1887 | { NULL }, |
| 1876 | }; | 1888 | }; |
| 1877 | static void usage(void) | 1889 | static void usage(void) |
| @@ -1894,6 +1906,12 @@ int main(int argc, char *argv[]) | |||
| 1894 | /* If they specify an initrd file to load. */ | 1906 | /* If they specify an initrd file to load. */ |
| 1895 | const char *initrd_name = NULL; | 1907 | const char *initrd_name = NULL; |
| 1896 | 1908 | ||
| 1909 | /* Password structure for initgroups/setres[gu]id */ | ||
| 1910 | struct passwd *user_details = NULL; | ||
| 1911 | |||
| 1912 | /* Directory to chroot to */ | ||
| 1913 | char *chroot_path = NULL; | ||
| 1914 | |||
| 1897 | /* Save the args: we "reboot" by execing ourselves again. */ | 1915 | /* Save the args: we "reboot" by execing ourselves again. */ |
| 1898 | main_args = argv; | 1916 | main_args = argv; |
| 1899 | 1917 | ||
| @@ -1950,6 +1968,14 @@ int main(int argc, char *argv[]) | |||
| 1950 | case 'i': | 1968 | case 'i': |
| 1951 | initrd_name = optarg; | 1969 | initrd_name = optarg; |
| 1952 | break; | 1970 | break; |
| 1971 | case 'u': | ||
| 1972 | user_details = getpwnam(optarg); | ||
| 1973 | if (!user_details) | ||
| 1974 | err(1, "getpwnam failed, incorrect username?"); | ||
| 1975 | break; | ||
| 1976 | case 'c': | ||
| 1977 | chroot_path = optarg; | ||
| 1978 | break; | ||
| 1953 | default: | 1979 | default: |
| 1954 | warnx("Unknown argument %s", argv[optind]); | 1980 | warnx("Unknown argument %s", argv[optind]); |
| 1955 | usage(); | 1981 | usage(); |
| @@ -2021,6 +2047,37 @@ int main(int argc, char *argv[]) | |||
| 2021 | /* If we exit via err(), this kills all the threads, restores tty. */ | 2047 | /* If we exit via err(), this kills all the threads, restores tty. */ |
| 2022 | atexit(cleanup_devices); | 2048 | atexit(cleanup_devices); |
| 2023 | 2049 | ||
| 2050 | /* If requested, chroot to a directory */ | ||
| 2051 | if (chroot_path) { | ||
| 2052 | if (chroot(chroot_path) != 0) | ||
| 2053 | err(1, "chroot(\"%s\") failed", chroot_path); | ||
| 2054 | |||
| 2055 | if (chdir("/") != 0) | ||
| 2056 | err(1, "chdir(\"/\") failed"); | ||
| 2057 | |||
| 2058 | verbose("chroot done\n"); | ||
| 2059 | } | ||
| 2060 | |||
| 2061 | /* If requested, drop privileges */ | ||
| 2062 | if (user_details) { | ||
| 2063 | uid_t u; | ||
| 2064 | gid_t g; | ||
| 2065 | |||
| 2066 | u = user_details->pw_uid; | ||
| 2067 | g = user_details->pw_gid; | ||
| 2068 | |||
| 2069 | if (initgroups(user_details->pw_name, g) != 0) | ||
| 2070 | err(1, "initgroups failed"); | ||
| 2071 | |||
| 2072 | if (setresgid(g, g, g) != 0) | ||
| 2073 | err(1, "setresgid failed"); | ||
| 2074 | |||
| 2075 | if (setresuid(u, u, u) != 0) | ||
| 2076 | err(1, "setresuid failed"); | ||
| 2077 | |||
| 2078 | verbose("Dropping privileges completed\n"); | ||
| 2079 | } | ||
| 2080 | |||
| 2024 | /* Finally, run the Guest. This doesn't return. */ | 2081 | /* Finally, run the Guest. This doesn't return. */ |
| 2025 | run_guest(); | 2082 | run_guest(); |
| 2026 | } | 2083 | } |
diff --git a/Documentation/lguest/lguest.txt b/Documentation/lguest/lguest.txt index 6ccaf8e1a00..dad99978a6a 100644 --- a/Documentation/lguest/lguest.txt +++ b/Documentation/lguest/lguest.txt | |||
| @@ -117,6 +117,11 @@ Running Lguest: | |||
| 117 | 117 | ||
| 118 | for general information on how to get bridging to work. | 118 | for general information on how to get bridging to work. |
| 119 | 119 | ||
| 120 | - Random number generation. Using the --rng option will provide a | ||
| 121 | /dev/hwrng in the guest that will read from the host's /dev/random. | ||
| 122 | Use this option in conjunction with rng-tools (see ../hw_random.txt) | ||
| 123 | to provide entropy to the guest kernel's /dev/random. | ||
| 124 | |||
| 120 | There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest | 125 | There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest |
| 121 | 126 | ||
| 122 | Good luck! | 127 | Good luck! |
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig index 38718041efc..6e121a2a49e 100644 --- a/arch/x86/lguest/Kconfig +++ b/arch/x86/lguest/Kconfig | |||
| @@ -2,6 +2,7 @@ config LGUEST_GUEST | |||
| 2 | bool "Lguest guest support" | 2 | bool "Lguest guest support" |
| 3 | select PARAVIRT | 3 | select PARAVIRT |
| 4 | depends on X86_32 | 4 | depends on X86_32 |
| 5 | select VIRTUALIZATION | ||
| 5 | select VIRTIO | 6 | select VIRTIO |
| 6 | select VIRTIO_RING | 7 | select VIRTIO_RING |
| 7 | select VIRTIO_CONSOLE | 8 | select VIRTIO_CONSOLE |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 4996cf5f73a..eba687f0cc0 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
| @@ -824,7 +824,7 @@ static void __init lguest_init_IRQ(void) | |||
| 824 | 824 | ||
| 825 | for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) { | 825 | for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) { |
| 826 | /* Some systems map "vectors" to interrupts weirdly. Not us! */ | 826 | /* Some systems map "vectors" to interrupts weirdly. Not us! */ |
| 827 | __get_cpu_var(vector_irq)[i] = i - FIRST_EXTERNAL_VECTOR; | 827 | __this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR); |
| 828 | if (i != SYSCALL_VECTOR) | 828 | if (i != SYSCALL_VECTOR) |
| 829 | set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); | 829 | set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); |
| 830 | } | 830 | } |
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 04b22128a47..d21578ee95d 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
| @@ -1137,7 +1137,7 @@ void free_guest_pagetable(struct lguest *lg) | |||
| 1137 | */ | 1137 | */ |
| 1138 | void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) | 1138 | void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) |
| 1139 | { | 1139 | { |
| 1140 | pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); | 1140 | pte_t *switcher_pte_page = __this_cpu_read(switcher_pte_pages); |
| 1141 | pte_t regs_pte; | 1141 | pte_t regs_pte; |
| 1142 | 1142 | ||
| 1143 | #ifdef CONFIG_X86_PAE | 1143 | #ifdef CONFIG_X86_PAE |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index b4eb675a807..9f1659c3d1f 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
| @@ -90,8 +90,8 @@ static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
| 90 | * meanwhile). If that's not the case, we pretend everything in the | 90 | * meanwhile). If that's not the case, we pretend everything in the |
| 91 | * Guest has changed. | 91 | * Guest has changed. |
| 92 | */ | 92 | */ |
| 93 | if (__get_cpu_var(lg_last_cpu) != cpu || cpu->last_pages != pages) { | 93 | if (__this_cpu_read(lg_last_cpu) != cpu || cpu->last_pages != pages) { |
| 94 | __get_cpu_var(lg_last_cpu) = cpu; | 94 | __this_cpu_write(lg_last_cpu, cpu); |
| 95 | cpu->last_pages = pages; | 95 | cpu->last_pages = pages; |
| 96 | cpu->changed = CHANGED_ALL; | 96 | cpu->changed = CHANGED_ALL; |
| 97 | } | 97 | } |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index ef8d9d558fc..4fb5b2bf234 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -96,11 +96,6 @@ static struct pci_device_id virtio_pci_id_table[] = { | |||
| 96 | 96 | ||
| 97 | MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); | 97 | MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); |
| 98 | 98 | ||
| 99 | /* A PCI device has it's own struct device and so does a virtio device so | ||
| 100 | * we create a place for the virtio devices to show up in sysfs. I think it | ||
| 101 | * would make more sense for virtio to not insist on having it's own device. */ | ||
| 102 | static struct device *virtio_pci_root; | ||
| 103 | |||
| 104 | /* Convert a generic virtio device to our structure */ | 99 | /* Convert a generic virtio device to our structure */ |
| 105 | static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) | 100 | static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) |
| 106 | { | 101 | { |
| @@ -629,7 +624,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, | |||
| 629 | if (vp_dev == NULL) | 624 | if (vp_dev == NULL) |
| 630 | return -ENOMEM; | 625 | return -ENOMEM; |
| 631 | 626 | ||
| 632 | vp_dev->vdev.dev.parent = virtio_pci_root; | 627 | vp_dev->vdev.dev.parent = &pci_dev->dev; |
| 633 | vp_dev->vdev.dev.release = virtio_pci_release_dev; | 628 | vp_dev->vdev.dev.release = virtio_pci_release_dev; |
| 634 | vp_dev->vdev.config = &virtio_pci_config_ops; | 629 | vp_dev->vdev.config = &virtio_pci_config_ops; |
| 635 | vp_dev->pci_dev = pci_dev; | 630 | vp_dev->pci_dev = pci_dev; |
| @@ -717,17 +712,7 @@ static struct pci_driver virtio_pci_driver = { | |||
| 717 | 712 | ||
| 718 | static int __init virtio_pci_init(void) | 713 | static int __init virtio_pci_init(void) |
| 719 | { | 714 | { |
| 720 | int err; | 715 | return pci_register_driver(&virtio_pci_driver); |
| 721 | |||
| 722 | virtio_pci_root = root_device_register("virtio-pci"); | ||
| 723 | if (IS_ERR(virtio_pci_root)) | ||
| 724 | return PTR_ERR(virtio_pci_root); | ||
| 725 | |||
| 726 | err = pci_register_driver(&virtio_pci_driver); | ||
| 727 | if (err) | ||
| 728 | root_device_unregister(virtio_pci_root); | ||
| 729 | |||
| 730 | return err; | ||
| 731 | } | 716 | } |
| 732 | 717 | ||
| 733 | module_init(virtio_pci_init); | 718 | module_init(virtio_pci_init); |
| @@ -735,7 +720,6 @@ module_init(virtio_pci_init); | |||
| 735 | static void __exit virtio_pci_exit(void) | 720 | static void __exit virtio_pci_exit(void) |
| 736 | { | 721 | { |
| 737 | pci_unregister_driver(&virtio_pci_driver); | 722 | pci_unregister_driver(&virtio_pci_driver); |
| 738 | root_device_unregister(virtio_pci_root); | ||
| 739 | } | 723 | } |
| 740 | 724 | ||
| 741 | module_exit(virtio_pci_exit); | 725 | module_exit(virtio_pci_exit); |
