commit 9848adf57ce712c941dd41a6bf74a09d4b7e3555 Author: Eric Sesterhenn <eric.sesterh...@lsexperts.de> Date: Fri Jul 11 03:56:08 2014 -0500
Implement chrooting for ovsdb-server This adds the command line options --chroot-dir and --chroot-user to ovsdb-server, which allows to put the process into a chroot. Signed-off-by: Eric Sesterhenn <eric.sesterh...@lsexperts.de> diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c index 89363c6..7043702 100644 --- a/ovsdb/ovsdb-server.c +++ b/ovsdb/ovsdb-server.c @@ -21,6 +21,13 @@ #include <signal.h> #include <sys/stat.h> #include <unistd.h> +#ifndef WIN32 +#include <sys/types.h> +#include <sys/wait.h> +#include <pwd.h> +#include <sys/resource.h> +#include <sys/prctl.h> +#endif #include "column.h" #include "command-line.h" @@ -28,6 +35,7 @@ #include "dirs.h" #include "dummy.h" #include "dynamic-string.h" +#include "entropy.h" #include "fatal-signal.h" #include "file.h" #include "hash.h" @@ -97,7 +105,8 @@ static void close_db(struct db *db); static void parse_options(int *argc, char **argvp[], struct sset *remotes, char **unixctl_pathp, - char **run_command); + char **run_command, + char **chroot_dir, char **chroot_user); static void usage(void) NO_RETURN; static char *reconfigure_remotes(struct ovsdb_jsonrpc_server *, @@ -119,7 +128,7 @@ static void load_config(FILE *config_file, struct sset *remotes, static void main_loop(struct ovsdb_jsonrpc_server *jsonrpc, struct shash *all_dbs, struct unixctl_server *unixctl, struct sset *remotes, - struct process *run_process, bool *exiting) + struct process *run_process, bool *exiting, bool chroot) { char *remotes_error, *ssl_error; struct shash_node *node; @@ -189,6 +198,11 @@ main_loop(struct ovsdb_jsonrpc_server *jsonrpc, struct shash *all_dbs, if (should_service_stop()) { *exiting = true; } +#ifndef WIN32 + if (chroot && (getppid() == 1)) { + *exiting = true; + } +#endif } } @@ -198,6 +212,8 @@ main(int argc, char *argv[]) { char *unixctl_path = NULL; char *run_command = NULL; + char *chroot_dir = NULL; + char *chroot_user = NULL; struct unixctl_server *unixctl; struct ovsdb_jsonrpc_server *jsonrpc; struct sset remotes, db_filenames; @@ -218,7 +234,8 @@ main(int argc, char *argv[]) fatal_ignore_sigpipe(); process_init(); - parse_options(&argc, &argv, &remotes, &unixctl_path, &run_command); + parse_options(&argc, &argv, &remotes, &unixctl_path, &run_command, + &chroot_dir, &chroot_user); /* Create and initialize 'config_tmpfile' as a temporary file to hold * ovsdb-server's most basic configuration, and then save our initial @@ -246,6 +263,10 @@ main(int argc, char *argv[]) save_config__(config_tmpfile, &remotes, &db_filenames); + if (initialize_entropy()) { + ovs_fatal(0, "Unable to initialize entropy source"); + } + daemonize_start(); /* Load the saved config. */ @@ -320,7 +341,64 @@ main(int argc, char *argv[]) unixctl_command_register("ovsdb-server/list-dbs", "", 0, 0, ovsdb_server_list_databases, &all_dbs); - main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting); +#ifndef WIN32 + if (chroot_dir && chroot_user && !run_command) { + pid_t pid; + struct passwd userpwd; + struct passwd* pwdptr = &userpwd; + struct passwd* tempPwdPtr; + char buf[200]; + size_t buflen = sizeof(buf); + + if (getuid() != 0) { + ovs_fatal(0, "can only chroot as root"); + } + + if (getpwnam_r(chroot_user, pwdptr, buf, buflen, &tempPwdPtr) != 0) { + ovs_fatal(0, "user does not exist"); + } + + pid = fork(); + if (pid == 0) { + if (chdir(chroot_dir)){ + ovs_fatal(0, "Cannot change directory"); + } + + if (chroot("./")){ + ovs_fatal(0, "Chroot failed"); + } + + if (setgid(userpwd.pw_gid) != 0) { + ovs_fatal(0, "Unable to drop GID"); + } + if (setuid(userpwd.pw_uid) != 0) { + ovs_fatal(0, "Unable to drop UID"); + } + if (access("/", W_OK) == 0) { + ovs_fatal(0, "We do not want to chroot into a writeable directory"); + } + + main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting, true); + exit(0); + + } else if (pid != -1) { + + /* wait for the forked/chrooted child */ + while ((exiting == false) && !waitpid(pid, NULL, WNOHANG)) { + poll_timer_wait(100); + poll_block(); + }; + + } else { + ovs_fatal(0, "fork failed"); + } + + } else { + main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting, false); + } +#else + main_loop(jsonrpc, &all_dbs, unixctl, &remotes, run_process, &exiting, false); +#endif ovsdb_jsonrpc_server_destroy(jsonrpc); SHASH_FOR_EACH_SAFE(node, next, &all_dbs) { @@ -340,6 +418,8 @@ main(int argc, char *argv[]) } } + cleanup_entropy(); + service_stop(); return 0; } @@ -1216,7 +1296,8 @@ ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED, static void parse_options(int *argcp, char **argvp[], - struct sset *remotes, char **unixctl_pathp, char **run_command) + struct sset *remotes, char **unixctl_pathp, char **run_command, + char **chroot_dir, char **chroot_user) { enum { OPT_REMOTE = UCHAR_MAX + 1, @@ -1225,6 +1306,8 @@ parse_options(int *argcp, char **argvp[], OPT_BOOTSTRAP_CA_CERT, OPT_ENABLE_DUMMY, VLOG_OPTION_ENUMS, + OPT_CHROOTDIR, + OPT_CHROOTUSER, DAEMON_OPTION_ENUMS }; static const struct option long_options[] = { @@ -1232,6 +1315,8 @@ parse_options(int *argcp, char **argvp[], {"unixctl", required_argument, NULL, OPT_UNIXCTL}, #ifndef _WIN32 {"run", required_argument, NULL, OPT_RUN}, + {"chroot_dir", required_argument, NULL, OPT_CHROOTDIR}, + {"chroot_user", required_argument, NULL, OPT_CHROOTUSER}, #endif {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, @@ -1270,6 +1355,12 @@ parse_options(int *argcp, char **argvp[], *run_command = optarg; break; + case OPT_CHROOTDIR: + *chroot_dir = optarg; + + case OPT_CHROOTUSER: + *chroot_user = optarg; + case 'h': usage(); @@ -1330,6 +1421,8 @@ usage(void) vlog_usage(); printf("\nOther options:\n" " --run COMMAND run COMMAND as subprocess then exit\n" + " --chrootdir DIRECTORY chroot into directory\n" + " --chrootuser USER change user to USER after chroot\n" " --unixctl=SOCKET override default control socket name\n" " -h, --help display this help message\n" " -V, --version display version information\n"); -- LSE Leading Security Experts GmbH, Postfach 100121, 64201 Darmstadt Unternehmenssitz: Weiterstadt, Amtsgericht Darmstadt: HRB8649 Geschäftsführer: Oliver Michel, Sven Walther _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev