From: "Daniel P. Berrangé" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
"Daniel P. Berrangé" <berrange@redhat.com>,
libvir-list@redhat.com, "Stefan Weil" <sw@weilnetz.de>,
"Hanna Reitz" <hreitz@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Eric Blake" <eblake@redhat.com>
Subject: [PATCH 4/4] softmmu: move parsing of -runas, -chroot and -daemonize code
Date: Fri, 4 Mar 2022 11:56:57 +0000 [thread overview]
Message-ID: <20220304115657.3177925-5-berrange@redhat.com> (raw)
In-Reply-To: <20220304115657.3177925-1-berrange@redhat.com>
With the future intent to try to move to a fully QAPI driven
configuration system, we want to have any current command
parsing well isolated from logic that applies the resulting
configuration.
We also don't want os-posix.c to contain code that is specific
to the system emulators, as this file is linked to other binaries
too.
To satisfy these goals, we move parsing of the -runas, -chroot and
-daemonize code out of the os-posix.c helper code, and pass the
parsed data into APIs in os-posix.c.
As a side benefit the 'os_daemonize()' function now lives upto to
its name and will always daemonize, instead of using global state
to decide to be a no-op sometimes.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/sysemu/os-posix.h | 4 +-
include/sysemu/os-win32.h | 1 -
os-posix.c | 148 +++++++++++---------------------------
os-win32.c | 9 ---
softmmu/vl.c | 76 ++++++++++++++++++--
5 files changed, 113 insertions(+), 125 deletions(-)
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 2edf33658a..390f3f8396 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -46,7 +46,9 @@ void os_set_line_buffering(void);
void os_set_proc_name(const char *s);
void os_setup_signal_handling(void);
void os_daemonize(void);
-void os_setup_post(void);
+void os_setup_post(const char *chroot_dir,
+ uid_t uid, gid_t gid,
+ const char *username);
int os_mlock(void);
#define closesocket(s) close(s)
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index 43f569b5c2..4879f8731d 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -61,7 +61,6 @@ struct tm *localtime_r(const time_t *timep, struct tm *result);
static inline void os_setup_signal_handling(void) {}
static inline void os_daemonize(void) {}
-static inline void os_setup_post(void) {}
void os_set_line_buffering(void);
static inline void os_set_proc_name(const char *dummy) {}
diff --git a/os-posix.c b/os-posix.c
index 30da1a1491..f598a52a4f 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -42,11 +42,6 @@
#include <sys/prctl.h>
#endif
-static char *user_name;
-static uid_t user_uid = (uid_t)-1;
-static gid_t user_gid = (gid_t)-1;
-
-static const char *chroot_dir;
static int daemonize;
static int daemon_pipe;
@@ -96,69 +91,6 @@ void os_set_proc_name(const char *s)
}
-static bool os_parse_runas_uid_gid(const char *optarg,
- uid_t *runas_uid, gid_t *runas_gid)
-{
- unsigned long lv;
- const char *ep;
- uid_t got_uid;
- gid_t got_gid;
- int rc;
-
- rc = qemu_strtoul(optarg, &ep, 0, &lv);
- got_uid = lv; /* overflow here is ID in C99 */
- if (rc || *ep != ':' || got_uid != lv || got_uid == (uid_t)-1) {
- return false;
- }
-
- rc = qemu_strtoul(ep + 1, 0, 0, &lv);
- got_gid = lv; /* overflow here is ID in C99 */
- if (rc || got_gid != lv || got_gid == (gid_t)-1) {
- return false;
- }
-
- *runas_uid = got_uid;
- *runas_gid = got_gid;
- return true;
-}
-
-/*
- * Parse OS specific command line options.
- * return 0 if option handled, -1 otherwise
- */
-int os_parse_cmd_args(int index, const char *optarg)
-{
- struct passwd *user_pwd;
-
- switch (index) {
- case QEMU_OPTION_runas:
- user_pwd = getpwnam(optarg);
- if (user_pwd) {
- user_uid = user_pwd->pw_uid;
- user_gid = user_pwd->pw_gid;
- user_name = g_strdup(user_pwd->pw_name);
- } else if (!os_parse_runas_uid_gid(optarg,
- &user_uid,
- &user_gid)) {
- error_report("User \"%s\" doesn't exist"
- " (and is not <uid>:<gid>)",
- optarg);
- exit(1);
- }
- break;
- case QEMU_OPTION_chroot:
- chroot_dir = optarg;
- break;
- case QEMU_OPTION_daemonize:
- daemonize = 1;
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
static void change_process_uid(uid_t uid, gid_t gid, const char *name)
{
if (setgid(gid) < 0) {
@@ -202,54 +134,56 @@ static void change_root(const char *root)
void os_daemonize(void)
{
- if (daemonize) {
- pid_t pid;
- int fds[2];
+ pid_t pid;
+ int fds[2];
- if (pipe(fds) == -1) {
- exit(1);
- }
+ if (pipe(fds) == -1) {
+ exit(1);
+ }
- pid = fork();
- if (pid > 0) {
- uint8_t status;
- ssize_t len;
+ pid = fork();
+ if (pid > 0) {
+ uint8_t status;
+ ssize_t len;
- close(fds[1]);
+ close(fds[1]);
- do {
- len = read(fds[0], &status, 1);
- } while (len < 0 && errno == EINTR);
+ do {
+ len = read(fds[0], &status, 1);
+ } while (len < 0 && errno == EINTR);
- /* only exit successfully if our child actually wrote
- * a one-byte zero to our pipe, upon successful init */
- exit(len == 1 && status == 0 ? 0 : 1);
+ /* only exit successfully if our child actually wrote
+ * a one-byte zero to our pipe, upon successful init */
+ exit(len == 1 && status == 0 ? 0 : 1);
- } else if (pid < 0) {
- exit(1);
- }
+ } else if (pid < 0) {
+ exit(1);
+ }
- close(fds[0]);
- daemon_pipe = fds[1];
- qemu_set_cloexec(daemon_pipe);
+ close(fds[0]);
+ daemon_pipe = fds[1];
+ qemu_set_cloexec(daemon_pipe);
- setsid();
+ setsid();
- pid = fork();
- if (pid > 0) {
+ pid = fork();
+ if (pid > 0) {
exit(0);
- } else if (pid < 0) {
- exit(1);
- }
- umask(027);
-
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
+ } else if (pid < 0) {
+ exit(1);
}
+ umask(027);
+
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+
+ daemonize = true;
}
-void os_setup_post(void)
+void os_setup_post(const char *root_dir,
+ uid_t runas_uid, gid_t runas_gid,
+ const char *runas_name)
{
int fd = 0;
@@ -264,11 +198,11 @@ void os_setup_post(void)
}
}
- if (chroot_dir) {
- change_root(chroot_dir);
+ if (root_dir != NULL) {
+ change_root(root_dir);
}
- if (user_uid != -1 && user_gid != -1) {
- change_process_uid(user_uid, user_gid, user_name);
+ if (runas_uid != -1 && runas_gid != -1) {
+ change_process_uid(runas_uid, runas_gid, runas_name);
}
if (daemonize) {
diff --git a/os-win32.c b/os-win32.c
index e31c921983..6f21b57841 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -61,12 +61,3 @@ void os_set_line_buffering(void)
setbuf(stdout, NULL);
setbuf(stderr, NULL);
}
-
-/*
- * Parse OS specific command line options.
- * return 0 if option handled, -1 otherwise
- */
-int os_parse_cmd_args(int index, const char *optarg)
-{
- return -1;
-}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 1fe028800f..cdf27b6027 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2602,11 +2602,13 @@ static void qemu_process_help_options(void)
}
}
-static void qemu_maybe_daemonize(const char *pid_file)
+static void qemu_maybe_daemonize(bool daemonize, const char *pid_file)
{
Error *err = NULL;
- os_daemonize();
+ if (daemonize) {
+ os_daemonize();
+ }
rcu_disable_atfork();
if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
@@ -2768,6 +2770,35 @@ void qmp_x_exit_preconfig(Error **errp)
}
}
+#ifndef WIN32
+static bool os_parse_runas_uid_gid(const char *optarg,
+ uid_t *runas_uid,
+ gid_t *runas_gid)
+{
+ unsigned long lv;
+ const char *ep;
+ uid_t got_uid;
+ gid_t got_gid;
+ int rc;
+
+ rc = qemu_strtoul(optarg, &ep, 0, &lv);
+ got_uid = lv; /* overflow here is ID in C99 */
+ if (rc || *ep != ':' || got_uid != lv || got_uid == (uid_t)-1) {
+ return false;
+ }
+
+ rc = qemu_strtoul(ep + 1, 0, 0, &lv);
+ got_gid = lv; /* overflow here is ID in C99 */
+ if (rc || got_gid != lv || got_gid == (gid_t)-1) {
+ return false;
+ }
+
+ *runas_gid = got_gid;
+ *runas_uid = got_uid;
+ return true;
+}
+#endif /* !WIN32 */
+
void qemu_init(int argc, char **argv, char **envp)
{
QemuOpts *opts;
@@ -2778,6 +2809,14 @@ void qemu_init(int argc, char **argv, char **envp)
MachineClass *machine_class;
bool userconfig = true;
FILE *vmstate_dump_file = NULL;
+ bool daemonize = false;
+#ifndef WIN32
+ struct passwd *pwd;
+ uid_t runas_uid = -1;
+ gid_t runas_gid = -1;
+ g_autofree char *runas_name = NULL;
+ const char *chroot_dir = NULL;
+#endif /* !WIN32 */
qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts);
@@ -3659,11 +3698,32 @@ void qemu_init(int argc, char **argv, char **envp)
case QEMU_OPTION_nouserconfig:
/* Nothing to be parsed here. Especially, do not error out below. */
break;
- default:
- if (os_parse_cmd_args(popt->index, optarg)) {
- error_report("Option not supported in this build");
+#ifndef WIN32
+ case QEMU_OPTION_runas:
+ pwd = getpwnam(optarg);
+ if (pwd) {
+ runas_uid = pwd->pw_uid;
+ runas_gid = pwd->pw_gid;
+ runas_name = g_strdup(pwd->pw_name);
+ } else if (!os_parse_runas_uid_gid(optarg,
+ &runas_uid,
+ &runas_gid)) {
+ error_report("User \"%s\" doesn't exist"
+ " (and is not <uid>:<gid>)",
+ optarg);
exit(1);
}
+ break;
+ case QEMU_OPTION_chroot:
+ chroot_dir = optarg;
+ break;
+ case QEMU_OPTION_daemonize:
+ daemonize = 1;
+ break;
+#endif /* !WIN32 */
+ default:
+ error_report("Option not supported in this build");
+ exit(1);
}
}
}
@@ -3683,7 +3743,7 @@ void qemu_init(int argc, char **argv, char **envp)
qemu_process_early_options();
qemu_process_help_options();
- qemu_maybe_daemonize(pid_file);
+ qemu_maybe_daemonize(daemonize, pid_file);
/*
* The trace backend must be initialized after daemonizing.
@@ -3778,6 +3838,8 @@ void qemu_init(int argc, char **argv, char **envp)
}
qemu_init_displays();
accel_setup_post(current_machine);
- os_setup_post();
+#ifndef WIN32
+ os_setup_post(chroot_dir, runas_uid, runas_gid, runas_name);
+#endif /* !WIN32 */
resume_mux_open();
}
--
2.34.1
next prev parent reply other threads:[~2022-03-04 12:01 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-04 11:56 [PATCH 0/4] softmmu: move and refactor -runas, -chroot and -daemonize Daniel P. Berrangé
2022-03-04 11:56 ` [PATCH 1/4] softmmu: remove deprecated --enable-fips option Daniel P. Berrangé
2022-03-04 13:55 ` Philippe Mathieu-Daudé
2022-03-04 17:14 ` Eric Blake
2022-03-04 11:56 ` [PATCH 2/4] os-posix: refactor code handling the -runas argument Daniel P. Berrangé
2022-03-04 17:19 ` Eric Blake
2022-03-04 11:56 ` [PATCH 3/4] os-posix: refactor code handling the -chroot argument Daniel P. Berrangé
2022-03-04 13:54 ` Philippe Mathieu-Daudé
2022-03-04 11:56 ` Daniel P. Berrangé [this message]
2022-03-04 14:54 ` [PATCH 4/4] softmmu: move parsing of -runas, -chroot and -daemonize code Daniel P. Berrangé
2022-03-04 17:21 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220304115657.3177925-5-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=eblake@redhat.com \
--cc=hreitz@redhat.com \
--cc=kraxel@redhat.com \
--cc=kwolf@redhat.com \
--cc=libvir-list@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=sw@weilnetz.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.