diff options
-rw-r--r-- | Documentation/lguest/lguest.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index dc73bc54cc4e..f64b85bcd6d4 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> |
@@ -1872,6 +1875,8 @@ static struct option opts[] = { | |||
1872 | { "block", 1, NULL, 'b' }, | 1875 | { "block", 1, NULL, 'b' }, |
1873 | { "rng", 0, NULL, 'r' }, | 1876 | { "rng", 0, NULL, 'r' }, |
1874 | { "initrd", 1, NULL, 'i' }, | 1877 | { "initrd", 1, NULL, 'i' }, |
1878 | { "username", 1, NULL, 'u' }, | ||
1879 | { "chroot", 1, NULL, 'c' }, | ||
1875 | { NULL }, | 1880 | { NULL }, |
1876 | }; | 1881 | }; |
1877 | static void usage(void) | 1882 | static void usage(void) |
@@ -1894,6 +1899,12 @@ int main(int argc, char *argv[]) | |||
1894 | /* If they specify an initrd file to load. */ | 1899 | /* If they specify an initrd file to load. */ |
1895 | const char *initrd_name = NULL; | 1900 | const char *initrd_name = NULL; |
1896 | 1901 | ||
1902 | /* Password structure for initgroups/setres[gu]id */ | ||
1903 | struct passwd *user_details = NULL; | ||
1904 | |||
1905 | /* Directory to chroot to */ | ||
1906 | char *chroot_path = NULL; | ||
1907 | |||
1897 | /* Save the args: we "reboot" by execing ourselves again. */ | 1908 | /* Save the args: we "reboot" by execing ourselves again. */ |
1898 | main_args = argv; | 1909 | main_args = argv; |
1899 | 1910 | ||
@@ -1950,6 +1961,14 @@ int main(int argc, char *argv[]) | |||
1950 | case 'i': | 1961 | case 'i': |
1951 | initrd_name = optarg; | 1962 | initrd_name = optarg; |
1952 | break; | 1963 | break; |
1964 | case 'u': | ||
1965 | user_details = getpwnam(optarg); | ||
1966 | if (!user_details) | ||
1967 | err(1, "getpwnam failed, incorrect username?"); | ||
1968 | break; | ||
1969 | case 'c': | ||
1970 | chroot_path = optarg; | ||
1971 | break; | ||
1953 | default: | 1972 | default: |
1954 | warnx("Unknown argument %s", argv[optind]); | 1973 | warnx("Unknown argument %s", argv[optind]); |
1955 | usage(); | 1974 | usage(); |
@@ -2021,6 +2040,37 @@ int main(int argc, char *argv[]) | |||
2021 | /* If we exit via err(), this kills all the threads, restores tty. */ | 2040 | /* If we exit via err(), this kills all the threads, restores tty. */ |
2022 | atexit(cleanup_devices); | 2041 | atexit(cleanup_devices); |
2023 | 2042 | ||
2043 | /* If requested, chroot to a directory */ | ||
2044 | if (chroot_path) { | ||
2045 | if (chroot(chroot_path) != 0) | ||
2046 | err(1, "chroot(\"%s\") failed", chroot_path); | ||
2047 | |||
2048 | if (chdir("/") != 0) | ||
2049 | err(1, "chdir(\"/\") failed"); | ||
2050 | |||
2051 | verbose("chroot done\n"); | ||
2052 | } | ||
2053 | |||
2054 | /* If requested, drop privileges */ | ||
2055 | if (user_details) { | ||
2056 | uid_t u; | ||
2057 | gid_t g; | ||
2058 | |||
2059 | u = user_details->pw_uid; | ||
2060 | g = user_details->pw_gid; | ||
2061 | |||
2062 | if (initgroups(user_details->pw_name, g) != 0) | ||
2063 | err(1, "initgroups failed"); | ||
2064 | |||
2065 | if (setresgid(g, g, g) != 0) | ||
2066 | err(1, "setresgid failed"); | ||
2067 | |||
2068 | if (setresuid(u, u, u) != 0) | ||
2069 | err(1, "setresuid failed"); | ||
2070 | |||
2071 | verbose("Dropping privileges completed\n"); | ||
2072 | } | ||
2073 | |||
2024 | /* Finally, run the Guest. This doesn't return. */ | 2074 | /* Finally, run the Guest. This doesn't return. */ |
2025 | run_guest(); | 2075 | run_guest(); |
2026 | } | 2076 | } |