diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-02-13 01:53:34 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-02-13 01:53:34 -0500 |
commit | c170093d31bd4e3bc51881cc0f123beeca7872c9 (patch) | |
tree | d93cd280d525dd339f33be010c75b7fd0bacd690 /Documentation/lguest/lguest.c | |
parent | 557218e2d662574bc58d840fe116c7fd8d57aed8 (diff) | |
parent | 78bba987bc025a7263248501b453476e77b93331 (diff) |
Merge branch 'devicetree/merge' into spi/merge
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r-- | Documentation/lguest/lguest.c | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index dc73bc54cc4e..d9da7e148538 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 | } |