[ovs-dev] [v2 2/3] lib: Add --user for daemon
Andy Zhou
azhou at nicira.com
Tue Sep 8 23:17:37 UTC 2015
Allow daemon running as root to accept --user option, that accepts
"user:group" string as input. Performs sanity check on the input,
and store the converted uid and gid.
daemon_become_new_user() needs to be called to make the actual
switch.
Signed-off-by: Andy Zhou <azhou at nicira.com>
---
v2 : use sysconf() to get proper buffer size. not hard code it
---
lib/daemon-unix.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/daemon.h | 27 ++++++++++++++-----
2 files changed, 97 insertions(+), 7 deletions(-)
diff --git a/lib/daemon-unix.c b/lib/daemon-unix.c
index 4a2e7b4..ee1761a 100644
--- a/lib/daemon-unix.c
+++ b/lib/daemon-unix.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
+#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -693,6 +694,82 @@ should_service_stop(void)
return false;
}
+void daemon_set_new_user(const char *user_spec)
+{
+ char *pos = strchr(user_spec, ':');
+ int bufsize;
+
+ uid = getuid();
+ gid = getgid();
+
+ if (gid || uid) {
+ VLOG_FATAL("%s: only root can use --user option", pidfile);
+ }
+
+ if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
+ VLOG_FATAL("%s: Invalid --user option %s (Unknown system password "
+ "configuration)", pidfile, user_spec);
+ }
+
+ user_spec += strspn(user_spec, " \t\r\n");
+ int len = pos ? pos - user_spec : strlen(user_spec);
+ struct passwd pwd, *res;
+ char buf[bufsize];
+
+ if (len) {
+ user = xzalloc(len + 1);
+ strncpy(user, user_spec, len);
+
+ if (getpwnam_r(user, &pwd, buf, bufsize, &res)) {
+ VLOG_FATAL("%s: Invalid --user option %s (no such user %s)",
+ pidfile, user_spec, user);
+ }
+ } else {
+ /* User is not specified, use current user. */
+ if (getpwuid_r(uid, &pwd, buf, bufsize, &res)) {
+ VLOG_FATAL("%s: Invalid --user option %s (failed to lookup "
+ "current user with uid %d)", pidfile, user_spec, uid);
+ }
+ user = strdup(pwd.pw_name);
+ }
+
+ uid = pwd.pw_uid;
+ gid = pwd.pw_gid;
+
+ if (pos) {
+ char *grpstr = pos + 1;
+ grpstr += strspn(grpstr, " \t\r\n");
+
+ if (*grpstr) {
+ struct group grp, *res;
+
+ if(getgrnam_r(grpstr, &grp, buf, bufsize, &res)) {
+ VLOG_FATAL("%s: Invalid --user option %s (unknown group %s)",
+ pidfile, user_spec, grpstr);
+ }
+
+ if(gid != grp.gr_gid) {
+ char **mem;
+
+ for(mem = grp.gr_mem; *mem; ++mem) {
+ if (!strcmp(*mem, user)) {
+ break;
+ }
+ }
+
+ if (!*mem) {
+ VLOG_FATAL("%s: Invalid --user option %s (user %s is "
+ "not in group %s)", pidfile, user_spec,
+ user, grpstr);
+ }
+ gid = grp.gr_gid;
+ }
+ }
+ }
+
+ switch_to_new_user = true;
+}
+
void
daemon_become_new_user(void)
{
diff --git a/lib/daemon.h b/lib/daemon.h
index ccf30f8..b00c698 100644
--- a/lib/daemon.h
+++ b/lib/daemon.h
@@ -42,14 +42,16 @@
OPT_NO_CHDIR, \
OPT_OVERWRITE_PIDFILE, \
OPT_PIDFILE, \
- OPT_MONITOR
+ OPT_MONITOR, \
+ OPT_USER_GROUP
-#define DAEMON_LONG_OPTIONS \
- {"detach", no_argument, NULL, OPT_DETACH}, \
- {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \
- {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \
+#define DAEMON_LONG_OPTIONS \
+ {"detach", no_argument, NULL, OPT_DETACH}, \
+ {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \
+ {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \
{"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \
- {"monitor", no_argument, NULL, OPT_MONITOR}
+ {"monitor", no_argument, NULL, OPT_MONITOR}, \
+ {"user", required_argument, NULL, OPT_USER_GROUP}
#define DAEMON_OPTION_HANDLERS \
case OPT_DETACH: \
@@ -70,6 +72,10 @@
\
case OPT_MONITOR: \
daemon_set_monitor(); \
+ break; \
+ \
+ case OPT_USER_GROUP: \
+ daemon_set_new_user(optarg); \
break;
void set_detach(void);
@@ -77,6 +83,7 @@ void daemon_set_monitor(void);
void set_no_chdir(void);
void ignore_existing_pidfile(void);
void daemon_become_new_user(void);
+void daemon_set_new_user(const char *);
pid_t read_pidfile(const char *name);
#else
#define DAEMON_OPTION_ENUMS \
@@ -85,7 +92,7 @@ pid_t read_pidfile(const char *name);
OPT_PIDFILE, \
OPT_PIPE_HANDLE, \
OPT_SERVICE, \
- OPT_SERVICE_MONITOR
+ OPT_SERVICE_MONITOR \
#define DAEMON_LONG_OPTIONS \
{"detach", no_argument, NULL, OPT_DETACH}, \
@@ -120,6 +127,12 @@ void control_handler(DWORD request);
void set_pipe_handle(const char *pipe_handle);
static inline void
+daemon_set_new_user(const char *)
+{
+ /* Not implemented. */
+}
+
+static inline void
daemon_become_new_user(void)
{
/* Not implemented. */
--
1.9.1
More information about the dev
mailing list